Skip to content

Commit 592d365

Browse files
mishuang2017Saeed Mahameed
authored andcommitted
net/mlx5e: Parse mirroring action for offloaded TC eswitch flows
Currently, we only support the mirred redirect TC sub-action. In order to support flow based vport mirroring, add support to parse the mirred mirror sub-action. For mirroring, user-space will typically set the action order such that the mirror port (mirror VF) sees packets as the original port (VF under mirroring) sent them or as it will receive them. In the general case, it means that packets are potentially sent to the mirror port before or after some actions were applied on them. To properly do that, we should follow on the exact action order as set for the flow and make sure this will also be the case when we program the HW offload. We introduce a counter for the output ports (attr->out_count), which we increase when parsing each mirred redirect/mirror sub-action and when dealing with encap. We introduce a counter (attr->mirror_count) telling us if split is needed. If no split is needed and mirroring is just multicasting to vport, the mirror count is zero, all the actions of the TC flow should apply on that single HW flow. If split is needed, the mirror count tells where to do the split, all non-mirred tc actions should apply only after the split. The mirror count is set while parsing the following actions encap/decap, header re-write, vlan push/pop. Signed-off-by: Chris Mi <[email protected]> Reviewed-by: Paul Blakey <[email protected]> Reviewed-by: Or Gerlitz <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent a842dd0 commit 592d365

File tree

3 files changed

+43
-21
lines changed

3 files changed

+43
-21
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,8 +844,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
844844
}
845845
out_priv = netdev_priv(encap_dev);
846846
rpriv = out_priv->ppriv;
847-
attr->out_rep = rpriv->rep;
848-
attr->out_mdev = out_priv->mdev;
847+
attr->out_rep[attr->out_count] = rpriv->rep;
848+
attr->out_mdev[attr->out_count++] = out_priv->mdev;
849849
}
850850

851851
err = mlx5_eswitch_add_vlan_action(esw, attr);
@@ -2537,6 +2537,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
25372537
return err;
25382538

25392539
action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
2540+
attr->mirror_count = attr->out_count;
25402541
continue;
25412542
}
25422543

@@ -2548,21 +2549,27 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
25482549
return -EOPNOTSUPP;
25492550
}
25502551

2551-
if (is_tcf_mirred_egress_redirect(a)) {
2552-
struct net_device *out_dev;
2552+
if (is_tcf_mirred_egress_redirect(a) || is_tcf_mirred_egress_mirror(a)) {
25532553
struct mlx5e_priv *out_priv;
2554+
struct net_device *out_dev;
25542555

25552556
out_dev = tcf_mirred_dev(a);
25562557

2558+
if (attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) {
2559+
pr_err("can't support more than %d output ports, can't offload forwarding\n",
2560+
attr->out_count);
2561+
return -EOPNOTSUPP;
2562+
}
2563+
25572564
if (switchdev_port_same_parent_id(priv->netdev,
25582565
out_dev) ||
25592566
is_merged_eswitch_dev(priv, out_dev)) {
25602567
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
25612568
MLX5_FLOW_CONTEXT_ACTION_COUNT;
25622569
out_priv = netdev_priv(out_dev);
25632570
rpriv = out_priv->ppriv;
2564-
attr->out_rep = rpriv->rep;
2565-
attr->out_mdev = out_priv->mdev;
2571+
attr->out_rep[attr->out_count] = rpriv->rep;
2572+
attr->out_mdev[attr->out_count++] = out_priv->mdev;
25662573
} else if (encap) {
25672574
parse_attr->mirred_ifindex = out_dev->ifindex;
25682575
parse_attr->tun_info = *info;
@@ -2585,6 +2592,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
25852592
encap = true;
25862593
else
25872594
return -EOPNOTSUPP;
2595+
attr->mirror_count = attr->out_count;
25882596
continue;
25892597
}
25902598

@@ -2606,6 +2614,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
26062614
} else { /* action is TCA_VLAN_ACT_MODIFY */
26072615
return -EOPNOTSUPP;
26082616
}
2617+
attr->mirror_count = attr->out_count;
26092618
continue;
26102619
}
26112620

@@ -2621,6 +2630,11 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
26212630
if (!actions_match_supported(priv, exts, parse_attr, flow))
26222631
return -EOPNOTSUPP;
26232632

2633+
if (attr->out_count > 1 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
2634+
netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n");
2635+
return -EOPNOTSUPP;
2636+
}
2637+
26242638
return 0;
26252639
}
26262640

drivers/net/ethernet/mellanox/mlx5/core/eswitch.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,18 @@ enum mlx5_flow_match_level {
239239
MLX5_MATCH_L4 = MLX5_INLINE_MODE_TCP_UDP,
240240
};
241241

242+
/* current maximum for flow based vport multicasting */
243+
#define MLX5_MAX_FLOW_FWD_VPORTS 2
244+
242245
struct mlx5_esw_flow_attr {
243246
struct mlx5_eswitch_rep *in_rep;
244-
struct mlx5_eswitch_rep *out_rep;
245-
struct mlx5_core_dev *out_mdev;
247+
struct mlx5_eswitch_rep *out_rep[MLX5_MAX_FLOW_FWD_VPORTS];
248+
struct mlx5_core_dev *out_mdev[MLX5_MAX_FLOW_FWD_VPORTS];
246249
struct mlx5_core_dev *in_mdev;
247250

251+
int mirror_count;
252+
int out_count;
253+
248254
int action;
249255
__be16 vlan_proto;
250256
u16 vlan_vid;

drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
4848
struct mlx5_flow_spec *spec,
4949
struct mlx5_esw_flow_attr *attr)
5050
{
51-
struct mlx5_flow_destination dest[2] = {};
51+
struct mlx5_flow_destination dest[MLX5_MAX_FLOW_FWD_VPORTS + 1] = {};
5252
struct mlx5_flow_act flow_act = {0};
5353
struct mlx5_fc *counter = NULL;
5454
struct mlx5_flow_handle *rule;
55+
int j, i = 0;
5556
void *misc;
56-
int i = 0;
5757

5858
if (esw->mode != SRIOV_OFFLOADS)
5959
return ERR_PTR(-EOPNOTSUPP);
@@ -70,14 +70,16 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
7070
}
7171

7272
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
73-
dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
74-
dest[i].vport.num = attr->out_rep->vport;
75-
if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
76-
dest[i].vport.vhca_id =
77-
MLX5_CAP_GEN(attr->out_mdev, vhca_id);
78-
dest[i].vport.vhca_id_valid = 1;
73+
for (j = attr->mirror_count; j < attr->out_count; j++) {
74+
dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
75+
dest[i].vport.num = attr->out_rep[j]->vport;
76+
if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
77+
dest[i].vport.vhca_id =
78+
MLX5_CAP_GEN(attr->out_mdev[j], vhca_id);
79+
dest[i].vport.vhca_id_valid = 1;
80+
}
81+
i++;
7982
}
80-
i++;
8183
}
8284
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
8385
counter = mlx5_fc_create(esw->dev, true);
@@ -173,7 +175,7 @@ esw_vlan_action_get_vport(struct mlx5_esw_flow_attr *attr, bool push, bool pop)
173175
struct mlx5_eswitch_rep *in_rep, *out_rep, *vport = NULL;
174176

175177
in_rep = attr->in_rep;
176-
out_rep = attr->out_rep;
178+
out_rep = attr->out_rep[0];
177179

178180
if (push)
179181
vport = in_rep;
@@ -194,7 +196,7 @@ static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
194196
goto out_notsupp;
195197

196198
in_rep = attr->in_rep;
197-
out_rep = attr->out_rep;
199+
out_rep = attr->out_rep[0];
198200

199201
if (push && in_rep->vport == FDB_UPLINK_VPORT)
200202
goto out_notsupp;
@@ -245,7 +247,7 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
245247

246248
if (!push && !pop && fwd) {
247249
/* tracks VF --> wire rules without vlan push action */
248-
if (attr->out_rep->vport == FDB_UPLINK_VPORT) {
250+
if (attr->out_rep[0]->vport == FDB_UPLINK_VPORT) {
249251
vport->vlan_refcount++;
250252
attr->vlan_handled = true;
251253
}
@@ -305,7 +307,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
305307

306308
if (!push && !pop && fwd) {
307309
/* tracks VF --> wire rules without vlan push action */
308-
if (attr->out_rep->vport == FDB_UPLINK_VPORT)
310+
if (attr->out_rep[0]->vport == FDB_UPLINK_VPORT)
309311
vport->vlan_refcount--;
310312

311313
return 0;

0 commit comments

Comments
 (0)