1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 4 #include <linux/if_vlan.h> 5 #include "act.h" 6 #include "vlan.h" 7 #include "en/tc_priv.h" 8 9 struct pedit_headers_action; 10 11 int 12 mlx5e_tc_act_vlan_add_rewrite_action(struct mlx5e_priv *priv, int namespace, 13 const struct flow_action_entry *act, 14 struct mlx5e_tc_flow_parse_attr *parse_attr, 15 struct pedit_headers_action *hdrs, 16 u32 *action, struct netlink_ext_ack *extack) 17 { 18 u16 mask16 = VLAN_VID_MASK; 19 u16 val16 = act->vlan.vid & VLAN_VID_MASK; 20 const struct flow_action_entry pedit_act = { 21 .id = FLOW_ACTION_MANGLE, 22 .mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH, 23 .mangle.offset = offsetof(struct vlan_ethhdr, h_vlan_TCI), 24 .mangle.mask = ~(u32)be16_to_cpu(*(__be16 *)&mask16), 25 .mangle.val = (u32)be16_to_cpu(*(__be16 *)&val16), 26 }; 27 u8 match_prio_mask, match_prio_val; 28 void *headers_c, *headers_v; 29 int err; 30 31 headers_c = mlx5e_get_match_headers_criteria(*action, &parse_attr->spec); 32 headers_v = mlx5e_get_match_headers_value(*action, &parse_attr->spec); 33 34 if (!(MLX5_GET(fte_match_set_lyr_2_4, headers_c, cvlan_tag) && 35 MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag))) { 36 NL_SET_ERR_MSG_MOD(extack, "VLAN rewrite action must have VLAN protocol match"); 37 return -EOPNOTSUPP; 38 } 39 40 match_prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio); 41 match_prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio); 42 if (act->vlan.prio != (match_prio_val & match_prio_mask)) { 43 NL_SET_ERR_MSG_MOD(extack, "Changing VLAN prio is not supported"); 44 return -EOPNOTSUPP; 45 } 46 47 err = mlx5e_tc_act_pedit_parse_action(priv, &pedit_act, namespace, parse_attr, hdrs, 48 NULL, extack); 49 *action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 50 51 return err; 52 } 53 54 static bool 55 tc_act_can_offload_vlan_mangle(struct mlx5e_tc_act_parse_state *parse_state, 56 const struct flow_action_entry *act, 57 int act_index) 58 { 59 return true; 60 } 61 62 static int 63 tc_act_parse_vlan_mangle(struct mlx5e_tc_act_parse_state *parse_state, 64 const struct flow_action_entry *act, 65 struct mlx5e_priv *priv, 66 struct mlx5_flow_attr *attr) 67 { 68 enum mlx5_flow_namespace_type ns_type; 69 int err; 70 71 ns_type = mlx5e_get_flow_namespace(parse_state->flow); 72 err = mlx5e_tc_act_vlan_add_rewrite_action(priv, ns_type, act, 73 attr->parse_attr, parse_state->hdrs, 74 &attr->action, parse_state->extack); 75 if (err) 76 return err; 77 78 if (ns_type == MLX5_FLOW_NAMESPACE_FDB) 79 attr->esw_attr->split_count = attr->esw_attr->out_count; 80 81 return 0; 82 } 83 84 struct mlx5e_tc_act mlx5e_tc_act_vlan_mangle = { 85 .can_offload = tc_act_can_offload_vlan_mangle, 86 .parse_action = tc_act_parse_vlan_mangle, 87 }; 88