Skip to content

Commit

Permalink
net/mlx5: E-Switch, properly handle ingress tagged packets on VST
Browse files Browse the repository at this point in the history
Fix SRIOV VST mode behavior to insert cvlan when a guest tag is already
present in the frame. Previous VST mode behavior was to drop packets or
override existing tag, depending on the device version.

In this patch we fix this behavior by correctly building the HW steering
rule with a push vlan action, or for older devices we ask the FW to stack
the vlan when a vlan is already present.

Fixes: 07bab95 ("net/mlx5: E-Switch, Refactor eswitch ingress acl codes")
Fixes: dfcb1ed ("net/mlx5: E-Switch, Vport ingress/egress ACLs rules for VST mode")
Signed-off-by: Moshe Shemesh <[email protected]>
Reviewed-by: Mark Bloch <[email protected]>
Signed-off-by: Saeed Mahameed <[email protected]>
  • Loading branch information
mosheshemesh2 authored and Saeed Mahameed committed Dec 28, 2022
1 parent 40cab44 commit 1f0ae22
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static void esw_acl_egress_lgcy_groups_destroy(struct mlx5_vport *vport)
int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
bool vst_mode_steering = esw_vst_mode_is_steering(esw);
struct mlx5_flow_destination drop_ctr_dst = {};
struct mlx5_flow_destination *dst = NULL;
struct mlx5_fc *drop_counter = NULL;
Expand All @@ -77,6 +78,7 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
*/
int table_size = 2;
int dest_num = 0;
int actions_flag;
int err = 0;

if (vport->egress.legacy.drop_counter) {
Expand Down Expand Up @@ -119,8 +121,11 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
vport->vport, vport->info.vlan, vport->info.qos);

/* Allowed vlan rule */
actions_flag = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
if (vst_mode_steering)
actions_flag |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
err = esw_egress_acl_vlan_create(esw, vport, NULL, vport->info.vlan,
MLX5_FLOW_CONTEXT_ACTION_ALLOW);
actions_flag);
if (err)
goto out;

Expand Down
33 changes: 28 additions & 5 deletions drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,14 @@ static void esw_acl_ingress_lgcy_groups_destroy(struct mlx5_vport *vport)
int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
bool vst_mode_steering = esw_vst_mode_is_steering(esw);
struct mlx5_flow_destination drop_ctr_dst = {};
struct mlx5_flow_destination *dst = NULL;
struct mlx5_flow_act flow_act = {};
struct mlx5_flow_spec *spec = NULL;
struct mlx5_fc *counter = NULL;
bool vst_check_cvlan = false;
bool vst_push_cvlan = false;
/* The ingress acl table contains 4 groups
* (2 active rules at the same time -
* 1 allow rule from one of the first 3 groups.
Expand Down Expand Up @@ -203,7 +206,26 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
goto out;
}

if (vport->info.vlan || vport->info.qos)
if ((vport->info.vlan || vport->info.qos)) {
if (vst_mode_steering)
vst_push_cvlan = true;
else if (!MLX5_CAP_ESW(esw->dev, vport_cvlan_insert_always))
vst_check_cvlan = true;
}

if (vst_check_cvlan || vport->info.spoofchk)
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;

/* Create ingress allow rule */
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
if (vst_push_cvlan) {
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
flow_act.vlan[0].prio = vport->info.qos;
flow_act.vlan[0].vid = vport->info.vlan;
flow_act.vlan[0].ethtype = ETH_P_8021Q;
}

if (vst_check_cvlan)
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.cvlan_tag);

Expand All @@ -218,9 +240,6 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
ether_addr_copy(smac_v, vport->info.mac);
}

/* Create ingress allow rule */
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
vport->ingress.allow_rule = mlx5_add_flow_rules(vport->ingress.acl, spec,
&flow_act, NULL, 0);
if (IS_ERR(vport->ingress.allow_rule)) {
Expand All @@ -232,6 +251,9 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
goto out;
}

if (!vst_check_cvlan && !vport->info.spoofchk)
goto out;

memset(&flow_act, 0, sizeof(flow_act));
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
/* Attach drop flow counter */
Expand All @@ -257,7 +279,8 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
return 0;

out:
esw_acl_ingress_lgcy_cleanup(esw, vport);
if (err)
esw_acl_ingress_lgcy_cleanup(esw, vport);
kvfree(spec);
return err;
}
Expand Down
30 changes: 21 additions & 9 deletions drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,17 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport,
esw_vport_context.vport_cvlan_strip, 1);

if (set_flags & SET_VLAN_INSERT) {
/* insert only if no vlan in packet */
MLX5_SET(modify_esw_vport_context_in, in,
esw_vport_context.vport_cvlan_insert, 1);

if (MLX5_CAP_ESW(dev, vport_cvlan_insert_always)) {
/* insert either if vlan exist in packet or not */
MLX5_SET(modify_esw_vport_context_in, in,
esw_vport_context.vport_cvlan_insert,
MLX5_VPORT_CVLAN_INSERT_ALWAYS);
} else {
/* insert only if no vlan in packet */
MLX5_SET(modify_esw_vport_context_in, in,
esw_vport_context.vport_cvlan_insert,
MLX5_VPORT_CVLAN_INSERT_WHEN_NO_CVLAN);
}
MLX5_SET(modify_esw_vport_context_in, in,
esw_vport_context.cvlan_pcp, qos);
MLX5_SET(modify_esw_vport_context_in, in,
Expand Down Expand Up @@ -809,6 +816,7 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *

static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
{
bool vst_mode_steering = esw_vst_mode_is_steering(esw);
u16 vport_num = vport->vport;
int flags;
int err;
Expand Down Expand Up @@ -839,8 +847,9 @@ static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)

flags = (vport->info.vlan || vport->info.qos) ?
SET_VLAN_STRIP | SET_VLAN_INSERT : 0;
modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan,
vport->info.qos, flags);
if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering)
modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan,
vport->info.qos, flags);

return 0;

Expand Down Expand Up @@ -1848,16 +1857,19 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
u16 vport, u16 vlan, u8 qos, u8 set_flags)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
bool vst_mode_steering = esw_vst_mode_is_steering(esw);
int err = 0;

if (IS_ERR(evport))
return PTR_ERR(evport);
if (vlan > 4095 || qos > 7)
return -EINVAL;

err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
if (err)
return err;
if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) {
err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
if (err)
return err;
}

evport->info.vlan = vlan;
evport->info.qos = qos;
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,12 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
u16 vport, u16 vlan, u8 qos, u8 set_flags);

static inline bool esw_vst_mode_is_steering(struct mlx5_eswitch *esw)
{
return (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, pop_vlan) &&
MLX5_CAP_ESW_INGRESS_ACL(esw->dev, push_vlan));
}

static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev,
u8 vlan_depth)
{
Expand Down
5 changes: 5 additions & 0 deletions include/linux/mlx5/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,11 @@ enum {
MLX5_VPORT_ADMIN_STATE_AUTO = 0x2,
};

enum {
MLX5_VPORT_CVLAN_INSERT_WHEN_NO_CVLAN = 0x1,
MLX5_VPORT_CVLAN_INSERT_ALWAYS = 0x3,
};

enum {
MLX5_L3_PROT_TYPE_IPV4 = 0,
MLX5_L3_PROT_TYPE_IPV6 = 1,
Expand Down
3 changes: 2 additions & 1 deletion include/linux/mlx5/mlx5_ifc.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,8 @@ struct mlx5_ifc_e_switch_cap_bits {
u8 vport_svlan_insert[0x1];
u8 vport_cvlan_insert_if_not_exist[0x1];
u8 vport_cvlan_insert_overwrite[0x1];
u8 reserved_at_5[0x2];
u8 reserved_at_5[0x1];
u8 vport_cvlan_insert_always[0x1];
u8 esw_shared_ingress_acl[0x1];
u8 esw_uplink_ingress_acl[0x1];
u8 root_ft_on_other_esw[0x1];
Expand Down

0 comments on commit 1f0ae22

Please sign in to comment.