1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 #include <linux/if_vlan.h>
7 #include "en/tc_priv.h"
10 add_vlan_prio_tag_rewrite_action(struct mlx5e_priv *priv,
11 struct mlx5e_tc_flow_parse_attr *parse_attr,
12 u32 *action, struct netlink_ext_ack *extack)
14 const struct flow_action_entry prio_tag_act = {
17 MLX5_GET(fte_match_set_lyr_2_4,
18 mlx5e_get_match_headers_value(*action,
21 MLX5_GET(fte_match_set_lyr_2_4,
22 mlx5e_get_match_headers_criteria(*action,
27 return mlx5e_tc_act_vlan_add_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB,
28 &prio_tag_act, parse_attr, action,
33 parse_tc_vlan_action(struct mlx5e_priv *priv,
34 const struct flow_action_entry *act,
35 struct mlx5_esw_flow_attr *attr,
37 struct netlink_ext_ack *extack,
38 struct mlx5e_tc_act_parse_state *parse_state)
40 u8 vlan_idx = attr->total_vlan;
42 if (vlan_idx >= MLX5_FS_VLAN_DEPTH) {
43 NL_SET_ERR_MSG_MOD(extack, "Total vlans used is greater than supported");
47 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, vlan_idx)) {
48 NL_SET_ERR_MSG_MOD(extack, "firmware vlan actions is not supported");
53 case FLOW_ACTION_VLAN_POP:
55 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
57 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
59 case FLOW_ACTION_VLAN_PUSH:
60 attr->vlan_vid[vlan_idx] = act->vlan.vid;
61 attr->vlan_prio[vlan_idx] = act->vlan.prio;
62 attr->vlan_proto[vlan_idx] = act->vlan.proto;
63 if (!attr->vlan_proto[vlan_idx])
64 attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);
67 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
69 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
71 case FLOW_ACTION_VLAN_POP_ETH:
72 parse_state->eth_pop = true;
74 case FLOW_ACTION_VLAN_PUSH_ETH:
75 if (!flow_flag_test(parse_state->flow, L3_TO_L2_DECAP))
77 parse_state->eth_push = true;
78 memcpy(attr->eth.h_dest, act->vlan_push_eth.dst, ETH_ALEN);
79 memcpy(attr->eth.h_source, act->vlan_push_eth.src, ETH_ALEN);
82 NL_SET_ERR_MSG_MOD(extack, "Unexpected action id for VLAN");
86 attr->total_vlan = vlan_idx + 1;
92 mlx5e_tc_act_vlan_add_push_action(struct mlx5e_priv *priv,
93 struct mlx5_flow_attr *attr,
94 struct net_device **out_dev,
95 struct netlink_ext_ack *extack)
97 struct net_device *vlan_dev = *out_dev;
98 struct flow_action_entry vlan_act = {
99 .id = FLOW_ACTION_VLAN_PUSH,
100 .vlan.vid = vlan_dev_vlan_id(vlan_dev),
101 .vlan.proto = vlan_dev_vlan_proto(vlan_dev),
106 err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action, extack, NULL);
111 *out_dev = dev_get_by_index_rcu(dev_net(vlan_dev), dev_get_iflink(vlan_dev));
116 if (is_vlan_dev(*out_dev))
117 err = mlx5e_tc_act_vlan_add_push_action(priv, attr, out_dev, extack);
123 mlx5e_tc_act_vlan_add_pop_action(struct mlx5e_priv *priv,
124 struct mlx5_flow_attr *attr,
125 struct netlink_ext_ack *extack)
127 struct flow_action_entry vlan_act = {
128 .id = FLOW_ACTION_VLAN_POP,
130 int nest_level, err = 0;
132 nest_level = attr->parse_attr->filter_dev->lower_level -
133 priv->netdev->lower_level;
134 while (nest_level--) {
135 err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action,
145 tc_act_parse_vlan(struct mlx5e_tc_act_parse_state *parse_state,
146 const struct flow_action_entry *act,
147 struct mlx5e_priv *priv,
148 struct mlx5_flow_attr *attr)
150 struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
153 if (act->id == FLOW_ACTION_VLAN_PUSH &&
154 (attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP)) {
155 /* Replace vlan pop+push with vlan modify */
156 attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
157 err = mlx5e_tc_act_vlan_add_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB, act,
158 attr->parse_attr, &attr->action,
159 parse_state->extack);
161 err = parse_tc_vlan_action(priv, act, esw_attr, &attr->action,
162 parse_state->extack, parse_state);
168 esw_attr->split_count = esw_attr->out_count;
169 parse_state->if_count = 0;
175 tc_act_post_parse_vlan(struct mlx5e_tc_act_parse_state *parse_state,
176 struct mlx5e_priv *priv,
177 struct mlx5_flow_attr *attr)
179 struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
180 struct netlink_ext_ack *extack = parse_state->extack;
181 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
184 if (MLX5_CAP_GEN(esw->dev, prio_tag_required) &&
185 attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) {
186 /* For prio tag mode, replace vlan pop with rewrite vlan prio
189 attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
190 err = add_vlan_prio_tag_rewrite_action(priv, parse_attr,
191 &attr->action, extack);
199 struct mlx5e_tc_act mlx5e_tc_act_vlan = {
200 .parse_action = tc_act_parse_vlan,
201 .post_parse = tc_act_post_parse_vlan,