Skip to content

Commit 49a0907

Browse files
vladimirolteankuba-moo
authored andcommitted
net: mscc: ocelot: allow tc-flower mirred action towards foreign interfaces
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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 3535d70 commit 49a0907

File tree

1 file changed

+42
-12
lines changed

1 file changed

+42
-12
lines changed

drivers/net/ethernet/mscc/ocelot_flower.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,32 @@ ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
228228
return 0;
229229
}
230230

231+
static int
232+
ocelot_flower_parse_egress_port(struct ocelot *ocelot, struct flow_cls_offload *f,
233+
const struct flow_action_entry *a, bool mirror,
234+
struct netlink_ext_ack *extack)
235+
{
236+
const char *act_string = mirror ? "mirror" : "redirect";
237+
int egress_port = ocelot->ops->netdev_to_port(a->dev);
238+
enum flow_action_id offloadable_act_id;
239+
240+
offloadable_act_id = mirror ? FLOW_ACTION_MIRRED : FLOW_ACTION_REDIRECT;
241+
242+
/* Mirroring towards foreign interfaces is handled in software */
243+
if (egress_port < 0 || a->id != offloadable_act_id) {
244+
if (f->common.skip_sw) {
245+
NL_SET_ERR_MSG_FMT(extack,
246+
"Can only %s to %s if filter also runs in software",
247+
act_string, egress_port < 0 ?
248+
"CPU" : "ingress of ocelot port");
249+
return -EOPNOTSUPP;
250+
}
251+
egress_port = ocelot->num_phys_ports;
252+
}
253+
254+
return egress_port;
255+
}
256+
231257
static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
232258
bool ingress, struct flow_cls_offload *f,
233259
struct ocelot_vcap_filter *filter)
@@ -356,6 +382,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
356382
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
357383
break;
358384
case FLOW_ACTION_REDIRECT:
385+
case FLOW_ACTION_REDIRECT_INGRESS:
359386
if (filter->block_id != VCAP_IS2) {
360387
NL_SET_ERR_MSG_MOD(extack,
361388
"Redirect action can only be offloaded to VCAP IS2");
@@ -366,17 +393,19 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
366393
"Last action must be GOTO");
367394
return -EOPNOTSUPP;
368395
}
369-
egress_port = ocelot->ops->netdev_to_port(a->dev);
370-
if (egress_port < 0) {
371-
NL_SET_ERR_MSG_MOD(extack,
372-
"Destination not an ocelot port");
373-
return -EOPNOTSUPP;
374-
}
396+
397+
egress_port = ocelot_flower_parse_egress_port(ocelot, f,
398+
a, false,
399+
extack);
400+
if (egress_port < 0)
401+
return egress_port;
402+
375403
filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
376404
filter->action.port_mask = BIT(egress_port);
377405
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
378406
break;
379407
case FLOW_ACTION_MIRRED:
408+
case FLOW_ACTION_MIRRED_INGRESS:
380409
if (filter->block_id != VCAP_IS2) {
381410
NL_SET_ERR_MSG_MOD(extack,
382411
"Mirror action can only be offloaded to VCAP IS2");
@@ -387,12 +416,13 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
387416
"Last action must be GOTO");
388417
return -EOPNOTSUPP;
389418
}
390-
egress_port = ocelot->ops->netdev_to_port(a->dev);
391-
if (egress_port < 0) {
392-
NL_SET_ERR_MSG_MOD(extack,
393-
"Destination not an ocelot port");
394-
return -EOPNOTSUPP;
395-
}
419+
420+
egress_port = ocelot_flower_parse_egress_port(ocelot, f,
421+
a, true,
422+
extack);
423+
if (egress_port < 0)
424+
return egress_port;
425+
396426
filter->egress_port.value = egress_port;
397427
filter->action.mirror_ena = true;
398428
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;

0 commit comments

Comments
 (0)