From f2a0e216bee5d95e2c2d916a8815a659cd3703c2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 16 Mar 2022 22:41:42 +0200 Subject: net: mscc: ocelot: offload per-flow mirroring using tc-mirred and VCAP IS2 Per-flow mirroring with the VCAP IS2 TCAM (in itself handled as an offload for tc-flower) is done by setting the MIRROR_ENA bit from the action vector of the filter. The packet is mirrored to the port mask configured in the ANA:ANA:MIRRORPORTS register (the same port mask as the destinations for port-based mirroring). Functionality was tested with: tc qdisc add dev swp3 clsact tc filter add dev swp3 ingress protocol ip \ flower skip_sw ip_proto icmp \ action mirred egress mirror dev swp1 and pinging through swp3, while seeing that the ICMP replies are mirrored towards swp1. Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot_vcap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net/ethernet/mscc/ocelot_vcap.c') diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c index 829fb55ea9dc..c8701ac955a8 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.c +++ b/drivers/net/ethernet/mscc/ocelot_vcap.c @@ -335,6 +335,7 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data, vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, a->mask_mode); vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, a->port_mask); + vcap_action_set(vcap, data, VCAP_IS2_ACT_MIRROR_ENA, a->mirror_ena); vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, a->police_ena); vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX, a->pol_ix); vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, a->cpu_qu_num); @@ -960,8 +961,16 @@ ocelot_vcap_filter_add_aux_resources(struct ocelot *ocelot, struct ocelot_vcap_filter *filter, struct netlink_ext_ack *extack) { + struct ocelot_mirror *m; int ret; + if (filter->block_id == VCAP_IS2 && filter->action.mirror_ena) { + m = ocelot_mirror_get(ocelot, filter->egress_port.value, + extack); + if (IS_ERR(m)) + return PTR_ERR(m); + } + if (filter->block_id == VCAP_IS2 && filter->action.police_ena) { ret = ocelot_vcap_policer_add(ocelot, filter->action.pol_ix, &filter->action.pol); @@ -978,6 +987,9 @@ ocelot_vcap_filter_del_aux_resources(struct ocelot *ocelot, { if (filter->block_id == VCAP_IS2 && filter->action.police_ena) ocelot_vcap_policer_del(ocelot, filter->action.pol_ix); + + if (filter->block_id == VCAP_IS2 && filter->action.mirror_ena) + ocelot_mirror_put(ocelot); } static int ocelot_vcap_filter_add_to_block(struct ocelot *ocelot, -- cgit