net/mlx5e: Add vlan push/pop/mangle to tc action infra
Add parsing support by implementing struct mlx5e_tc_act for this action. Signed-off-by: Roi Dayan <roid@nvidia.com> Reviewed-by: Oz Shlomo <ozsh@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
parent
e36db1ee7a
commit
8ee7263834
@ -49,7 +49,8 @@ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en_tc.o en/rep/tc.o en/rep/neigh.o \
|
||||
|
||||
mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/act/trap.o \
|
||||
en/tc/act/accept.o en/tc/act/mark.o en/tc/act/goto.o \
|
||||
en/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o
|
||||
en/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o \
|
||||
en/tc/act/vlan.o en/tc/act/vlan_mangle.o
|
||||
|
||||
mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
|
||||
mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o
|
||||
|
@ -15,9 +15,9 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = {
|
||||
NULL, /* FLOW_ACTION_MIRRED, */
|
||||
NULL, /* FLOW_ACTION_REDIRECT_INGRESS, */
|
||||
NULL, /* FLOW_ACTION_MIRRED_INGRESS, */
|
||||
NULL, /* FLOW_ACTION_VLAN_PUSH, */
|
||||
NULL, /* FLOW_ACTION_VLAN_POP, */
|
||||
NULL, /* FLOW_ACTION_VLAN_MANGLE, */
|
||||
&mlx5e_tc_act_vlan,
|
||||
&mlx5e_tc_act_vlan,
|
||||
&mlx5e_tc_act_vlan_mangle,
|
||||
&mlx5e_tc_act_tun_encap,
|
||||
&mlx5e_tc_act_tun_decap,
|
||||
&mlx5e_tc_act_pedit,
|
||||
|
@ -42,6 +42,8 @@ extern struct mlx5e_tc_act mlx5e_tc_act_tun_encap;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_tun_decap;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_csum;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_pedit;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_vlan;
|
||||
extern struct mlx5e_tc_act mlx5e_tc_act_vlan_mangle;
|
||||
|
||||
struct mlx5e_tc_act *
|
||||
mlx5e_tc_act_get(enum flow_action_id act_id,
|
||||
|
167
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
Normal file
167
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
Normal file
@ -0,0 +1,167 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
|
||||
#include <linux/if_vlan.h>
|
||||
#include "act.h"
|
||||
#include "vlan.h"
|
||||
#include "en/tc_priv.h"
|
||||
|
||||
static int
|
||||
parse_tc_vlan_action(struct mlx5e_priv *priv,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5_esw_flow_attr *attr,
|
||||
u32 *action,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u8 vlan_idx = attr->total_vlan;
|
||||
|
||||
if (vlan_idx >= MLX5_FS_VLAN_DEPTH) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Total vlans used is greater than supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_VLAN_POP:
|
||||
if (vlan_idx) {
|
||||
if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
|
||||
MLX5_FS_VLAN_DEPTH)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "vlan pop action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
|
||||
} else {
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
|
||||
}
|
||||
break;
|
||||
case FLOW_ACTION_VLAN_PUSH:
|
||||
attr->vlan_vid[vlan_idx] = act->vlan.vid;
|
||||
attr->vlan_prio[vlan_idx] = act->vlan.prio;
|
||||
attr->vlan_proto[vlan_idx] = act->vlan.proto;
|
||||
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)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"vlan push action is not supported for vlan depth > 1");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
|
||||
} else {
|
||||
if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) &&
|
||||
(act->vlan.proto != htons(ETH_P_8021Q) ||
|
||||
act->vlan.prio)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "vlan push action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unexpected action id for VLAN");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
attr->total_vlan = vlan_idx + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mlx5e_tc_act_vlan_add_push_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct net_device **out_dev,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct net_device *vlan_dev = *out_dev;
|
||||
struct flow_action_entry vlan_act = {
|
||||
.id = FLOW_ACTION_VLAN_PUSH,
|
||||
.vlan.vid = vlan_dev_vlan_id(vlan_dev),
|
||||
.vlan.proto = vlan_dev_vlan_proto(vlan_dev),
|
||||
.vlan.prio = 0,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rcu_read_lock();
|
||||
*out_dev = dev_get_by_index_rcu(dev_net(vlan_dev), dev_get_iflink(vlan_dev));
|
||||
rcu_read_unlock();
|
||||
if (!*out_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (is_vlan_dev(*out_dev))
|
||||
err = mlx5e_tc_act_vlan_add_push_action(priv, attr, out_dev, extack);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
mlx5e_tc_act_vlan_add_pop_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct flow_action_entry vlan_act = {
|
||||
.id = FLOW_ACTION_VLAN_POP,
|
||||
};
|
||||
int nest_level, err = 0;
|
||||
|
||||
nest_level = attr->parse_attr->filter_dev->lower_level -
|
||||
priv->netdev->lower_level;
|
||||
while (nest_level--) {
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_act_can_offload_vlan(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
const struct flow_action_entry *act,
|
||||
int act_index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
tc_act_parse_vlan(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr)
|
||||
{
|
||||
struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
|
||||
int err;
|
||||
|
||||
if (act->id == FLOW_ACTION_VLAN_PUSH &&
|
||||
(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP)) {
|
||||
/* Replace vlan pop+push with vlan modify */
|
||||
attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
|
||||
err = mlx5e_tc_act_vlan_add_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB, act,
|
||||
attr->parse_attr, parse_state->hdrs,
|
||||
&attr->action, parse_state->extack);
|
||||
} else {
|
||||
err = parse_tc_vlan_action(priv, act, esw_attr, &attr->action,
|
||||
parse_state->extack);
|
||||
}
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
esw_attr->split_count = esw_attr->out_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mlx5e_tc_act mlx5e_tc_act_vlan = {
|
||||
.can_offload = tc_act_can_offload_vlan,
|
||||
.parse_action = tc_act_parse_vlan,
|
||||
};
|
30
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.h
Normal file
30
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||
|
||||
#ifndef __MLX5_EN_TC_ACT_VLAN_H__
|
||||
#define __MLX5_EN_TC_ACT_VLAN_H__
|
||||
|
||||
#include <net/flow_offload.h>
|
||||
#include "en/tc_priv.h"
|
||||
|
||||
struct pedit_headers_action;
|
||||
|
||||
int
|
||||
mlx5e_tc_act_vlan_add_push_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct net_device **out_dev,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
int
|
||||
mlx5e_tc_act_vlan_add_pop_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
int
|
||||
mlx5e_tc_act_vlan_add_rewrite_action(struct mlx5e_priv *priv, int namespace,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
struct pedit_headers_action *hdrs,
|
||||
u32 *action, struct netlink_ext_ack *extack);
|
||||
|
||||
#endif /* __MLX5_EN_TC_ACT_VLAN_H__ */
|
@ -0,0 +1,87 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
|
||||
#include <linux/if_vlan.h>
|
||||
#include "act.h"
|
||||
#include "vlan.h"
|
||||
#include "en/tc_priv.h"
|
||||
|
||||
struct pedit_headers_action;
|
||||
|
||||
int
|
||||
mlx5e_tc_act_vlan_add_rewrite_action(struct mlx5e_priv *priv, int namespace,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
struct pedit_headers_action *hdrs,
|
||||
u32 *action, struct netlink_ext_ack *extack)
|
||||
{
|
||||
u16 mask16 = VLAN_VID_MASK;
|
||||
u16 val16 = act->vlan.vid & VLAN_VID_MASK;
|
||||
const struct flow_action_entry pedit_act = {
|
||||
.id = FLOW_ACTION_MANGLE,
|
||||
.mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH,
|
||||
.mangle.offset = offsetof(struct vlan_ethhdr, h_vlan_TCI),
|
||||
.mangle.mask = ~(u32)be16_to_cpu(*(__be16 *)&mask16),
|
||||
.mangle.val = (u32)be16_to_cpu(*(__be16 *)&val16),
|
||||
};
|
||||
u8 match_prio_mask, match_prio_val;
|
||||
void *headers_c, *headers_v;
|
||||
int err;
|
||||
|
||||
headers_c = mlx5e_get_match_headers_criteria(*action, &parse_attr->spec);
|
||||
headers_v = mlx5e_get_match_headers_value(*action, &parse_attr->spec);
|
||||
|
||||
if (!(MLX5_GET(fte_match_set_lyr_2_4, headers_c, cvlan_tag) &&
|
||||
MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag))) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "VLAN rewrite action must have VLAN protocol match");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
match_prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
|
||||
match_prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
|
||||
if (act->vlan.prio != (match_prio_val & match_prio_mask)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Changing VLAN prio is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = mlx5e_tc_act_pedit_parse_action(priv, &pedit_act, namespace, parse_attr, hdrs,
|
||||
NULL, extack);
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_act_can_offload_vlan_mangle(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
const struct flow_action_entry *act,
|
||||
int act_index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
tc_act_parse_vlan_mangle(struct mlx5e_tc_act_parse_state *parse_state,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr)
|
||||
{
|
||||
enum mlx5_flow_namespace_type ns_type;
|
||||
int err;
|
||||
|
||||
ns_type = mlx5e_get_flow_namespace(parse_state->flow);
|
||||
err = mlx5e_tc_act_vlan_add_rewrite_action(priv, ns_type, act,
|
||||
attr->parse_attr, parse_state->hdrs,
|
||||
&attr->action, parse_state->extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ns_type == MLX5_FLOW_NAMESPACE_FDB)
|
||||
attr->esw_attr->split_count = attr->esw_attr->out_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mlx5e_tc_act mlx5e_tc_act_vlan_mangle = {
|
||||
.can_offload = tc_act_can_offload_vlan_mangle,
|
||||
.parse_action = tc_act_parse_vlan_mangle,
|
||||
};
|
@ -183,4 +183,8 @@ struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow);
|
||||
|
||||
struct mlx5e_tc_int_port_priv *
|
||||
mlx5e_get_int_port_priv(struct mlx5e_priv *priv);
|
||||
|
||||
void *mlx5e_get_match_headers_value(u32 flags, struct mlx5_flow_spec *spec);
|
||||
void *mlx5e_get_match_headers_criteria(u32 flags, struct mlx5_flow_spec *spec);
|
||||
|
||||
#endif /* __MLX5_EN_TC_PRIV_H__ */
|
||||
|
@ -61,7 +61,7 @@
|
||||
#include "en/tc_tun_encap.h"
|
||||
#include "en/tc/sample.h"
|
||||
#include "en/tc/act/act.h"
|
||||
#include "en/tc/act/pedit.h"
|
||||
#include "en/tc/act/vlan.h"
|
||||
#include "lib/devcom.h"
|
||||
#include "lib/geneve.h"
|
||||
#include "lib/fs_chains.h"
|
||||
@ -2051,16 +2051,14 @@ static void *get_match_outer_headers_value(struct mlx5_flow_spec *spec)
|
||||
outer_headers);
|
||||
}
|
||||
|
||||
static void *get_match_headers_value(u32 flags,
|
||||
struct mlx5_flow_spec *spec)
|
||||
void *mlx5e_get_match_headers_value(u32 flags, struct mlx5_flow_spec *spec)
|
||||
{
|
||||
return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
|
||||
get_match_inner_headers_value(spec) :
|
||||
get_match_outer_headers_value(spec);
|
||||
}
|
||||
|
||||
static void *get_match_headers_criteria(u32 flags,
|
||||
struct mlx5_flow_spec *spec)
|
||||
void *mlx5e_get_match_headers_criteria(u32 flags, struct mlx5_flow_spec *spec)
|
||||
{
|
||||
return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
|
||||
get_match_inner_headers_criteria(spec) :
|
||||
@ -2725,8 +2723,8 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
|
||||
u8 cmd;
|
||||
|
||||
mod_acts = &parse_attr->mod_hdr_acts;
|
||||
headers_c = get_match_headers_criteria(*action_flags, &parse_attr->spec);
|
||||
headers_v = get_match_headers_value(*action_flags, &parse_attr->spec);
|
||||
headers_c = mlx5e_get_match_headers_criteria(*action_flags, &parse_attr->spec);
|
||||
headers_v = mlx5e_get_match_headers_value(*action_flags, &parse_attr->spec);
|
||||
|
||||
set_masks = &hdrs[0].masks;
|
||||
add_masks = &hdrs[1].masks;
|
||||
@ -2998,8 +2996,8 @@ static bool modify_header_match_supported(struct mlx5e_priv *priv,
|
||||
u8 ip_proto;
|
||||
int i;
|
||||
|
||||
headers_c = get_match_headers_criteria(actions, spec);
|
||||
headers_v = get_match_headers_value(actions, spec);
|
||||
headers_c = mlx5e_get_match_headers_criteria(actions, spec);
|
||||
headers_v = mlx5e_get_match_headers_value(actions, spec);
|
||||
ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
|
||||
|
||||
/* for non-IP we only re-write MACs, so we're okay */
|
||||
@ -3127,50 +3125,6 @@ static bool same_vf_reps(struct mlx5e_priv *priv,
|
||||
priv->netdev == out_dev;
|
||||
}
|
||||
|
||||
static int add_vlan_rewrite_action(struct mlx5e_priv *priv, int namespace,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
struct pedit_headers_action *hdrs,
|
||||
u32 *action, struct netlink_ext_ack *extack)
|
||||
{
|
||||
u16 mask16 = VLAN_VID_MASK;
|
||||
u16 val16 = act->vlan.vid & VLAN_VID_MASK;
|
||||
const struct flow_action_entry pedit_act = {
|
||||
.id = FLOW_ACTION_MANGLE,
|
||||
.mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH,
|
||||
.mangle.offset = offsetof(struct vlan_ethhdr, h_vlan_TCI),
|
||||
.mangle.mask = ~(u32)be16_to_cpu(*(__be16 *)&mask16),
|
||||
.mangle.val = (u32)be16_to_cpu(*(__be16 *)&val16),
|
||||
};
|
||||
u8 match_prio_mask, match_prio_val;
|
||||
void *headers_c, *headers_v;
|
||||
int err;
|
||||
|
||||
headers_c = get_match_headers_criteria(*action, &parse_attr->spec);
|
||||
headers_v = get_match_headers_value(*action, &parse_attr->spec);
|
||||
|
||||
if (!(MLX5_GET(fte_match_set_lyr_2_4, headers_c, cvlan_tag) &&
|
||||
MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag))) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"VLAN rewrite action must have VLAN protocol match");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
match_prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
|
||||
match_prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
|
||||
if (act->vlan.prio != (match_prio_val & match_prio_mask)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Changing VLAN prio is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = mlx5e_tc_act_pedit_parse_action(priv, &pedit_act, namespace, parse_attr, hdrs,
|
||||
NULL, extack);
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
add_vlan_prio_tag_rewrite_action(struct mlx5e_priv *priv,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
@ -3181,18 +3135,18 @@ add_vlan_prio_tag_rewrite_action(struct mlx5e_priv *priv,
|
||||
.vlan.vid = 0,
|
||||
.vlan.prio =
|
||||
MLX5_GET(fte_match_set_lyr_2_4,
|
||||
get_match_headers_value(*action,
|
||||
&parse_attr->spec),
|
||||
mlx5e_get_match_headers_value(*action,
|
||||
&parse_attr->spec),
|
||||
first_prio) &
|
||||
MLX5_GET(fte_match_set_lyr_2_4,
|
||||
get_match_headers_criteria(*action,
|
||||
&parse_attr->spec),
|
||||
mlx5e_get_match_headers_criteria(*action,
|
||||
&parse_attr->spec),
|
||||
first_prio),
|
||||
};
|
||||
|
||||
return add_vlan_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB,
|
||||
&prio_tag_act, parse_attr, hdrs, action,
|
||||
extack);
|
||||
return mlx5e_tc_act_vlan_add_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB,
|
||||
&prio_tag_act, parse_attr, hdrs, action,
|
||||
extack);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -3280,15 +3234,6 @@ parse_tc_nic_actions(struct mlx5e_priv *priv,
|
||||
|
||||
flow_action_for_each(i, act, flow_action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_VLAN_MANGLE:
|
||||
err = add_vlan_rewrite_action(priv,
|
||||
MLX5_FLOW_NAMESPACE_KERNEL,
|
||||
act, parse_attr, hdrs,
|
||||
&attr->action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
break;
|
||||
case FLOW_ACTION_REDIRECT: {
|
||||
struct net_device *peer_dev = act->dev;
|
||||
|
||||
@ -3362,72 +3307,6 @@ static bool is_merged_eswitch_vfs(struct mlx5e_priv *priv,
|
||||
same_hw_devs(priv, peer_priv));
|
||||
}
|
||||
|
||||
static int parse_tc_vlan_action(struct mlx5e_priv *priv,
|
||||
const struct flow_action_entry *act,
|
||||
struct mlx5_esw_flow_attr *attr,
|
||||
u32 *action,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u8 vlan_idx = attr->total_vlan;
|
||||
|
||||
if (vlan_idx >= MLX5_FS_VLAN_DEPTH) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Total vlans used is greater than supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_VLAN_POP:
|
||||
if (vlan_idx) {
|
||||
if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
|
||||
MLX5_FS_VLAN_DEPTH)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"vlan pop action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
|
||||
} else {
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
|
||||
}
|
||||
break;
|
||||
case FLOW_ACTION_VLAN_PUSH:
|
||||
attr->vlan_vid[vlan_idx] = act->vlan.vid;
|
||||
attr->vlan_prio[vlan_idx] = act->vlan.prio;
|
||||
attr->vlan_proto[vlan_idx] = act->vlan.proto;
|
||||
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)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"vlan push action is not supported for vlan depth > 1");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
|
||||
} else {
|
||||
if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) &&
|
||||
(act->vlan.proto != htons(ETH_P_8021Q) ||
|
||||
act->vlan.prio)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"vlan push action is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unexpected action id for VLAN");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
attr->total_vlan = vlan_idx + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device *get_fdb_out_dev(struct net_device *uplink_dev,
|
||||
struct net_device *out_dev)
|
||||
{
|
||||
@ -3450,57 +3329,6 @@ static struct net_device *get_fdb_out_dev(struct net_device *uplink_dev,
|
||||
return fdb_out_dev;
|
||||
}
|
||||
|
||||
static int add_vlan_push_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct net_device **out_dev,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct net_device *vlan_dev = *out_dev;
|
||||
struct flow_action_entry vlan_act = {
|
||||
.id = FLOW_ACTION_VLAN_PUSH,
|
||||
.vlan.vid = vlan_dev_vlan_id(vlan_dev),
|
||||
.vlan.proto = vlan_dev_vlan_proto(vlan_dev),
|
||||
.vlan.prio = 0,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rcu_read_lock();
|
||||
*out_dev = dev_get_by_index_rcu(dev_net(vlan_dev), dev_get_iflink(vlan_dev));
|
||||
rcu_read_unlock();
|
||||
if (!*out_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (is_vlan_dev(*out_dev))
|
||||
err = add_vlan_push_action(priv, attr, out_dev, extack);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int add_vlan_pop_action(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_attr *attr,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct flow_action_entry vlan_act = {
|
||||
.id = FLOW_ACTION_VLAN_POP,
|
||||
};
|
||||
int nest_level, err = 0;
|
||||
|
||||
nest_level = attr->parse_attr->filter_dev->lower_level -
|
||||
priv->netdev->lower_level;
|
||||
while (nest_level--) {
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr,
|
||||
&attr->action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool same_hw_reps(struct mlx5e_priv *priv,
|
||||
struct net_device *peer_netdev)
|
||||
{
|
||||
@ -3824,13 +3652,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
||||
return -ENODEV;
|
||||
|
||||
if (is_vlan_dev(out_dev)) {
|
||||
err = add_vlan_push_action(priv, attr, &out_dev, extack);
|
||||
err = mlx5e_tc_act_vlan_add_push_action(priv, attr,
|
||||
&out_dev,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (is_vlan_dev(parse_attr->filter_dev)) {
|
||||
err = add_vlan_pop_action(priv, attr, extack);
|
||||
err = mlx5e_tc_act_vlan_add_pop_action(priv, attr,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@ -3887,35 +3718,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FLOW_ACTION_VLAN_PUSH:
|
||||
case FLOW_ACTION_VLAN_POP:
|
||||
if (act->id == FLOW_ACTION_VLAN_PUSH &&
|
||||
(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP)) {
|
||||
/* Replace vlan pop+push with vlan modify */
|
||||
attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
|
||||
err = add_vlan_rewrite_action(priv,
|
||||
MLX5_FLOW_NAMESPACE_FDB,
|
||||
act, parse_attr, hdrs,
|
||||
&attr->action, extack);
|
||||
} else {
|
||||
err = parse_tc_vlan_action(priv, act, esw_attr, &attr->action,
|
||||
extack);
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
esw_attr->split_count = esw_attr->out_count;
|
||||
break;
|
||||
case FLOW_ACTION_VLAN_MANGLE:
|
||||
err = add_vlan_rewrite_action(priv,
|
||||
MLX5_FLOW_NAMESPACE_FDB,
|
||||
act, parse_attr, hdrs,
|
||||
&attr->action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
esw_attr->split_count = esw_attr->out_count;
|
||||
break;
|
||||
case FLOW_ACTION_CT:
|
||||
if (flow_flag_test(flow, SAMPLE)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported");
|
||||
|
Loading…
x
Reference in New Issue
Block a user