[OpenWrt-Devel] [PATCH] [ar71xx] ag71xx: add support for port mirroring

Milan Krstić milan.krstic at gmail.com
Wed Apr 26 15:52:44 EDT 2017


This exposes hardware port mirroring in ag71xx driver (e.g. TL-WR841ND) via
swconfig API. It's my first patch ever so any feedback is welcome.

Signed-off-by: Milan Krstic <milan.krstic at gmail.com>
---
 .../net/ethernet/atheros/ag71xx/ag71xx_ar7240.c    | 154
+++++++++++++++++++++
 1 file changed, 154 insertions(+)

diff --git
a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
index c5aed0d..da9c0dd 100644
---
a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
+++
b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
@@ -77,6 +77,7 @@

 #define AR7240_REG_CPU_PORT 0x78
 #define AR7240_MIRROR_PORT_S 4
+#define AR7240_MIRROR_PORT_M BITM(4)
 #define AR7240_CPU_PORT_EN BIT(8)

 #define AR7240_REG_MIB_FUNCTION0 0x80
@@ -1013,6 +1014,134 @@ ar7240_get_port_stats(struct switch_dev *dev, int
port,
  return 0;
 }

+static int
+ar7240_set_mirror_monitor_port(struct switch_dev *dev,
+       const struct switch_attr *attr,
+       struct switch_val *val)
+{
+ struct ar7240sw *as = sw_to_ar7240(dev);
+ struct mii_bus *mii = as->mii_bus;
+
+ int port = val->value.i;
+
+ if (port > 15)
+ return -EINVAL;
+
+ ar7240sw_reg_rmw(mii, AR7240_REG_CPU_PORT,
+ AR7240_MIRROR_PORT_M << AR7240_MIRROR_PORT_S,
+ port << AR7240_MIRROR_PORT_S);
+
+ return 0;
+}
+
+static int
+ar7240_get_mirror_monitor_port(struct switch_dev *dev,
+       const struct switch_attr *attr,
+       struct switch_val *val)
+{
+ struct ar7240sw *as = sw_to_ar7240(dev);
+ struct mii_bus *mii = as->mii_bus;
+
+ u32 ret;
+
+ ret = ar7240sw_reg_read(mii, AR7240_REG_CPU_PORT);
+ val->value.i = (ret >> AR7240_MIRROR_PORT_S) & AR7240_MIRROR_PORT_M;
+
+ return 0;
+}
+
+static int
+ar7240_set_mirror_rx(struct switch_dev *dev, const struct switch_attr
*attr,
+     struct switch_val *val)
+{
+ struct ar7240sw *as = sw_to_ar7240(dev);
+ struct mii_bus *mii = as->mii_bus;
+
+ int port = val->port_vlan;
+
+ if (port >= dev->ports)
+ return -EINVAL;
+
+ if (val && val->value.i == 1)
+ ar7240sw_reg_set(mii, AR7240_REG_PORT_CTRL(port),
+ AR7240_PORT_CTRL_MIRROR_RX);
+ else
+ ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(port),
+ AR7240_PORT_CTRL_MIRROR_RX, 0);
+
+ return 0;
+}
+
+static int
+ar7240_get_mirror_rx(struct switch_dev *dev, const struct switch_attr
*attr,
+     struct switch_val *val)
+{
+ struct ar7240sw *as = sw_to_ar7240(dev);
+ struct mii_bus *mii = as->mii_bus;
+
+ u32 ctrl;
+
+ int port = val->port_vlan;
+
+ if (port >= dev->ports)
+ return -EINVAL;
+
+ ctrl = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port));
+
+ if ((ctrl & AR7240_PORT_CTRL_MIRROR_RX) == AR7240_PORT_CTRL_MIRROR_RX)
+ val->value.i = 1;
+ else
+ val->value.i = 0;
+
+ return 0;
+}
+
+static int
+ar7240_set_mirror_tx(struct switch_dev *dev, const struct switch_attr
*attr,
+     struct switch_val *val)
+{
+ struct ar7240sw *as = sw_to_ar7240(dev);
+ struct mii_bus *mii = as->mii_bus;
+
+ int port = val->port_vlan;
+
+ if (port >= dev->ports)
+ return -EINVAL;
+
+ if (val && val->value.i == 1)
+ ar7240sw_reg_set(mii, AR7240_REG_PORT_CTRL(port),
+ AR7240_PORT_CTRL_MIRROR_TX);
+ else
+ ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(port),
+ AR7240_PORT_CTRL_MIRROR_TX, 0);
+
+ return 0;
+}
+
+static int
+ar7240_get_mirror_tx(struct switch_dev *dev, const struct switch_attr
*attr,
+     struct switch_val *val)
+{
+ struct ar7240sw *as = sw_to_ar7240(dev);
+ struct mii_bus *mii = as->mii_bus;
+
+ u32 ctrl;
+
+ int port = val->port_vlan;
+
+ if (port >= dev->ports)
+ return -EINVAL;
+
+ ctrl = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port));
+
+ if ((ctrl & AR7240_PORT_CTRL_MIRROR_TX) == AR7240_PORT_CTRL_MIRROR_TX)
+ val->value.i = 1;
+ else
+ val->value.i = 0;
+
+ return 0;
+}
+
 static struct switch_attr ar7240_globals[] = {
  {
  .type = SWITCH_TYPE_INT,
@@ -1022,9 +1151,34 @@ static struct switch_attr ar7240_globals[] = {
  .get = ar7240_get_vlan,
  .max = 1
  },
+ {
+ .type = SWITCH_TYPE_INT,
+ .name = "mirror_monitor_port",
+ .description = "Mirror monitor port",
+ .set = ar7240_set_mirror_monitor_port,
+ .get = ar7240_get_mirror_monitor_port,
+ .max = 15
+ },
 };

 static struct switch_attr ar7240_port[] = {
+ {
+ .type = SWITCH_TYPE_INT,
+ .name = "enable_mirror_rx",
+ .description = "Enable mirroring of RX packets",
+ .set = ar7240_set_mirror_rx,
+ .get = ar7240_get_mirror_rx,
+ .max = 1
+ },
+ {
+
+ .type = SWITCH_TYPE_INT,
+ .name = "enable_mirror_tx",
+ .description = "Enable mirroring of TX packets",
+ .set = ar7240_set_mirror_tx,
+ .get = ar7240_get_mirror_tx,
+ .max = 1
+ },
 };

 static struct switch_attr ar7240_vlan[] = {
-- 
1.8.3.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/openwrt-devel/attachments/20170426/d665c570/attachment.htm>
-------------- next part --------------
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list