[source] ag71xx: add support for port mirroring

LEDE Commits lede-commits at lists.infradead.org
Thu Jul 20 23:10:58 PDT 2017


jow pushed a commit to source.git, branch master:
https://git.lede-project.org/4c1ce83548abacfeabb75c6e28e8eb450ef10951

commit 4c1ce83548abacfeabb75c6e28e8eb450ef10951
Author: Milan Krstić <milan.krstic at gmail.com>
AuthorDate: Wed Apr 26 21:52:44 2017 +0200

    ag71xx: add support for port mirroring
    
    This exposes hardware port mirroring in ag71xx driver (e.g. TL-WR841ND) via
    swconfig API.
    
    Signed-off-by: Milan Krstić <milan.krstic at gmail.com>
---
 .../net/ethernet/atheros/ag71xx/ag71xx_ar7240.c    | 153 +++++++++++++++++++++
 1 file changed, 153 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 e457acb..3f2f64e 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,33 @@ 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[] = {



More information about the lede-commits mailing list