Commit cc495188 authored by Jianbo Liu's avatar Jianbo Liu Committed by Saeed Mahameed

net/mlx5e: Support offloading double vlan push/pop tc actions

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: default avatarJianbo Liu <jianbol@mellanox.com>
Reviewed-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 1482bd3d
...@@ -2583,24 +2583,48 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv, ...@@ -2583,24 +2583,48 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv,
struct mlx5_esw_flow_attr *attr, struct mlx5_esw_flow_attr *attr,
u32 *action) 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[vlan_idx] = tcf_vlan_push_vid(a);
attr->vlan_vid[0] = tcf_vlan_push_vid(a); attr->vlan_prio[vlan_idx] = tcf_vlan_push_prio(a);
if (mlx5_eswitch_vlan_actions_supported(priv->mdev)) { attr->vlan_proto[vlan_idx] = tcf_vlan_push_proto(a);
attr->vlan_prio[0] = tcf_vlan_push_prio(a); if (!attr->vlan_proto[vlan_idx])
attr->vlan_proto[0] = tcf_vlan_push_proto(a); attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);
if (!attr->vlan_proto[0])
attr->vlan_proto[0] = htons(ETH_P_8021Q); if (vlan_idx) {
} else if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) || if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
tcf_vlan_push_prio(a)) { MLX5_FS_VLAN_DEPTH))
return -EOPNOTSUPP; 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 */ } else { /* action is TCA_VLAN_ACT_MODIFY */
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
attr->total_vlan = vlan_idx + 1;
return 0; return 0;
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <net/devlink.h> #include <net/devlink.h>
#include <linux/mlx5/device.h> #include <linux/mlx5/device.h>
#include <linux/mlx5/eswitch.h> #include <linux/mlx5/eswitch.h>
#include <linux/mlx5/fs.h>
#include "lib/mpfs.h" #include "lib/mpfs.h"
#ifdef CONFIG_MLX5_ESWITCH #ifdef CONFIG_MLX5_ESWITCH
...@@ -256,9 +257,10 @@ struct mlx5_esw_flow_attr { ...@@ -256,9 +257,10 @@ struct mlx5_esw_flow_attr {
int out_count; int out_count;
int action; int action;
__be16 vlan_proto[1]; __be16 vlan_proto[MLX5_FS_VLAN_DEPTH];
u16 vlan_vid[1]; u16 vlan_vid[MLX5_FS_VLAN_DEPTH];
u8 vlan_prio[1]; u8 vlan_prio[MLX5_FS_VLAN_DEPTH];
u8 total_vlan;
bool vlan_handled; bool vlan_handled;
u32 encap_id; u32 encap_id;
u32 mod_hdr_id; u32 mod_hdr_id;
...@@ -282,10 +284,17 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, ...@@ -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 __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
int vport, u16 vlan, u8 qos, u8 set_flags); 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) && bool ret = MLX5_CAP_ESW_FLOWTABLE_FDB(dev, pop_vlan) &&
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, push_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)
......
...@@ -66,13 +66,18 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, ...@@ -66,13 +66,18 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
flow_act.action = attr->action; flow_act.action = attr->action;
/* if per flow vlan pop/push is emulated, don't set that into the firmware */ /* 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 | flow_act.action &= ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
MLX5_FLOW_CONTEXT_ACTION_VLAN_POP); MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
else if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) { 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].ethtype = ntohs(attr->vlan_proto[0]);
flow_act.vlan[0].vid = attr->vlan_vid[0]; flow_act.vlan[0].vid = attr->vlan_vid[0];
flow_act.vlan[0].prio = attr->vlan_prio[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, ...@@ -284,7 +289,7 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
int err = 0; int err = 0;
/* nop if we're on the vlan push/pop non emulation mode */ /* 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; return 0;
push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH); push = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH);
...@@ -347,7 +352,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, ...@@ -347,7 +352,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
int err = 0; int err = 0;
/* nop if we're on the vlan push/pop non emulation mode */ /* 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; return 0;
if (!attr->vlan_handled) if (!attr->vlan_handled)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment