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/post_act.h" 6 #include "en/tc_priv.h" 7 #include "mlx5_core.h" 8 9 static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = { 10 [FLOW_ACTION_ACCEPT] = &mlx5e_tc_act_accept, 11 [FLOW_ACTION_DROP] = &mlx5e_tc_act_drop, 12 [FLOW_ACTION_TRAP] = &mlx5e_tc_act_trap, 13 [FLOW_ACTION_GOTO] = &mlx5e_tc_act_goto, 14 [FLOW_ACTION_REDIRECT] = &mlx5e_tc_act_mirred, 15 [FLOW_ACTION_MIRRED] = &mlx5e_tc_act_mirred, 16 [FLOW_ACTION_REDIRECT_INGRESS] = &mlx5e_tc_act_redirect_ingress, 17 [FLOW_ACTION_VLAN_PUSH] = &mlx5e_tc_act_vlan, 18 [FLOW_ACTION_VLAN_POP] = &mlx5e_tc_act_vlan, 19 [FLOW_ACTION_VLAN_MANGLE] = &mlx5e_tc_act_vlan_mangle, 20 [FLOW_ACTION_TUNNEL_ENCAP] = &mlx5e_tc_act_tun_encap, 21 [FLOW_ACTION_TUNNEL_DECAP] = &mlx5e_tc_act_tun_decap, 22 [FLOW_ACTION_MANGLE] = &mlx5e_tc_act_pedit, 23 [FLOW_ACTION_ADD] = &mlx5e_tc_act_pedit, 24 [FLOW_ACTION_CSUM] = &mlx5e_tc_act_csum, 25 [FLOW_ACTION_PTYPE] = &mlx5e_tc_act_ptype, 26 [FLOW_ACTION_SAMPLE] = &mlx5e_tc_act_sample, 27 [FLOW_ACTION_POLICE] = &mlx5e_tc_act_police, 28 [FLOW_ACTION_CT] = &mlx5e_tc_act_ct, 29 [FLOW_ACTION_MPLS_PUSH] = &mlx5e_tc_act_mpls_push, 30 [FLOW_ACTION_MPLS_POP] = &mlx5e_tc_act_mpls_pop, 31 [FLOW_ACTION_VLAN_PUSH_ETH] = &mlx5e_tc_act_vlan, 32 [FLOW_ACTION_VLAN_POP_ETH] = &mlx5e_tc_act_vlan, 33 }; 34 35 static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = { 36 [FLOW_ACTION_ACCEPT] = &mlx5e_tc_act_accept, 37 [FLOW_ACTION_DROP] = &mlx5e_tc_act_drop, 38 [FLOW_ACTION_GOTO] = &mlx5e_tc_act_goto, 39 [FLOW_ACTION_REDIRECT] = &mlx5e_tc_act_mirred_nic, 40 [FLOW_ACTION_MANGLE] = &mlx5e_tc_act_pedit, 41 [FLOW_ACTION_ADD] = &mlx5e_tc_act_pedit, 42 [FLOW_ACTION_CSUM] = &mlx5e_tc_act_csum, 43 [FLOW_ACTION_MARK] = &mlx5e_tc_act_mark, 44 [FLOW_ACTION_CT] = &mlx5e_tc_act_ct, 45 }; 46 47 /** 48 * mlx5e_tc_act_get() - Get an action parser for an action id. 49 * @act_id: Flow action id. 50 * @ns_type: flow namespace type. 51 */ 52 struct mlx5e_tc_act * 53 mlx5e_tc_act_get(enum flow_action_id act_id, 54 enum mlx5_flow_namespace_type ns_type) 55 { 56 struct mlx5e_tc_act **tc_acts; 57 58 tc_acts = ns_type == MLX5_FLOW_NAMESPACE_FDB ? tc_acts_fdb : tc_acts_nic; 59 60 return tc_acts[act_id]; 61 } 62 63 /** 64 * mlx5e_tc_act_init_parse_state() - Init a new parse_state. 65 * @parse_state: Parsing state. 66 * @flow: mlx5e tc flow being handled. 67 * @flow_action: flow action to parse. 68 * @extack: to set an error msg. 69 * 70 * The same parse_state should be passed to action parsers 71 * for tracking the current parsing state. 72 */ 73 void 74 mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state, 75 struct mlx5e_tc_flow *flow, 76 struct flow_action *flow_action, 77 struct netlink_ext_ack *extack) 78 { 79 memset(parse_state, 0, sizeof(*parse_state)); 80 parse_state->flow = flow; 81 parse_state->extack = extack; 82 parse_state->flow_action = flow_action; 83 } 84 85 void 86 mlx5e_tc_act_reorder_flow_actions(struct flow_action *flow_action, 87 struct mlx5e_tc_flow_action *flow_action_reorder) 88 { 89 struct flow_action_entry *act; 90 int i, j = 0; 91 92 flow_action_for_each(i, act, flow_action) { 93 /* Add CT action to be first. */ 94 if (act->id == FLOW_ACTION_CT) 95 flow_action_reorder->entries[j++] = act; 96 } 97 98 flow_action_for_each(i, act, flow_action) { 99 if (act->id == FLOW_ACTION_CT) 100 continue; 101 flow_action_reorder->entries[j++] = act; 102 } 103 } 104 105 int 106 mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state, 107 struct flow_action *flow_action, 108 struct mlx5_flow_attr *attr, 109 enum mlx5_flow_namespace_type ns_type) 110 { 111 struct flow_action_entry *act; 112 struct mlx5e_tc_act *tc_act; 113 struct mlx5e_priv *priv; 114 int err = 0, i; 115 116 priv = parse_state->flow->priv; 117 118 flow_action_for_each(i, act, flow_action) { 119 tc_act = mlx5e_tc_act_get(act->id, ns_type); 120 if (!tc_act || !tc_act->post_parse) 121 continue; 122 123 err = tc_act->post_parse(parse_state, priv, attr); 124 if (err) 125 goto out; 126 } 127 128 out: 129 return err; 130 } 131 132 int 133 mlx5e_tc_act_set_next_post_act(struct mlx5e_tc_flow *flow, 134 struct mlx5_flow_attr *attr, 135 struct mlx5_flow_attr *next_attr) 136 { 137 struct mlx5_core_dev *mdev = flow->priv->mdev; 138 struct mlx5e_tc_mod_hdr_acts *mod_acts; 139 int err; 140 141 mod_acts = &attr->parse_attr->mod_hdr_acts; 142 143 /* Set handle on current post act rule to next post act rule. */ 144 err = mlx5e_tc_post_act_set_handle(mdev, next_attr->post_act_handle, mod_acts); 145 if (err) { 146 mlx5_core_warn(mdev, "Failed setting post action handle"); 147 return err; 148 } 149 150 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 151 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 152 153 return 0; 154 } 155