net/mlx5e: Offload tc vlan push/pop using HW action
authorOr Gerlitz <ogerlitz@mellanox.com>
Wed, 31 Jan 2018 16:36:03 +0000 (18:36 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 26 Mar 2018 20:47:13 +0000 (13:47 -0700)
Currently, we are emulating the offload of vlan push/pop actions using
global setup as done by commit f5f82476090f ("net/mlx5: E-Switch, Support
VLAN actions in the offloads mode"). With newer NICs, we can apply a flow
action for that matter, do that while keeping the emulated path for the
older HW brands.

Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Mark Bloch <markb@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

index 7c33df2034f07d69a04b6a1d6365500d1dd70261..3e4a7e81b67f0c94069324e95a2fcb701cf20c43 100644 (file)
@@ -2530,12 +2530,17 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
                        } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
                        if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
                        } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
-                               if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) ||
-                                   tcf_vlan_push_prio(a))
-                                       return -EOPNOTSUPP;
-
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
-                               attr->vlan = tcf_vlan_push_vid(a);
+                               attr->vlan_vid = tcf_vlan_push_vid(a);
+                               if (mlx5_eswitch_vlan_actions_supported(priv->mdev)) {
+                                       attr->vlan_prio = tcf_vlan_push_prio(a);
+                                       attr->vlan_proto = tcf_vlan_push_proto(a);
+                                       if (!attr->vlan_proto)
+                                               attr->vlan_proto = htons(ETH_P_8021Q);
+                               } else if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) ||
+                                          tcf_vlan_push_prio(a)) {
+                                       return -EOPNOTSUPP;
+                               }
                        } else { /* action is TCA_VLAN_ACT_MODIFY */
                                return -EOPNOTSUPP;
                        }
                        } else { /* action is TCA_VLAN_ACT_MODIFY */
                                return -EOPNOTSUPP;
                        }
index a435eb7971c6eca751d2cbe6be466cf446358858..4cd773fa55e333f20dad15619a0509bdb3006f1a 100644 (file)
@@ -232,7 +232,9 @@ struct mlx5_esw_flow_attr {
        struct mlx5_eswitch_rep *out_rep;
 
        int     action;
        struct mlx5_eswitch_rep *out_rep;
 
        int     action;
-       u16     vlan;
+       __be16  vlan_proto;
+       u16     vlan_vid;
+       u8      vlan_prio;
        bool    vlan_handled;
        u32     encap_id;
        u32     mod_hdr_id;
        bool    vlan_handled;
        u32     encap_id;
        u32     mod_hdr_id;
@@ -255,6 +257,12 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
                                  int vport, u16 vlan, u8 qos, u8 set_flags);
 
 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
                                  int vport, u16 vlan, u8 qos, u8 set_flags);
 
+static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev)
+{
+       return MLX5_CAP_ESW_FLOWTABLE_FDB(dev, pop_vlan) &&
+              MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan);
+}
+
 #define MLX5_DEBUG_ESWITCH_MASK BIT(3)
 
 #define esw_info(dev, format, ...)                             \
 #define MLX5_DEBUG_ESWITCH_MASK BIT(3)
 
 #define esw_info(dev, format, ...)                             \
index 21ebe3e80e6e2d9724c9fd5ddb273dc2043dcd68..35e256eb2f6e40de5cc4a78fed19327fafacec7c 100644 (file)
@@ -58,8 +58,16 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
        if (esw->mode != SRIOV_OFFLOADS)
                return ERR_PTR(-EOPNOTSUPP);
 
        if (esw->mode != SRIOV_OFFLOADS)
                return ERR_PTR(-EOPNOTSUPP);
 
-       /* per flow vlan pop/push is emulated, don't set that into the firmware */
-       flow_act.action = attr->action & ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH | MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
+       flow_act.action = attr->action;
+       /* if per flow vlan pop/push is emulated, don't set that into the firmware */
+       if (!mlx5_eswitch_vlan_actions_supported(esw->dev))
+               flow_act.action &= ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
+                                    MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
+       else if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
+               flow_act.vlan.ethtype = ntohs(attr->vlan_proto);
+               flow_act.vlan.vid = attr->vlan_vid;
+               flow_act.vlan.prio = attr->vlan_prio;
+       }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
                dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
                dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
@@ -185,7 +193,7 @@ static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
        /* protects against (1) setting rules with different vlans to push and
         * (2) setting rules w.o vlans (attr->vlan = 0) && w. vlans to push (!= 0)
         */
        /* protects against (1) setting rules with different vlans to push and
         * (2) setting rules w.o vlans (attr->vlan = 0) && w. vlans to push (!= 0)
         */
-       if (push && in_rep->vlan_refcount && (in_rep->vlan != attr->vlan))
+       if (push && in_rep->vlan_refcount && (in_rep->vlan != attr->vlan_vid))
                goto out_notsupp;
 
        return 0;
                goto out_notsupp;
 
        return 0;
@@ -202,6 +210,10 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
        bool push, pop, fwd;
        int err = 0;
 
        bool push, pop, fwd;
        int err = 0;
 
+       /* nop if we're on the vlan push/pop non emulation mode */
+       if (mlx5_eswitch_vlan_actions_supported(esw->dev))
+               return 0;
+
        push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
        pop  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
        fwd  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
        push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
        pop  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
        fwd  = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
@@ -239,11 +251,11 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
                if (vport->vlan_refcount)
                        goto skip_set_push;
 
                if (vport->vlan_refcount)
                        goto skip_set_push;
 
-               err = __mlx5_eswitch_set_vport_vlan(esw, vport->vport, attr->vlan, 0,
+               err = __mlx5_eswitch_set_vport_vlan(esw, vport->vport, attr->vlan_vid, 0,
                                                    SET_VLAN_INSERT | SET_VLAN_STRIP);
                if (err)
                        goto out;
                                                    SET_VLAN_INSERT | SET_VLAN_STRIP);
                if (err)
                        goto out;
-               vport->vlan = attr->vlan;
+               vport->vlan = attr->vlan_vid;
 skip_set_push:
                vport->vlan_refcount++;
        }
 skip_set_push:
                vport->vlan_refcount++;
        }
@@ -261,6 +273,10 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
        bool push, pop, fwd;
        int err = 0;
 
        bool push, pop, fwd;
        int err = 0;
 
+       /* nop if we're on the vlan push/pop non emulation mode */
+       if (mlx5_eswitch_vlan_actions_supported(esw->dev))
+               return 0;
+
        if (!attr->vlan_handled)
                return 0;
 
        if (!attr->vlan_handled)
                return 0;