public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH net-next 0/6] Mirroring to DSA CPU port
@ 2024-09-13 15:29 Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 1/6] net: sched: propagate "skip_sw" flag to offload for flower and matchall Vladimir Oltean
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

Greetings,

Users of the NXP LS1028A SoC (drivers/net/dsa/ocelot L2 switch inside)
have requested to mirror packets from the ingress of a switch port to
software. Both port-based and flow-based mirroring is required.

The simplest way I could come up with was to set up tc mirred actions
towards a dummy net_device, and make the offloading of that be accepted
by the driver. Currently, the pattern in drivers is to reject mirred
towards ports they don't know about, but I'm now permitting that,
precisely by mirroring "to the CPU". I am unsure if there are other,
perhaps better ways of doing this.

Vladimir Oltean (6):
  net: sched: propagate "skip_sw" flag to offload for flower and
    matchall
  net: dsa: clean up dsa_user_add_cls_matchall()
  net: dsa: add more extack messages in
    dsa_user_add_cls_matchall_mirred()
  net: dsa: refuse cross-chip mirroring operations
  net: dsa: allow matchall mirroring rules towards the CPU
  net: mscc: ocelot: allow tc-flower mirred action towards foreign
    interfaces

 drivers/net/ethernet/mscc/ocelot_flower.c | 58 ++++++++++++++----
 include/net/flow_offload.h                |  1 +
 include/net/pkt_cls.h                     |  1 +
 net/dsa/user.c                            | 72 ++++++++++++++++++-----
 net/sched/cls_flower.c                    |  1 +
 net/sched/cls_matchall.c                  |  1 +
 6 files changed, 107 insertions(+), 27 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH net-next 1/6] net: sched: propagate "skip_sw" flag to offload for flower and matchall
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
@ 2024-09-13 15:29 ` Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 2/6] net: dsa: clean up dsa_user_add_cls_matchall() Vladimir Oltean
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

In some cases, an offloaded filter can only do half the work, and the
rest must be handled by software.

For example, redirecting/mirroring from the ingress of a switchdev port
towards a virtual interface like veth/dummy/etc that is completely
foreign to said switchdev port. The most that the switchdev port can do
is to extract the matching packets from its data path and send them to
the CPU. From there on, the software filter runs (a second time) on the
packet and performs the mirred.

It makes sense for switchdev drivers which allow this kind of "half
offloading" to sense the "skip_sw" flag of the filter/action, and deny
attempts from the user to install a filter that does not run in
software, because that simply won't work.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/net/flow_offload.h | 1 +
 include/net/pkt_cls.h      | 1 +
 net/sched/cls_flower.c     | 1 +
 net/sched/cls_matchall.c   | 1 +
 4 files changed, 4 insertions(+)

diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 292cd8f4b762..a2f688dd0447 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -692,6 +692,7 @@ struct flow_cls_offload {
 	struct flow_cls_common_offload common;
 	enum flow_cls_command command;
 	bool use_act_stats;
+	bool skip_sw;
 	unsigned long cookie;
 	struct flow_rule *rule;
 	struct flow_stats stats;
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 4880b3a7aced..7b9f41f33c33 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -782,6 +782,7 @@ struct tc_cls_matchall_offload {
 	struct flow_rule *rule;
 	struct flow_stats stats;
 	bool use_act_stats;
+	bool skip_sw;
 	unsigned long cookie;
 };
 
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index e280c27cb9f9..8f7c60805f85 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -480,6 +480,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
 	cls_flower.rule->match.mask = &f->mask->key;
 	cls_flower.rule->match.key = &f->mkey;
 	cls_flower.classid = f->res.classid;
+	cls_flower.skip_sw = skip_sw;
 
 	err = tc_setup_offload_action(&cls_flower.rule->action, &f->exts,
 				      cls_flower.common.extack);
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 9f1e62ca508d..9bd598f8a46c 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -98,6 +98,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
 	tc_cls_common_offload_init(&cls_mall.common, tp, head->flags, extack);
 	cls_mall.command = TC_CLSMATCHALL_REPLACE;
 	cls_mall.cookie = cookie;
+	cls_mall.skip_sw = skip_sw;
 
 	err = tc_setup_offload_action(&cls_mall.rule->action, &head->exts,
 				      cls_mall.common.extack);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC PATCH net-next 2/6] net: dsa: clean up dsa_user_add_cls_matchall()
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 1/6] net: sched: propagate "skip_sw" flag to offload for flower and matchall Vladimir Oltean
@ 2024-09-13 15:29 ` Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 3/6] net: dsa: add more extack messages in dsa_user_add_cls_matchall_mirred() Vladimir Oltean
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

The body is a bit hard to read, hard to extend, and has duplicated
conditions.

Clean up the "if (many conditions) else if (many conditions, some
of them repeated)" pattern by:

- Moving the repeated conditions out
- Replacing the repeated tests for the same variable with a switch/case
- Moving the protocol check inside the dsa_user_add_cls_matchall_mirred()
  function call.

This is pure refactoring, no logic has been changed.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/user.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/net/dsa/user.c b/net/dsa/user.c
index 74eda9b30608..143e566e26b9 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -1377,6 +1377,9 @@ dsa_user_add_cls_matchall_mirred(struct net_device *dev,
 	struct dsa_port *to_dp;
 	int err;
 
+	if (cls->common.protocol != htons(ETH_P_ALL))
+		return -EOPNOTSUPP;
+
 	if (!ds->ops->port_mirror_add)
 		return -EOPNOTSUPP;
 
@@ -1481,17 +1484,21 @@ static int dsa_user_add_cls_matchall(struct net_device *dev,
 				     struct tc_cls_matchall_offload *cls,
 				     bool ingress)
 {
-	int err = -EOPNOTSUPP;
+	const struct flow_action *action = &cls->rule->action;
 
-	if (cls->common.protocol == htons(ETH_P_ALL) &&
-	    flow_offload_has_one_action(&cls->rule->action) &&
-	    cls->rule->action.entries[0].id == FLOW_ACTION_MIRRED)
-		err = dsa_user_add_cls_matchall_mirred(dev, cls, ingress);
-	else if (flow_offload_has_one_action(&cls->rule->action) &&
-		 cls->rule->action.entries[0].id == FLOW_ACTION_POLICE)
-		err = dsa_user_add_cls_matchall_police(dev, cls, ingress);
+	if (!flow_offload_has_one_action(action))
+		return -EOPNOTSUPP;
 
-	return err;
+	switch (action->entries[0].id) {
+	case FLOW_ACTION_MIRRED:
+		return dsa_user_add_cls_matchall_mirred(dev, cls, ingress);
+	case FLOW_ACTION_POLICE:
+		return dsa_user_add_cls_matchall_police(dev, cls, ingress);
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
 }
 
 static void dsa_user_del_cls_matchall(struct net_device *dev,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC PATCH net-next 3/6] net: dsa: add more extack messages in dsa_user_add_cls_matchall_mirred()
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 1/6] net: sched: propagate "skip_sw" flag to offload for flower and matchall Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 2/6] net: dsa: clean up dsa_user_add_cls_matchall() Vladimir Oltean
@ 2024-09-13 15:29 ` Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 4/6] net: dsa: refuse cross-chip mirroring operations Vladimir Oltean
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

Do not leave -EOPNOTSUPP errors without an explanation. It is confusing
for the user to figure out what is wrong otherwise.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/user.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/net/dsa/user.c b/net/dsa/user.c
index 143e566e26b9..42ff3415c808 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -1377,11 +1377,17 @@ dsa_user_add_cls_matchall_mirred(struct net_device *dev,
 	struct dsa_port *to_dp;
 	int err;
 
-	if (cls->common.protocol != htons(ETH_P_ALL))
+	if (cls->common.protocol != htons(ETH_P_ALL)) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Can only offload \"protocol all\" matchall filter");
 		return -EOPNOTSUPP;
+	}
 
-	if (!ds->ops->port_mirror_add)
+	if (!ds->ops->port_mirror_add) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Switch does not support mirroring operation");
 		return -EOPNOTSUPP;
+	}
 
 	if (!flow_action_basic_hw_stats_check(&cls->rule->action,
 					      cls->common.extack))
@@ -1485,9 +1491,13 @@ static int dsa_user_add_cls_matchall(struct net_device *dev,
 				     bool ingress)
 {
 	const struct flow_action *action = &cls->rule->action;
+	struct netlink_ext_ack *extack = cls->common.extack;
 
-	if (!flow_offload_has_one_action(action))
+	if (!flow_offload_has_one_action(action)) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Cannot offload matchall filter with more than one action");
 		return -EOPNOTSUPP;
+	}
 
 	switch (action->entries[0].id) {
 	case FLOW_ACTION_MIRRED:
@@ -1495,6 +1505,7 @@ static int dsa_user_add_cls_matchall(struct net_device *dev,
 	case FLOW_ACTION_POLICE:
 		return dsa_user_add_cls_matchall_police(dev, cls, ingress);
 	default:
+		NL_SET_ERR_MSG_MOD(extack, "Unknown action");
 		break;
 	}
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC PATCH net-next 4/6] net: dsa: refuse cross-chip mirroring operations
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
                   ` (2 preceding siblings ...)
  2024-09-13 15:29 ` [RFC PATCH net-next 3/6] net: dsa: add more extack messages in dsa_user_add_cls_matchall_mirred() Vladimir Oltean
@ 2024-09-13 15:29 ` Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 5/6] net: dsa: allow matchall mirroring rules towards the CPU Vladimir Oltean
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

These are not implemented but are not rejected either. Do so now.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/user.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/net/dsa/user.c b/net/dsa/user.c
index 42ff3415c808..c8ddbe22d647 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -1401,6 +1401,14 @@ dsa_user_add_cls_matchall_mirred(struct net_device *dev,
 	if (!dsa_user_dev_check(act->dev))
 		return -EOPNOTSUPP;
 
+	to_dp = dsa_user_to_port(act->dev);
+
+	if (dp->ds != to_dp->ds) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Cross-chip mirroring not implemented");
+		return -EOPNOTSUPP;
+	}
+
 	mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL);
 	if (!mall_tc_entry)
 		return -ENOMEM;
@@ -1408,9 +1416,6 @@ dsa_user_add_cls_matchall_mirred(struct net_device *dev,
 	mall_tc_entry->cookie = cls->cookie;
 	mall_tc_entry->type = DSA_PORT_MALL_MIRROR;
 	mirror = &mall_tc_entry->mirror;
-
-	to_dp = dsa_user_to_port(act->dev);
-
 	mirror->to_local_port = to_dp->index;
 	mirror->ingress = ingress;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC PATCH net-next 5/6] net: dsa: allow matchall mirroring rules towards the CPU
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
                   ` (3 preceding siblings ...)
  2024-09-13 15:29 ` [RFC PATCH net-next 4/6] net: dsa: refuse cross-chip mirroring operations Vladimir Oltean
@ 2024-09-13 15:29 ` Vladimir Oltean
  2024-09-13 15:29 ` [RFC PATCH net-next 6/6] net: mscc: ocelot: allow tc-flower mirred action towards foreign interfaces Vladimir Oltean
  2024-10-04 11:13 ` [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

If the CPU bandwidth capacity permits, it may be useful to mirror the
entire ingress of a user port to software.

This is in fact possible to express even if there is no net_device
representation for the CPU port. In fact, that representation wouldn't
have even helped.

The idea behind implementing this is that currently, we refuse to
offload any mirroring towards a non-DSA target net_device. But if we
acknowledge the fact that to reach any foreign net_device, the switch
must send the packet to the CPU anyway, then we can simply offload just
that part, and let the software do the rest.

Example:

$ ip link add dummy0 type dummy; ip link set dummy0 up
$ tc qdisc add dev swp0 clsact
$ tc filter add dev swp0 ingress matchall action mirred ingress mirror dev dummy0

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/user.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/net/dsa/user.c b/net/dsa/user.c
index c8ddbe22d647..bd3e3944931e 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -1365,7 +1365,7 @@ dsa_user_mall_tc_entry_find(struct net_device *dev, unsigned long cookie)
 static int
 dsa_user_add_cls_matchall_mirred(struct net_device *dev,
 				 struct tc_cls_matchall_offload *cls,
-				 bool ingress)
+				 bool ingress, bool ingress_target)
 {
 	struct netlink_ext_ack *extack = cls->common.extack;
 	struct dsa_port *dp = dsa_user_to_port(dev);
@@ -1398,10 +1398,25 @@ dsa_user_add_cls_matchall_mirred(struct net_device *dev,
 	if (!act->dev)
 		return -EINVAL;
 
-	if (!dsa_user_dev_check(act->dev))
-		return -EOPNOTSUPP;
-
-	to_dp = dsa_user_to_port(act->dev);
+	if (dsa_user_dev_check(act->dev)) {
+		if (ingress_target) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "Cannot mirror to ingress of target port");
+			return -EOPNOTSUPP;
+		}
+		to_dp = dsa_user_to_port(act->dev);
+	} else {
+		/* Handle mirroring to foreign target ports as a mirror towards
+		 * the CPU. The software tc rule will take the packets from
+		 * there.
+		 */
+		if (cls->skip_sw) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "Can only mirred to CPU if filter also runs in software");
+			return -EOPNOTSUPP;
+		}
+		to_dp = dp->cpu_dp;
+	}
 
 	if (dp->ds != to_dp->ds) {
 		NL_SET_ERR_MSG_MOD(extack,
@@ -1506,7 +1521,11 @@ static int dsa_user_add_cls_matchall(struct net_device *dev,
 
 	switch (action->entries[0].id) {
 	case FLOW_ACTION_MIRRED:
-		return dsa_user_add_cls_matchall_mirred(dev, cls, ingress);
+		return dsa_user_add_cls_matchall_mirred(dev, cls, ingress,
+							false);
+	case FLOW_ACTION_MIRRED_INGRESS:
+		return dsa_user_add_cls_matchall_mirred(dev, cls, ingress,
+							true);
 	case FLOW_ACTION_POLICE:
 		return dsa_user_add_cls_matchall_police(dev, cls, ingress);
 	default:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC PATCH net-next 6/6] net: mscc: ocelot: allow tc-flower mirred action towards foreign interfaces
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
                   ` (4 preceding siblings ...)
  2024-09-13 15:29 ` [RFC PATCH net-next 5/6] net: dsa: allow matchall mirroring rules towards the CPU Vladimir Oltean
@ 2024-09-13 15:29 ` Vladimir Oltean
  2024-10-04 11:13 ` [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-09-13 15:29 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

Debugging certain flows in the offloaded switch data path can be done by
installing two tc-mirred filters for mirroring: one in the hardware data
path, which copies the frames to the CPU, and one which takes the frame
from there and mirrors it to a virtual interface like a dummy device,
where it can be seen with tcpdump.

The effect of having 2 filters run on the same packet can be obtained by
default using tc, by not specifying either the 'skip_sw' or 'skip_hw'
keywords.

Instead of refusing to offload mirroring/redirecting packets towards
interfaces that aren't switch ports, just treat every other destination
for what it is: something that is handled in software, behind the CPU
port.

Usage:

$ ip link add dummy0 type dummy; ip link set dummy0 up
$ tc qdisc add dev swp0 clsact
$ tc filter add dev swp0 ingress protocol ip flower action mirred ingress mirror dev dummy0

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_flower.c | 58 ++++++++++++++++++-----
 1 file changed, 46 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index a057ec3dab97..d03a7e636290 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -228,6 +228,36 @@ ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
 	return 0;
 }
 
+static int
+ocelot_flower_parse_egress_port(struct ocelot *ocelot, struct flow_cls_offload *f,
+				const struct flow_action_entry *a, bool mirror,
+				struct netlink_ext_ack *extack)
+{
+	const char *act_string = mirror ? "mirror" : "redirect";
+	int egress_port = ocelot->ops->netdev_to_port(a->dev);
+	enum flow_action_id offloadable_act_id;
+
+	offloadable_act_id = mirror ? FLOW_ACTION_MIRRED : FLOW_ACTION_REDIRECT;
+
+	/* Mirroring towards foreign interfaces is handled in software */
+	if (egress_port < 0) {
+		if (f->skip_sw) {
+			NL_SET_ERR_MSG_FMT_MOD(extack,
+					       "Can only %s to CPU if filter also runs in software",
+					       act_string);
+			return -EOPNOTSUPP;
+		}
+		egress_port = ocelot->num_phys_ports;
+	} else if (a->id != offloadable_act_id) {
+		NL_SET_ERR_MSG_FMT_MOD(extack,
+				       "Can %s only to egress of ocelot port",
+				       act_string);
+		return -EOPNOTSUPP;
+	}
+
+	return egress_port;
+}
+
 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
 				      bool ingress, struct flow_cls_offload *f,
 				      struct ocelot_vcap_filter *filter)
@@ -356,6 +386,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 			break;
 		case FLOW_ACTION_REDIRECT:
+		case FLOW_ACTION_REDIRECT_INGRESS:
 			if (filter->block_id != VCAP_IS2) {
 				NL_SET_ERR_MSG_MOD(extack,
 						   "Redirect action can only be offloaded to VCAP IS2");
@@ -366,17 +397,19 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
 						   "Last action must be GOTO");
 				return -EOPNOTSUPP;
 			}
-			egress_port = ocelot->ops->netdev_to_port(a->dev);
-			if (egress_port < 0) {
-				NL_SET_ERR_MSG_MOD(extack,
-						   "Destination not an ocelot port");
-				return -EOPNOTSUPP;
-			}
+
+			egress_port = ocelot_flower_parse_egress_port(ocelot, f,
+								      a, false,
+								      extack);
+			if (egress_port < 0)
+				return egress_port;
+
 			filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
 			filter->action.port_mask = BIT(egress_port);
 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 			break;
 		case FLOW_ACTION_MIRRED:
+		case FLOW_ACTION_MIRRED_INGRESS:
 			if (filter->block_id != VCAP_IS2) {
 				NL_SET_ERR_MSG_MOD(extack,
 						   "Mirror action can only be offloaded to VCAP IS2");
@@ -387,12 +420,13 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
 						   "Last action must be GOTO");
 				return -EOPNOTSUPP;
 			}
-			egress_port = ocelot->ops->netdev_to_port(a->dev);
-			if (egress_port < 0) {
-				NL_SET_ERR_MSG_MOD(extack,
-						   "Destination not an ocelot port");
-				return -EOPNOTSUPP;
-			}
+
+			egress_port = ocelot_flower_parse_egress_port(ocelot, f,
+								      a, true,
+								      extack);
+			if (egress_port < 0)
+				return egress_port;
+
 			filter->egress_port.value = egress_port;
 			filter->action.mirror_ena = true;
 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH net-next 0/6] Mirroring to DSA CPU port
  2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
                   ` (5 preceding siblings ...)
  2024-09-13 15:29 ` [RFC PATCH net-next 6/6] net: mscc: ocelot: allow tc-flower mirred action towards foreign interfaces Vladimir Oltean
@ 2024-10-04 11:13 ` Vladimir Oltean
  6 siblings, 0 replies; 8+ messages in thread
From: Vladimir Oltean @ 2024-10-04 11:13 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Florian Fainelli, Petr Machata, Ido Schimmel,
	Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver,
	Jamal Hadi Salim, Cong Wang, Jiri Pirko, linux-kernel

On Fri, Sep 13, 2024 at 06:29:09PM +0300, Vladimir Oltean wrote:
> Greetings,
> 
> Users of the NXP LS1028A SoC (drivers/net/dsa/ocelot L2 switch inside)
> have requested to mirror packets from the ingress of a switch port to
> software. Both port-based and flow-based mirroring is required.
> 
> The simplest way I could come up with was to set up tc mirred actions
> towards a dummy net_device, and make the offloading of that be accepted
> by the driver. Currently, the pattern in drivers is to reject mirred
> towards ports they don't know about, but I'm now permitting that,
> precisely by mirroring "to the CPU". I am unsure if there are other,
> perhaps better ways of doing this.

Since there aren't any review comments, I will just resubmit this to
net-next.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-10-04 11:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-13 15:29 [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean
2024-09-13 15:29 ` [RFC PATCH net-next 1/6] net: sched: propagate "skip_sw" flag to offload for flower and matchall Vladimir Oltean
2024-09-13 15:29 ` [RFC PATCH net-next 2/6] net: dsa: clean up dsa_user_add_cls_matchall() Vladimir Oltean
2024-09-13 15:29 ` [RFC PATCH net-next 3/6] net: dsa: add more extack messages in dsa_user_add_cls_matchall_mirred() Vladimir Oltean
2024-09-13 15:29 ` [RFC PATCH net-next 4/6] net: dsa: refuse cross-chip mirroring operations Vladimir Oltean
2024-09-13 15:29 ` [RFC PATCH net-next 5/6] net: dsa: allow matchall mirroring rules towards the CPU Vladimir Oltean
2024-09-13 15:29 ` [RFC PATCH net-next 6/6] net: mscc: ocelot: allow tc-flower mirred action towards foreign interfaces Vladimir Oltean
2024-10-04 11:13 ` [RFC PATCH net-next 0/6] Mirroring to DSA CPU port Vladimir Oltean

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox