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