net/mlx5e: Support offloading double vlan push/pop tc actions
authorJianbo Liu <jianbol@mellanox.com>
Wed, 25 Apr 2018 09:57:26 +0000 (09:57 +0000)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 23 Jul 2018 22:01:11 +0000 (15:01 -0700)
As we can configure two push/pop actions in one flow table entry,
add support to offload those double vlan actions in a rule to HW.

Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@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 35b3e135ae1dd63467ab154620d7d0396bc01504..e9888d6c1f7c99fc75b917e88e2c1eec77fcace7 100644 (file)
@@ -2583,24 +2583,48 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
                                struct mlx5_esw_flow_attr *attr,
                                u32 *action)
 {
                                struct mlx5_esw_flow_attr *attr,
                                u32 *action)
 {
+       u8 vlan_idx = attr->total_vlan;
+
+       if (vlan_idx >= MLX5_FS_VLAN_DEPTH)
+               return -EOPNOTSUPP;
+
        if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
        if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
-               *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
+               if (vlan_idx) {
+                       if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
+                                                                MLX5_FS_VLAN_DEPTH))
+                               return -EOPNOTSUPP;
+
+                       *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
+               } else {
+                       *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
+               }
        } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
        } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
-               *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
-               attr->vlan_vid[0] = tcf_vlan_push_vid(a);
-               if (mlx5_eswitch_vlan_actions_supported(priv->mdev)) {
-                       attr->vlan_prio[0] = tcf_vlan_push_prio(a);
-                       attr->vlan_proto[0] = tcf_vlan_push_proto(a);
-                       if (!attr->vlan_proto[0])
-                               attr->vlan_proto[0] = htons(ETH_P_8021Q);
-               } else if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) ||
-                          tcf_vlan_push_prio(a)) {
-                       return -EOPNOTSUPP;
+               attr->vlan_vid[vlan_idx] = tcf_vlan_push_vid(a);
+               attr->vlan_prio[vlan_idx] = tcf_vlan_push_prio(a);
+               attr->vlan_proto[vlan_idx] = tcf_vlan_push_proto(a);
+               if (!attr->vlan_proto[vlan_idx])
+                       attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);
+
+               if (vlan_idx) {
+                       if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
+                                                                MLX5_FS_VLAN_DEPTH))
+                               return -EOPNOTSUPP;
+
+                       *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
+               } else {
+                       if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) &&
+                           (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) ||
+                            tcf_vlan_push_prio(a)))
+                               return -EOPNOTSUPP;
+
+                       *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
                }
        } else { /* action is TCA_VLAN_ACT_MODIFY */
                return -EOPNOTSUPP;
        }
 
                }
        } else { /* action is TCA_VLAN_ACT_MODIFY */
                return -EOPNOTSUPP;
        }
 
+       attr->total_vlan = vlan_idx + 1;
+
        return 0;
 }
 
        return 0;
 }
 
index befa0011efee4f1620d0bd64c0feaf604afc2b30..c17bfcab517c18745901d0c059b316bea1945203 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/devlink.h>
 #include <linux/mlx5/device.h>
 #include <linux/mlx5/eswitch.h>
 #include <net/devlink.h>
 #include <linux/mlx5/device.h>
 #include <linux/mlx5/eswitch.h>
+#include <linux/mlx5/fs.h>
 #include "lib/mpfs.h"
 
 #ifdef CONFIG_MLX5_ESWITCH
 #include "lib/mpfs.h"
 
 #ifdef CONFIG_MLX5_ESWITCH
@@ -256,9 +257,10 @@ struct mlx5_esw_flow_attr {
        int out_count;
 
        int     action;
        int out_count;
 
        int     action;
-       __be16  vlan_proto[1];
-       u16     vlan_vid[1];
-       u8      vlan_prio[1];
+       __be16  vlan_proto[MLX5_FS_VLAN_DEPTH];
+       u16     vlan_vid[MLX5_FS_VLAN_DEPTH];
+       u8      vlan_prio[MLX5_FS_VLAN_DEPTH];
+       u8      total_vlan;
        bool    vlan_handled;
        u32     encap_id;
        u32     mod_hdr_id;
        bool    vlan_handled;
        u32     encap_id;
        u32     mod_hdr_id;
@@ -282,10 +284,17 @@ 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)
+static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev,
+                                                      u8 vlan_depth)
 {
 {
-       return MLX5_CAP_ESW_FLOWTABLE_FDB(dev, pop_vlan) &&
-              MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan);
+       bool ret = MLX5_CAP_ESW_FLOWTABLE_FDB(dev, pop_vlan) &&
+                  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan);
+
+       if (vlan_depth == 1)
+               return ret;
+
+       return  ret && MLX5_CAP_ESW_FLOWTABLE_FDB(dev, pop_vlan_2) &&
+               MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_vlan_2);
 }
 
 #define MLX5_DEBUG_ESWITCH_MASK BIT(3)
 }
 
 #define MLX5_DEBUG_ESWITCH_MASK BIT(3)
index 552954d7184e9b99cb6d6af1824f21ed87221430..f72b5c9dcfe95f98cc388676462207bf76247504 100644 (file)
@@ -66,13 +66,18 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 
        flow_act.action = attr->action;
        /* if per flow vlan pop/push is emulated, don't set that into the firmware */
 
        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))
+       if (!mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
                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[0].ethtype = ntohs(attr->vlan_proto[0]);
                flow_act.vlan[0].vid = attr->vlan_vid[0];
                flow_act.vlan[0].prio = attr->vlan_prio[0];
                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[0].ethtype = ntohs(attr->vlan_proto[0]);
                flow_act.vlan[0].vid = attr->vlan_vid[0];
                flow_act.vlan[0].prio = attr->vlan_prio[0];
+               if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) {
+                       flow_act.vlan[1].ethtype = ntohs(attr->vlan_proto[1]);
+                       flow_act.vlan[1].vid = attr->vlan_vid[1];
+                       flow_act.vlan[1].prio = attr->vlan_prio[1];
+               }
        }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
        }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
@@ -284,7 +289,7 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
        int err = 0;
 
        /* nop if we're on the vlan push/pop non emulation mode */
        int err = 0;
 
        /* nop if we're on the vlan push/pop non emulation mode */
-       if (mlx5_eswitch_vlan_actions_supported(esw->dev))
+       if (mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
                return 0;
 
        push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
                return 0;
 
        push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
@@ -347,7 +352,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
        int err = 0;
 
        /* nop if we're on the vlan push/pop non emulation mode */
        int err = 0;
 
        /* nop if we're on the vlan push/pop non emulation mode */
-       if (mlx5_eswitch_vlan_actions_supported(esw->dev))
+       if (mlx5_eswitch_vlan_actions_supported(esw->dev, 1))
                return 0;
 
        if (!attr->vlan_handled)
                return 0;
 
        if (!attr->vlan_handled)