1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 4 #include "act.h" 5 #include "en/tc_priv.h" 6 #include "en/tc_ct.h" 7 8 static bool 9 tc_act_can_offload_ct(struct mlx5e_tc_act_parse_state *parse_state, 10 const struct flow_action_entry *act, 11 int act_index, 12 struct mlx5_flow_attr *attr) 13 { 14 bool clear_action = act->ct.action & TCA_CT_ACT_CLEAR; 15 struct netlink_ext_ack *extack = parse_state->extack; 16 17 if (parse_state->ct && !clear_action) { 18 NL_SET_ERR_MSG_MOD(extack, "Multiple CT actions are not supported"); 19 return false; 20 } 21 22 return true; 23 } 24 25 static int 26 tc_act_parse_ct(struct mlx5e_tc_act_parse_state *parse_state, 27 const struct flow_action_entry *act, 28 struct mlx5e_priv *priv, 29 struct mlx5_flow_attr *attr) 30 { 31 bool clear_action = act->ct.action & TCA_CT_ACT_CLEAR; 32 int err; 33 34 /* It's redundant to do ct clear more than once. */ 35 if (clear_action && parse_state->ct_clear) 36 return 0; 37 38 err = mlx5_tc_ct_parse_action(parse_state->ct_priv, attr, 39 &attr->parse_attr->mod_hdr_acts, 40 act, parse_state->extack); 41 if (err) 42 return err; 43 44 45 if (mlx5e_is_eswitch_flow(parse_state->flow)) 46 attr->esw_attr->split_count = attr->esw_attr->out_count; 47 48 if (clear_action) { 49 parse_state->ct_clear = true; 50 } else { 51 attr->flags |= MLX5_ATTR_FLAG_CT; 52 flow_flag_set(parse_state->flow, CT); 53 parse_state->ct = true; 54 } 55 56 return 0; 57 } 58 59 static int 60 tc_act_post_parse_ct(struct mlx5e_tc_act_parse_state *parse_state, 61 struct mlx5e_priv *priv, 62 struct mlx5_flow_attr *attr) 63 { 64 struct mlx5e_tc_mod_hdr_acts *mod_acts = &attr->parse_attr->mod_hdr_acts; 65 int err; 66 67 /* If ct action exist, we can ignore previous ct_clear actions */ 68 if (parse_state->ct) 69 return 0; 70 71 if (parse_state->ct_clear) { 72 err = mlx5_tc_ct_set_ct_clear_regs(parse_state->ct_priv, mod_acts); 73 if (err) { 74 NL_SET_ERR_MSG_MOD(parse_state->extack, 75 "Failed to set registers for ct clear"); 76 return err; 77 } 78 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 79 80 /* Prevent handling of additional, redundant clear actions */ 81 parse_state->ct_clear = false; 82 } 83 84 return 0; 85 } 86 87 static bool 88 tc_act_is_multi_table_act_ct(struct mlx5e_priv *priv, 89 const struct flow_action_entry *act, 90 struct mlx5_flow_attr *attr) 91 { 92 if (act->ct.action & TCA_CT_ACT_CLEAR) 93 return false; 94 95 return true; 96 } 97 98 struct mlx5e_tc_act mlx5e_tc_act_ct = { 99 .can_offload = tc_act_can_offload_ct, 100 .parse_action = tc_act_parse_ct, 101 .is_multi_table_act = tc_act_is_multi_table_act_ct, 102 .post_parse = tc_act_post_parse_ct, 103 }; 104 105