net: dsa: ksz9477: port mirror sniffing limited to one port

This patch limits the sniffing to only one port during the mirror add.
And during the mirror_del it checks for all the ports using the sniff,
if and only if no other ports are referring, sniffing is disabled.
The code is updated based on the review comments of LAN937x port mirror
patch.

Link: https://patchwork.kernel.org/project/netdevbpf/patch/20210422094257.1641396-8-prasanna.vengateshan@microchip.com/
Fixes: b987e98e50 ("dsa: add DSA switch driver for Microchip KSZ9477")
Signed-off-by: Prasanna Vengateshan <prasanna.vengateshan@microchip.com>
Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Link: https://lore.kernel.org/r/20220428070709.7094-1-arun.ramadoss@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Arun Ramadoss 2022-04-28 12:37:09 +05:30 committed by Jakub Kicinski
parent 52b2abef45
commit fee34dd199

View File

@ -1021,14 +1021,32 @@ static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
bool ingress, struct netlink_ext_ack *extack) bool ingress, struct netlink_ext_ack *extack)
{ {
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
u8 data;
int p;
/* Limit to one sniffer port
* Check if any of the port is already set for sniffing
* If yes, instruct the user to remove the previous entry & exit
*/
for (p = 0; p < dev->port_cnt; p++) {
/* Skip the current sniffing port */
if (p == mirror->to_local_port)
continue;
ksz_pread8(dev, p, P_MIRROR_CTRL, &data);
if (data & PORT_MIRROR_SNIFFER) {
NL_SET_ERR_MSG_MOD(extack,
"Sniffer port is already configured, delete existing rules & retry");
return -EBUSY;
}
}
if (ingress) if (ingress)
ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true);
else else
ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true);
ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false);
/* configure mirror port */ /* configure mirror port */
ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
PORT_MIRROR_SNIFFER, true); PORT_MIRROR_SNIFFER, true);
@ -1042,16 +1060,28 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror) struct dsa_mall_mirror_tc_entry *mirror)
{ {
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
bool in_use = false;
u8 data; u8 data;
int p;
if (mirror->ingress) if (mirror->ingress)
ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false);
else else
ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false);
ksz_pread8(dev, port, P_MIRROR_CTRL, &data);
if (!(data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) /* Check if any of the port is still referring to sniffer port */
for (p = 0; p < dev->port_cnt; p++) {
ksz_pread8(dev, p, P_MIRROR_CTRL, &data);
if ((data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) {
in_use = true;
break;
}
}
/* delete sniffing if there are no other mirroring rules */
if (!in_use)
ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
PORT_MIRROR_SNIFFER, false); PORT_MIRROR_SNIFFER, false);
} }