Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include <cnxk_flow.h>
5 : : #include <cnxk_rep.h>
6 : :
7 : : #define IS_REP_BIT 7
8 : :
9 : : #define TNL_DCP_MATCH_ID 5
10 : : #define NRML_MATCH_ID 1
11 : :
12 : : const struct cnxk_rte_flow_term_info term[] = {
13 : : [RTE_FLOW_ITEM_TYPE_ETH] = {ROC_NPC_ITEM_TYPE_ETH, sizeof(struct rte_flow_item_eth)},
14 : : [RTE_FLOW_ITEM_TYPE_VLAN] = {ROC_NPC_ITEM_TYPE_VLAN, sizeof(struct rte_flow_item_vlan)},
15 : : [RTE_FLOW_ITEM_TYPE_E_TAG] = {ROC_NPC_ITEM_TYPE_E_TAG, sizeof(struct rte_flow_item_e_tag)},
16 : : [RTE_FLOW_ITEM_TYPE_IPV4] = {ROC_NPC_ITEM_TYPE_IPV4, sizeof(struct rte_flow_item_ipv4)},
17 : : [RTE_FLOW_ITEM_TYPE_IPV6] = {ROC_NPC_ITEM_TYPE_IPV6, sizeof(struct rte_flow_item_ipv6)},
18 : : [RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT,
19 : : sizeof(struct rte_flow_item_ipv6_frag_ext)},
20 : : [RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4] = {ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
21 : : sizeof(struct rte_flow_item_arp_eth_ipv4)},
22 : : [RTE_FLOW_ITEM_TYPE_MPLS] = {ROC_NPC_ITEM_TYPE_MPLS, sizeof(struct rte_flow_item_mpls)},
23 : : [RTE_FLOW_ITEM_TYPE_ICMP] = {ROC_NPC_ITEM_TYPE_ICMP, sizeof(struct rte_flow_item_icmp)},
24 : : [RTE_FLOW_ITEM_TYPE_UDP] = {ROC_NPC_ITEM_TYPE_UDP, sizeof(struct rte_flow_item_udp)},
25 : : [RTE_FLOW_ITEM_TYPE_TCP] = {ROC_NPC_ITEM_TYPE_TCP, sizeof(struct rte_flow_item_tcp)},
26 : : [RTE_FLOW_ITEM_TYPE_SCTP] = {ROC_NPC_ITEM_TYPE_SCTP, sizeof(struct rte_flow_item_sctp)},
27 : : [RTE_FLOW_ITEM_TYPE_ESP] = {ROC_NPC_ITEM_TYPE_ESP, sizeof(struct rte_flow_item_esp)},
28 : : [RTE_FLOW_ITEM_TYPE_GRE] = {ROC_NPC_ITEM_TYPE_GRE, sizeof(struct rte_flow_item_gre)},
29 : : [RTE_FLOW_ITEM_TYPE_NVGRE] = {ROC_NPC_ITEM_TYPE_NVGRE, sizeof(struct rte_flow_item_nvgre)},
30 : : [RTE_FLOW_ITEM_TYPE_VXLAN] = {ROC_NPC_ITEM_TYPE_VXLAN, sizeof(struct rte_flow_item_vxlan)},
31 : : [RTE_FLOW_ITEM_TYPE_GTPC] = {ROC_NPC_ITEM_TYPE_GTPC, sizeof(struct rte_flow_item_gtp)},
32 : : [RTE_FLOW_ITEM_TYPE_GTPU] = {ROC_NPC_ITEM_TYPE_GTPU, sizeof(struct rte_flow_item_gtp)},
33 : : [RTE_FLOW_ITEM_TYPE_GENEVE] = {ROC_NPC_ITEM_TYPE_GENEVE,
34 : : sizeof(struct rte_flow_item_geneve)},
35 : : [RTE_FLOW_ITEM_TYPE_VXLAN_GPE] = {ROC_NPC_ITEM_TYPE_VXLAN_GPE,
36 : : sizeof(struct rte_flow_item_vxlan_gpe)},
37 : : [RTE_FLOW_ITEM_TYPE_IPV6_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_EXT,
38 : : sizeof(struct rte_flow_item_ipv6_ext)},
39 : : [RTE_FLOW_ITEM_TYPE_VOID] = {ROC_NPC_ITEM_TYPE_VOID, 0},
40 : : [RTE_FLOW_ITEM_TYPE_ANY] = {ROC_NPC_ITEM_TYPE_ANY, 0},
41 : : [RTE_FLOW_ITEM_TYPE_GRE_KEY] = {ROC_NPC_ITEM_TYPE_GRE_KEY, sizeof(uint32_t)},
42 : : [RTE_FLOW_ITEM_TYPE_HIGIG2] = {ROC_NPC_ITEM_TYPE_HIGIG2,
43 : : sizeof(struct rte_flow_item_higig2_hdr)},
44 : : [RTE_FLOW_ITEM_TYPE_RAW] = {ROC_NPC_ITEM_TYPE_RAW, sizeof(struct rte_flow_item_raw)},
45 : : [RTE_FLOW_ITEM_TYPE_MARK] = {ROC_NPC_ITEM_TYPE_MARK, sizeof(struct rte_flow_item_mark)},
46 : : [RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT,
47 : : sizeof(struct rte_flow_item_ipv6_routing_ext)},
48 : : [RTE_FLOW_ITEM_TYPE_TX_QUEUE] = {ROC_NPC_ITEM_TYPE_TX_QUEUE,
49 : : sizeof(struct rte_flow_item_tx_queue)},
50 : : [RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT] = {ROC_NPC_ITEM_TYPE_REPRESENTED_PORT,
51 : : sizeof(struct rte_flow_item_ethdev)},
52 : : [RTE_FLOW_ITEM_TYPE_PPPOES] = {ROC_NPC_ITEM_TYPE_PPPOES,
53 : : sizeof(struct rte_flow_item_pppoe)}};
54 : :
55 : : static int
56 : 0 : npc_rss_action_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
57 : : const struct rte_flow_action *act)
58 : : {
59 : : const struct rte_flow_action_rss *rss;
60 : :
61 : 0 : rss = (const struct rte_flow_action_rss *)act->conf;
62 : :
63 [ # # ]: 0 : if (attr->egress) {
64 : 0 : plt_err("No support of RSS in egress");
65 : 0 : return -EINVAL;
66 : : }
67 : :
68 [ # # ]: 0 : if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
69 : 0 : plt_err("multi-queue mode is disabled");
70 : 0 : return -ENOTSUP;
71 : : }
72 : :
73 [ # # # # ]: 0 : if (!rss || !rss->queue_num) {
74 : 0 : plt_err("no valid queues");
75 : 0 : return -EINVAL;
76 : : }
77 : :
78 [ # # ]: 0 : if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
79 : 0 : plt_err("non-default RSS hash functions are not supported");
80 : 0 : return -ENOTSUP;
81 : : }
82 : :
83 [ # # ]: 0 : if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
84 : 0 : plt_err("RSS hash key too large");
85 : 0 : return -ENOTSUP;
86 : : }
87 : :
88 : : return 0;
89 : : }
90 : :
91 : : static void
92 : : npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev, const struct roc_npc_action *rss_action,
93 : : uint32_t *flowkey_cfg, uint64_t default_rss_types)
94 : : {
95 : : const struct roc_npc_action_rss *rss;
96 : : uint64_t rss_types;
97 : :
98 : : rss = (const struct roc_npc_action_rss *)rss_action->conf;
99 : 0 : rss_types = rss->types;
100 : : /* If no RSS types are specified, use default one */
101 : 0 : if (rss_types == 0)
102 : : rss_types = default_rss_types;
103 : :
104 : 0 : *flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss_types, rss->level);
105 : 0 : }
106 : :
107 : : static int
108 : 0 : npc_parse_port_id_action(struct rte_eth_dev *eth_dev, const struct rte_flow_action *action,
109 : : uint16_t *dst_pf_func, uint16_t *dst_channel)
110 : : {
111 : : const struct rte_flow_action_port_id *port_act;
112 : : struct rte_eth_dev *portid_eth_dev;
113 : : char if_name[RTE_ETH_NAME_MAX_LEN];
114 : : struct cnxk_eth_dev *hw_dst;
115 : : struct roc_npc *roc_npc_dst;
116 : : int rc = 0;
117 : :
118 : 0 : port_act = (const struct rte_flow_action_port_id *)action->conf;
119 : :
120 : 0 : rc = rte_eth_dev_get_name_by_port(port_act->id, if_name);
121 [ # # ]: 0 : if (rc) {
122 : 0 : plt_err("Name not found for output port id");
123 : 0 : goto err_exit;
124 : : }
125 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
126 [ # # ]: 0 : if (!portid_eth_dev) {
127 : 0 : plt_err("eth_dev not found for output port id");
128 : 0 : goto err_exit;
129 : : }
130 [ # # ]: 0 : if (strcmp(portid_eth_dev->device->driver->name, eth_dev->device->driver->name) != 0) {
131 : 0 : plt_err("Output port not under same driver");
132 : 0 : goto err_exit;
133 : : }
134 : 0 : hw_dst = portid_eth_dev->data->dev_private;
135 : : roc_npc_dst = &hw_dst->npc;
136 : 0 : *dst_pf_func = roc_npc_dst->pf_func;
137 : 0 : *dst_channel = hw_dst->npc.channel;
138 : :
139 : 0 : return 0;
140 : :
141 : : err_exit:
142 : : return -EINVAL;
143 : : }
144 : :
145 : : static int
146 : 0 : roc_npc_parse_sample_subaction(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[],
147 : : struct roc_npc_action_sample *sample_action)
148 : : {
149 : 0 : uint16_t dst_pf_func = 0, dst_channel = 0;
150 : : const struct roc_npc_action_vf *vf_act;
151 : : int rc = 0, count = 0;
152 : : bool is_empty = true;
153 : :
154 [ # # ]: 0 : if (sample_action->ratio != 1) {
155 : 0 : plt_err("Sample ratio must be 1");
156 : 0 : return -EINVAL;
157 : : }
158 : :
159 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
160 : : is_empty = false;
161 [ # # # # ]: 0 : switch (actions->type) {
162 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
163 : 0 : count++;
164 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_PF;
165 : 0 : break;
166 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
167 : 0 : count++;
168 : 0 : vf_act = (const struct roc_npc_action_vf *)actions->conf;
169 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_VF;
170 : 0 : sample_action->pf_func = vf_act->id & NPC_PFVF_FUNC_MASK;
171 : 0 : break;
172 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
173 : 0 : rc = npc_parse_port_id_action(eth_dev, actions, &dst_pf_func, &dst_channel);
174 [ # # ]: 0 : if (rc)
175 : : return -EINVAL;
176 : :
177 : 0 : count++;
178 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_PORT_ID;
179 : 0 : sample_action->pf_func = dst_pf_func;
180 : 0 : sample_action->channel = dst_channel;
181 : 0 : break;
182 : 0 : default:
183 : 0 : continue;
184 : : }
185 : : }
186 : :
187 [ # # ]: 0 : if (count > 1 || is_empty)
188 : 0 : return -EINVAL;
189 : :
190 : : return 0;
191 : : }
192 : :
193 : : static int
194 : 0 : append_mark_action(struct roc_npc_action *in_actions, uint8_t has_tunnel_pattern,
195 : : uint64_t *free_allocs, int *act_cnt)
196 : : {
197 : : struct rte_flow_action_mark *act_mark;
198 : 0 : int i = *act_cnt, j = 0;
199 : :
200 : : /* Add Mark action */
201 : 0 : i++;
202 : 0 : act_mark = plt_zmalloc(sizeof(struct rte_flow_action_mark), 0);
203 [ # # ]: 0 : if (!act_mark) {
204 : 0 : plt_err("Error allocation memory");
205 : 0 : return -ENOMEM;
206 : : }
207 : :
208 [ # # ]: 0 : while (free_allocs[j] != 0)
209 : 0 : j++;
210 : 0 : free_allocs[j] = (uint64_t)act_mark;
211 : : /* Mark ID format: (tunnel type - VxLAN, Geneve << 6) | Tunnel decap */
212 : 0 : act_mark->id =
213 [ # # ]: 0 : has_tunnel_pattern ? ((has_tunnel_pattern << 6) | TNL_DCP_MATCH_ID) : NRML_MATCH_ID;
214 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
215 : 0 : in_actions[i].conf = (struct rte_flow_action_mark *)act_mark;
216 : :
217 : 0 : plt_rep_dbg("Assigned mark ID %x", act_mark->id);
218 : :
219 : 0 : *act_cnt = i;
220 : :
221 : 0 : return 0;
222 : : }
223 : :
224 : : static int
225 : 0 : append_rss_action(struct cnxk_eth_dev *dev, struct roc_npc_action *in_actions, uint16_t nb_rxq,
226 : : uint32_t *flowkey_cfg, uint64_t *free_allocs, uint16_t rss_repte_pf_func,
227 : : int *act_cnt)
228 : : {
229 : : struct roc_npc_action_rss *rss_conf;
230 : 0 : int i = *act_cnt, j = 0, l, rc = 0;
231 : : uint16_t *queue_arr;
232 : :
233 : 0 : rss_conf = plt_zmalloc(sizeof(struct roc_npc_action_rss), 0);
234 [ # # ]: 0 : if (!rss_conf) {
235 : 0 : plt_err("Failed to allocate memory for rss conf");
236 : : rc = -ENOMEM;
237 : 0 : goto fail;
238 : : }
239 : :
240 : : /* Add RSS action */
241 : 0 : rss_conf->queue_num = nb_rxq;
242 : 0 : queue_arr = plt_zmalloc(rss_conf->queue_num * sizeof(uint16_t), 0);
243 [ # # ]: 0 : if (!queue_arr) {
244 : 0 : plt_err("Failed to allocate memory for rss queue");
245 : : rc = -ENOMEM;
246 : 0 : goto free_rss;
247 : : }
248 : :
249 [ # # ]: 0 : for (l = 0; l < nb_rxq; l++)
250 : 0 : queue_arr[l] = l;
251 : 0 : rss_conf->queue = queue_arr;
252 : 0 : rss_conf->key = NULL;
253 : 0 : rss_conf->types = RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP;
254 : :
255 : 0 : i++;
256 : :
257 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
258 : 0 : in_actions[i].conf = (struct roc_npc_action_rss *)rss_conf;
259 : 0 : in_actions[i].rss_repte_pf_func = rss_repte_pf_func;
260 : :
261 : : npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg,
262 : : RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP);
263 : :
264 : 0 : *act_cnt = i;
265 : :
266 [ # # ]: 0 : while (free_allocs[j] != 0)
267 : 0 : j++;
268 : 0 : free_allocs[j] = (uint64_t)rss_conf;
269 : 0 : j++;
270 : 0 : free_allocs[j] = (uint64_t)queue_arr;
271 : :
272 : 0 : return 0;
273 : : free_rss:
274 : 0 : plt_free(rss_conf);
275 : : fail:
276 : : return rc;
277 : : }
278 : :
279 : : static int
280 [ # # ]: 0 : representor_rep_portid_action(struct roc_npc_action *in_actions, struct rte_eth_dev *eth_dev,
281 : : struct rte_eth_dev *portid_eth_dev,
282 : : enum rte_flow_action_type act_type, uint8_t rep_pattern,
283 : : uint16_t *dst_pf_func, bool is_rep, uint8_t has_tunnel_pattern,
284 : : uint64_t *free_allocs, int *act_cnt, uint32_t *flowkey_cfg)
285 : : {
286 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
287 : : struct rte_eth_dev *rep_eth_dev = portid_eth_dev;
288 : : struct rte_flow_action_of_set_vlan_vid *vlan_vid;
289 : : struct rte_flow_action_of_set_vlan_pcp *vlan_pcp;
290 : : struct rte_flow_action_of_push_vlan *push_vlan;
291 : : struct rte_flow_action_queue *act_q = NULL;
292 : : struct cnxk_rep_dev *rep_dev;
293 : : struct roc_npc *npc;
294 : : uint16_t vlan_tci;
295 : : int j = 0, rc;
296 : :
297 : : /* For inserting an action in the list */
298 [ # # ]: 0 : int i = *act_cnt;
299 : :
300 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
301 [ # # ]: 0 : if (!is_rep) {
302 : : dev = cnxk_eth_pmd_priv(eth_dev);
303 : 0 : npc = &dev->npc;
304 : : } else {
305 : 0 : npc = &rep_dev->parent_dev->npc;
306 : : }
307 [ # # ]: 0 : if (rep_pattern >> IS_REP_BIT) { /* Check for normal/representor port as action */
308 [ # # ]: 0 : if ((rep_pattern & 0x7f) == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
309 : : /* Case: Repr port pattern -> Default TX rule -> LBK ->
310 : : * Pattern RX LBK rule hit -> Action: send to new pf_func
311 : : */
312 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) {
313 : : /* New pf_func corresponds to ESW + queue corresponding to rep_id */
314 : 0 : act_q = plt_zmalloc(sizeof(struct rte_flow_action_queue), 0);
315 [ # # ]: 0 : if (!act_q) {
316 : 0 : plt_err("Error allocation memory");
317 : 0 : return -ENOMEM;
318 : : }
319 : 0 : act_q->index = rep_dev->rep_id;
320 : :
321 [ # # ]: 0 : while (free_allocs[j] != 0)
322 : 0 : j++;
323 : 0 : free_allocs[j] = (uint64_t)act_q;
324 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
325 : 0 : in_actions[i].conf = (struct rte_flow_action_queue *)act_q;
326 : 0 : npc->rep_act_pf_func = rep_dev->parent_dev->npc.pf_func;
327 : : } else {
328 : : /* New pf_func corresponds to hw_func of representee */
329 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
330 : 0 : npc->rep_act_pf_func = rep_dev->hw_func;
331 : 0 : *dst_pf_func = rep_dev->hw_func;
332 : : }
333 : : /* Additional action to strip the VLAN from packets received by LBK */
334 : 0 : i++;
335 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
336 : 0 : goto done;
337 : : }
338 : : /* Case: Repd port pattern -> TX Rule with VLAN -> LBK -> Default RX LBK rule hit
339 : : * base on vlan, if packet goes to ESW or actual pf_func -> Action :
340 : : * act port_representor: send to ESW respective using 1<<8 | rep_id as tci value
341 : : * act represented_port: send to actual port using rep_id as tci value.
342 : : */
343 : : /* Add RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN action */
344 : 0 : push_vlan = plt_zmalloc(sizeof(struct rte_flow_action_of_push_vlan), 0);
345 [ # # ]: 0 : if (!push_vlan) {
346 : 0 : plt_err("Error allocation memory");
347 : 0 : return -ENOMEM;
348 : : }
349 : :
350 [ # # ]: 0 : while (free_allocs[j] != 0)
351 : 0 : j++;
352 : 0 : free_allocs[j] = (uint64_t)push_vlan;
353 : 0 : push_vlan->ethertype = ntohs(ROC_ESWITCH_VLAN_TPID);
354 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
355 : 0 : in_actions[i].conf = (struct rte_flow_action_of_push_vlan *)push_vlan;
356 : 0 : i++;
357 : :
358 : : /* Add RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP action */
359 : 0 : vlan_pcp = plt_zmalloc(sizeof(struct rte_flow_action_of_set_vlan_pcp), 0);
360 [ # # ]: 0 : if (!vlan_pcp) {
361 : 0 : plt_err("Error allocation memory");
362 : 0 : return -ENOMEM;
363 : : }
364 : :
365 : 0 : free_allocs[j + 1] = (uint64_t)vlan_pcp;
366 : 0 : vlan_pcp->vlan_pcp = 0;
367 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
368 : 0 : in_actions[i].conf = (struct rte_flow_action_of_set_vlan_pcp *)vlan_pcp;
369 : 0 : i++;
370 : :
371 : : /* Add RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID action */
372 : 0 : vlan_vid = plt_zmalloc(sizeof(struct rte_flow_action_of_set_vlan_vid), 0);
373 [ # # ]: 0 : if (!vlan_vid) {
374 : 0 : plt_err("Error allocation memory");
375 : 0 : return -ENOMEM;
376 : : }
377 : :
378 : 0 : free_allocs[j + 2] = (uint64_t)vlan_vid;
379 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)
380 : 0 : vlan_tci = rep_dev->rep_id | (1ULL << CNXK_ESWITCH_VFPF_SHIFT);
381 : : else
382 : 0 : vlan_tci = rep_dev->rep_id;
383 : 0 : vlan_vid->vlan_vid = ntohs(vlan_tci);
384 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
385 : 0 : in_actions[i].conf = (struct rte_flow_action_of_set_vlan_vid *)vlan_vid;
386 : :
387 : : /* Change default channel to UCAST_CHAN (63) while sending */
388 : 0 : npc->rep_act_rep = true;
389 : : } else {
390 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) {
391 : : /* Case: Pattern wire port -> Pattern RX rule->
392 : : * Action: pf_func = ESW. queue = rep_id
393 : : */
394 : 0 : act_q = plt_zmalloc(sizeof(struct rte_flow_action_queue), 0);
395 [ # # ]: 0 : if (!act_q) {
396 : 0 : plt_err("Error allocation memory");
397 : 0 : return -ENOMEM;
398 : : }
399 [ # # ]: 0 : while (free_allocs[j] != 0)
400 : 0 : j++;
401 : 0 : free_allocs[j] = (uint64_t)act_q;
402 : 0 : act_q->index = rep_dev->rep_id;
403 : :
404 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
405 : 0 : in_actions[i].conf = (struct rte_flow_action_queue *)act_q;
406 : 0 : npc->rep_act_pf_func = rep_dev->parent_dev->npc.pf_func;
407 : : } else {
408 : : /* Case: Pattern wire port -> Pattern RX rule->
409 : : * Action: Receive at actual hw_func
410 : : */
411 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
412 : 0 : npc->rep_act_pf_func = rep_dev->hw_func;
413 : 0 : *dst_pf_func = rep_dev->hw_func;
414 : :
415 : : /* Append a mark action - needed to identify the flow */
416 : 0 : rc = append_mark_action(in_actions, has_tunnel_pattern, free_allocs, &i);
417 [ # # ]: 0 : if (rc)
418 : : return rc;
419 : : /* Append RSS action if representee has RSS enabled */
420 [ # # ]: 0 : if (rep_dev->nb_rxq > 1) {
421 : : /* PF can install rule for only its VF acting as representee */
422 [ # # # # ]: 0 : if (rep_dev->hw_func &&
423 : 0 : roc_eswitch_is_repte_pfs_vf(rep_dev->hw_func,
424 : 0 : roc_nix_get_pf_func(npc->roc_nix))) {
425 : 0 : rc = append_rss_action(dev, in_actions, rep_dev->nb_rxq,
426 : : flowkey_cfg, free_allocs,
427 : 0 : rep_dev->hw_func, &i);
428 [ # # ]: 0 : if (rc)
429 : : return rc;
430 : : }
431 : : }
432 : : }
433 : : }
434 : 0 : done:
435 : 0 : *act_cnt = i;
436 : :
437 : 0 : return 0;
438 : : }
439 : :
440 : : static int
441 : 0 : representor_portid_action(struct roc_npc_action *in_actions, struct rte_eth_dev *portid_eth_dev,
442 : : uint16_t *dst_pf_func, uint8_t has_tunnel_pattern, uint64_t *free_allocs,
443 : : int *act_cnt)
444 : : {
445 : : struct rte_eth_dev *rep_eth_dev = portid_eth_dev;
446 : : struct cnxk_rep_dev *rep_dev;
447 : : /* For inserting an action in the list */
448 : 0 : int i = *act_cnt, rc;
449 : :
450 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
451 : :
452 : 0 : *dst_pf_func = rep_dev->hw_func;
453 : :
454 : 0 : rc = append_mark_action(in_actions, has_tunnel_pattern, free_allocs, &i);
455 [ # # ]: 0 : if (rc)
456 : : return rc;
457 : :
458 : 0 : *act_cnt = i;
459 : 0 : plt_rep_dbg("Rep port %d ID %d rep_dev->hw_func 0x%x", rep_dev->port_id, rep_dev->rep_id,
460 : : rep_dev->hw_func);
461 : :
462 : 0 : return 0;
463 : : }
464 : :
465 : : static int
466 : 0 : cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
467 : : const struct rte_flow_action actions[], struct roc_npc_action in_actions[],
468 : : struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
469 : : uint16_t *dst_pf_func, uint64_t *npc_default_action, uint8_t has_tunnel_pattern,
470 : : bool is_rep, uint8_t rep_pattern, uint64_t *free_allocs, uint32_t flow_flags)
471 : : {
472 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
473 : : const struct rte_flow_action_queue *act_q = NULL;
474 : : const struct rte_flow_action_ethdev *act_ethdev;
475 : : const struct rte_flow_action_sample *act_sample;
476 : : const struct rte_flow_action_port_id *port_act;
477 : : struct rte_eth_dev *portid_eth_dev;
478 : : char if_name[RTE_ETH_NAME_MAX_LEN];
479 : : struct cnxk_eth_dev *hw_dst;
480 : : struct roc_npc *roc_npc_dst;
481 : : bool is_vf_action = false;
482 : 0 : int i = 0, rc = 0;
483 : : int rq;
484 : :
485 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
486 [ # # # # : 0 : switch (actions->type) {
# # # # #
# # # # #
# # # # #
# # ]
487 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
488 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VOID;
489 : 0 : break;
490 : :
491 : 0 : case RTE_FLOW_ACTION_TYPE_MARK:
492 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
493 : 0 : in_actions[i].conf = actions->conf;
494 : 0 : break;
495 : :
496 : 0 : case RTE_FLOW_ACTION_TYPE_FLAG:
497 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_FLAG;
498 : 0 : break;
499 : :
500 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
501 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_COUNT;
502 : 0 : break;
503 : :
504 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
505 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_DROP;
506 : 0 : break;
507 : :
508 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
509 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PF;
510 : 0 : break;
511 : :
512 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
513 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VF;
514 : 0 : in_actions[i].conf = actions->conf;
515 : : is_vf_action = true;
516 : 0 : break;
517 : :
518 : 0 : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
519 : : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
520 : 0 : in_actions[i].conf = actions->conf;
521 : : act_ethdev = (const struct rte_flow_action_ethdev *)actions->conf;
522 [ # # ]: 0 : if (rte_eth_dev_get_name_by_port(act_ethdev->port_id, if_name)) {
523 : 0 : plt_err("Name not found for output port id");
524 : 0 : goto err_exit;
525 : : }
526 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
527 [ # # ]: 0 : if (!portid_eth_dev) {
528 : 0 : plt_err("eth_dev not found for output port id");
529 : 0 : goto err_exit;
530 : : }
531 : :
532 : 0 : plt_rep_dbg("Rule installed by port %d if_name %s act_ethdev->port_id %d",
533 : : eth_dev->data->port_id, if_name, act_ethdev->port_id);
534 [ # # ]: 0 : if (cnxk_ethdev_is_representor(if_name)) {
535 [ # # ]: 0 : if (representor_rep_portid_action(in_actions, eth_dev,
536 : 0 : portid_eth_dev, actions->type,
537 : : rep_pattern, dst_pf_func,
538 : : is_rep, has_tunnel_pattern,
539 : : free_allocs, &i, flowkey_cfg)) {
540 : 0 : plt_err("Representor port action set failed");
541 : 0 : goto err_exit;
542 : : }
543 : : } else {
544 [ # # ]: 0 : if (actions->type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT)
545 : 0 : continue;
546 : : /* Normal port as represented_port as action not supported*/
547 : : return -ENOTSUP;
548 : : }
549 : : break;
550 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
551 : : /* No port ID action on representor ethdevs */
552 [ # # ]: 0 : if (is_rep)
553 : 0 : continue;
554 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
555 : 0 : in_actions[i].conf = actions->conf;
556 : : act_ethdev = (const struct rte_flow_action_ethdev *)actions->conf;
557 : : port_act = (const struct rte_flow_action_port_id *)actions->conf;
558 [ # # ]: 0 : if (rte_eth_dev_get_name_by_port(
559 : : actions->type != RTE_FLOW_ACTION_TYPE_PORT_ID ?
560 : : act_ethdev->port_id :
561 : 0 : port_act->id,
562 : : if_name)) {
563 : 0 : plt_err("Name not found for output port id");
564 : 0 : goto err_exit;
565 : : }
566 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
567 [ # # ]: 0 : if (!portid_eth_dev) {
568 : 0 : plt_err("eth_dev not found for output port id");
569 : 0 : goto err_exit;
570 : : }
571 : :
572 [ # # ]: 0 : if (cnxk_ethdev_is_representor(if_name)) {
573 : 0 : plt_rep_dbg("Representor port %d act port %d", port_act->id,
574 : : act_ethdev->port_id);
575 [ # # ]: 0 : if (representor_portid_action(in_actions, portid_eth_dev,
576 : : dst_pf_func, has_tunnel_pattern,
577 : : free_allocs, &i)) {
578 : 0 : plt_err("Representor port action set failed");
579 : 0 : goto err_exit;
580 : : }
581 : : } else {
582 : 0 : if (strcmp(portid_eth_dev->device->driver->name,
583 [ # # ]: 0 : eth_dev->device->driver->name) != 0) {
584 : 0 : plt_err("Output port not under same driver");
585 : 0 : goto err_exit;
586 : : }
587 : :
588 : 0 : hw_dst = portid_eth_dev->data->dev_private;
589 : 0 : roc_npc_mcam_default_rule_action_get(&hw_dst->npc,
590 : : npc_default_action);
591 : : roc_npc_dst = &hw_dst->npc;
592 : 0 : *dst_pf_func = roc_npc_dst->pf_func;
593 : : }
594 : : break;
595 : :
596 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
597 : 0 : act_q = (const struct rte_flow_action_queue *)actions->conf;
598 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
599 : 0 : in_actions[i].conf = actions->conf;
600 : 0 : break;
601 : :
602 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
603 : : /* No RSS action on representor ethdevs */
604 [ # # ]: 0 : if (is_rep)
605 : 0 : continue;
606 : 0 : rc = npc_rss_action_validate(eth_dev, attr, actions);
607 [ # # ]: 0 : if (rc)
608 : 0 : goto err_exit;
609 : :
610 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
611 : 0 : in_actions[i].conf = actions->conf;
612 : 0 : npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg,
613 [ # # ]: 0 : eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf);
614 : : break;
615 : :
616 : 0 : case RTE_FLOW_ACTION_TYPE_SECURITY:
617 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
618 : 0 : in_actions[i].conf = actions->conf;
619 : 0 : in_actions[i].is_non_inp = flow_flags & CNXK_FLOW_NON_INPLACE;
620 : 0 : in_actions[i].no_sec_action = flow_flags & CNXK_FLOW_NO_SEC_ACTION;
621 : 0 : break;
622 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
623 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
624 : 0 : break;
625 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
626 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
627 : 0 : in_actions[i].conf = actions->conf;
628 : 0 : break;
629 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
630 : 0 : in_actions[i].type =
631 : : ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
632 : 0 : in_actions[i].conf = actions->conf;
633 : 0 : break;
634 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
635 : 0 : in_actions[i].type =
636 : : ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
637 : 0 : in_actions[i].conf = actions->conf;
638 : 0 : break;
639 : 0 : case RTE_FLOW_ACTION_TYPE_METER:
640 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_METER;
641 : 0 : in_actions[i].conf = actions->conf;
642 : 0 : break;
643 : 0 : case RTE_FLOW_ACTION_TYPE_AGE:
644 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE;
645 : 0 : in_actions[i].conf = actions->conf;
646 : 0 : break;
647 : 0 : case RTE_FLOW_ACTION_TYPE_SAMPLE:
648 : 0 : act_sample = actions->conf;
649 : 0 : in_sample_actions->ratio = act_sample->ratio;
650 : 0 : rc = roc_npc_parse_sample_subaction(eth_dev, act_sample->actions,
651 : : in_sample_actions);
652 [ # # ]: 0 : if (rc) {
653 : 0 : plt_err("Sample subaction parsing failed.");
654 : 0 : goto err_exit;
655 : : }
656 : :
657 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_SAMPLE;
658 : 0 : in_actions[i].conf = in_sample_actions;
659 : 0 : break;
660 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
661 : 0 : continue;
662 : 0 : default:
663 : 0 : plt_npc_dbg("Action is not supported = %d", actions->type);
664 : 0 : goto err_exit;
665 : : }
666 : 0 : i++;
667 : : }
668 : :
669 [ # # ]: 0 : if (!is_vf_action && act_q) {
670 : 0 : rq = act_q->index;
671 [ # # ]: 0 : if (rq >= eth_dev->data->nb_rx_queues) {
672 : 0 : plt_npc_dbg("Invalid queue index");
673 : 0 : goto err_exit;
674 : : }
675 : : }
676 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_END;
677 : 0 : return 0;
678 : :
679 : : err_exit:
680 : : return -EINVAL;
681 : : }
682 : :
683 : : static int
684 : 0 : cnxk_map_pattern(struct rte_eth_dev *eth_dev, const struct rte_flow_item pattern[],
685 : : struct roc_npc_item_info in_pattern[], uint8_t *has_tunnel_pattern, bool is_rep,
686 : : uint8_t *rep_pattern, uint64_t *free_allocs)
687 : : {
688 : : const struct rte_flow_item_ethdev *rep_eth_dev;
689 : : struct rte_eth_dev *portid_eth_dev;
690 : : char if_name[RTE_ETH_NAME_MAX_LEN];
691 : : struct cnxk_eth_dev *hw_dst;
692 : : struct cnxk_rep_dev *rdev;
693 : : struct cnxk_eth_dev *dev;
694 : : struct roc_npc *npc;
695 : : int i = 0, j = 0;
696 : :
697 [ # # ]: 0 : if (!is_rep) {
698 : : dev = cnxk_eth_pmd_priv(eth_dev);
699 : 0 : npc = &dev->npc;
700 : : } else {
701 : : rdev = cnxk_rep_pmd_priv(eth_dev);
702 : 0 : npc = &rdev->parent_dev->npc;
703 : :
704 : 0 : npc->rep_npc = npc;
705 : 0 : npc->rep_port_id = rdev->port_id;
706 : 0 : npc->rep_pf_func = rdev->hw_func;
707 : : }
708 : :
709 [ # # ]: 0 : while (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
710 : 0 : in_pattern[i].spec = pattern->spec;
711 : 0 : in_pattern[i].last = pattern->last;
712 : 0 : in_pattern[i].mask = pattern->mask;
713 : 0 : in_pattern[i].type = term[pattern->type].item_type;
714 : 0 : in_pattern[i].size = term[pattern->type].item_size;
715 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT ||
716 : : pattern->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
717 : : rep_eth_dev = (const struct rte_flow_item_ethdev *)pattern->spec;
718 [ # # ]: 0 : if (rte_eth_dev_get_name_by_port(rep_eth_dev->port_id, if_name)) {
719 : 0 : plt_err("Name not found for output port id");
720 : 0 : goto fail;
721 : : }
722 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
723 [ # # ]: 0 : if (!portid_eth_dev) {
724 : 0 : plt_err("eth_dev not found for output port id");
725 : 0 : goto fail;
726 : : }
727 : 0 : *rep_pattern = pattern->type;
728 [ # # ]: 0 : if (cnxk_ethdev_is_representor(if_name)) {
729 : : /* Case where represented port not part of same
730 : : * app and represented by a representor port.
731 : : */
732 : : struct cnxk_rep_dev *rep_dev;
733 : : struct cnxk_eswitch_dev *eswitch_dev;
734 : :
735 : : rep_dev = cnxk_rep_pmd_priv(portid_eth_dev);
736 : 0 : eswitch_dev = rep_dev->parent_dev;
737 : 0 : npc->rep_npc = &eswitch_dev->npc;
738 : 0 : npc->rep_port_id = rep_eth_dev->port_id;
739 : 0 : npc->rep_pf_func = rep_dev->hw_func;
740 : :
741 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
742 : : struct rte_flow_item_vlan *vlan;
743 : :
744 : 0 : npc->rep_pf_func = eswitch_dev->npc.pf_func;
745 : : /* Add VLAN pattern corresponding to rep_id */
746 : 0 : i++;
747 : 0 : vlan = plt_zmalloc(sizeof(struct rte_flow_item_vlan), 0);
748 [ # # ]: 0 : if (!vlan) {
749 : 0 : plt_err("error allocation memory");
750 : 0 : return -ENOMEM;
751 : : }
752 : :
753 [ # # ]: 0 : while (free_allocs[j] != 0)
754 : 0 : j++;
755 : 0 : free_allocs[j] = (uint64_t)vlan;
756 : :
757 : 0 : npc->rep_rx_channel = ROC_ESWITCH_LBK_CHAN;
758 : 0 : vlan->hdr.vlan_tci = RTE_BE16(rep_dev->rep_id);
759 : 0 : in_pattern[i].spec = (struct rte_flow_item_vlan *)vlan;
760 : 0 : in_pattern[i].last = NULL;
761 : 0 : in_pattern[i].mask = &rte_flow_item_vlan_mask;
762 : 0 : in_pattern[i].type =
763 : : term[RTE_FLOW_ITEM_TYPE_VLAN].item_type;
764 : 0 : in_pattern[i].size =
765 : : term[RTE_FLOW_ITEM_TYPE_VLAN].item_size;
766 : : }
767 : 0 : *rep_pattern |= 1 << IS_REP_BIT;
768 : 0 : plt_rep_dbg("Represented port %d act port %d rep_dev->hw_func 0x%x",
769 : : rep_eth_dev->port_id, eth_dev->data->port_id,
770 : : rep_dev->hw_func);
771 : : } else {
772 : 0 : if (strcmp(portid_eth_dev->device->driver->name,
773 [ # # ]: 0 : eth_dev->device->driver->name) != 0) {
774 : 0 : plt_err("Output port not under same driver");
775 : 0 : goto fail;
776 : : }
777 : : /* Normal port as port_representor pattern can't be supported */
778 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
779 : : return -ENOTSUP;
780 : : /* Case where represented port part of same app
781 : : * as PF.
782 : : */
783 : 0 : hw_dst = portid_eth_dev->data->dev_private;
784 : 0 : npc->rep_npc = &hw_dst->npc;
785 : 0 : npc->rep_port_id = rep_eth_dev->port_id;
786 : 0 : npc->rep_pf_func = hw_dst->npc.pf_func;
787 : : }
788 : : }
789 : :
790 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
791 [ # # ]: 0 : pattern->type == RTE_FLOW_ITEM_TYPE_VXLAN_GPE ||
792 : : pattern->type == RTE_FLOW_ITEM_TYPE_GRE)
793 : 0 : *has_tunnel_pattern = pattern->type;
794 : :
795 : 0 : pattern++;
796 : 0 : i++;
797 : : }
798 : 0 : in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
799 : 0 : return 0;
800 : : fail:
801 : : return -EINVAL;
802 : : }
803 : :
804 : : static int
805 : 0 : cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
806 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
807 : : struct roc_npc_attr *in_attr, struct roc_npc_item_info in_pattern[],
808 : : struct roc_npc_action in_actions[],
809 : : struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
810 : : uint16_t *dst_pf_func, uint64_t *def_action, bool is_rep, uint64_t *free_allocs,
811 : : uint32_t flow_flags)
812 : : {
813 : 0 : uint8_t has_tunnel_pattern = 0, rep_pattern = 0;
814 : : int rc;
815 : :
816 : 0 : in_attr->priority = attr->priority;
817 : 0 : in_attr->ingress = attr->ingress;
818 : 0 : in_attr->egress = attr->egress;
819 : :
820 : 0 : rc = cnxk_map_pattern(eth_dev, pattern, in_pattern, &has_tunnel_pattern, is_rep,
821 : : &rep_pattern, free_allocs);
822 [ # # ]: 0 : if (rc) {
823 : 0 : plt_err("Failed to map pattern list");
824 : 0 : return rc;
825 : : }
826 : :
827 [ # # ]: 0 : if (attr->transfer) {
828 : : /* rep_pattern is used to identify if RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT
829 : : * OR RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR is defined + if pattern's portid is
830 : : * normal port or representor port.
831 : : * For normal port_id, rep_pattern = pattern-> type
832 : : * For representor port, rep_pattern = pattern-> type | 1 << IS_REP_BIT
833 : : */
834 [ # # # # ]: 0 : if (is_rep || rep_pattern) {
835 [ # # # # ]: 0 : if (rep_pattern == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT ||
836 : : ((rep_pattern & 0x7f) == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR))
837 : : /* If pattern is port_representor or pattern has normal port as
838 : : * represented port, install ingress rule.
839 : : */
840 : 0 : in_attr->ingress = attr->transfer;
841 : : else
842 : 0 : in_attr->egress = attr->transfer;
843 : : } else {
844 : 0 : in_attr->ingress = attr->transfer;
845 : : }
846 : : }
847 : :
848 : 0 : return cnxk_map_actions(eth_dev, attr, actions, in_actions, in_sample_actions, flowkey_cfg,
849 : : dst_pf_func, def_action, has_tunnel_pattern, is_rep, rep_pattern,
850 : : free_allocs, flow_flags);
851 : : }
852 : :
853 : : int
854 : 0 : cnxk_flow_validate_common(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
855 : : const struct rte_flow_item pattern[],
856 : : const struct rte_flow_action actions[], struct rte_flow_error *error,
857 : : bool is_rep, uint32_t flow_flags)
858 : : {
859 : : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
860 : : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
861 : : struct roc_npc_action_sample in_sample_action;
862 : 0 : uint64_t npc_default_action = 0;
863 : : struct cnxk_rep_dev *rep_dev;
864 : : struct roc_npc_attr in_attr;
865 : : uint64_t *free_allocs, sz;
866 : : struct cnxk_eth_dev *dev;
867 : : struct roc_npc_flow flow;
868 : 0 : uint16_t dst_pf_func = 0;
869 : 0 : uint32_t flowkey_cfg = 0;
870 : : struct roc_npc *npc = 0;
871 : : int rc, j;
872 : :
873 : : /* is_rep set for operation performed via representor ports */
874 [ # # ]: 0 : if (!is_rep) {
875 : : dev = cnxk_eth_pmd_priv(eth_dev);
876 : 0 : npc = &dev->npc;
877 : : /* Skip flow validation for MACsec. */
878 [ # # # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
879 : 0 : cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL)
880 : : return 0;
881 : : } else {
882 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
883 : 0 : npc = &rep_dev->parent_dev->npc;
884 : : }
885 : :
886 : : memset(&flow, 0, sizeof(flow));
887 : : memset(&in_sample_action, 0, sizeof(in_sample_action));
888 : 0 : flow.is_validate = true;
889 : :
890 : : sz = ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1;
891 : 0 : free_allocs = plt_zmalloc(sz * sizeof(uint64_t), 0);
892 [ # # ]: 0 : if (!free_allocs) {
893 : 0 : rte_flow_error_set(error, -ENOMEM, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
894 : : "Failed to map flow data");
895 : 0 : return -ENOMEM;
896 : : }
897 : 0 : rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
898 : : &in_sample_action, &flowkey_cfg, &dst_pf_func, &npc_default_action,
899 : : is_rep, free_allocs, flow_flags);
900 [ # # ]: 0 : if (rc) {
901 : 0 : rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
902 : : "Failed to map flow data");
903 : 0 : goto clean;
904 : : }
905 : :
906 : 0 : rc = roc_npc_flow_parse(npc, &in_attr, in_pattern, in_actions, &flow);
907 : :
908 [ # # ]: 0 : if (rc) {
909 : 0 : rte_flow_error_set(error, 0, rc, NULL,
910 : : "Flow validation failed");
911 : 0 : goto clean;
912 : : }
913 : 0 : clean:
914 : : /* Freeing the allocations done for additional patterns/actions */
915 [ # # # # ]: 0 : for (j = 0; (j < (int)sz) && free_allocs[j]; j++)
916 : 0 : plt_free((void *)free_allocs[j]);
917 : 0 : plt_free(free_allocs);
918 : :
919 : 0 : return rc;
920 : : }
921 : :
922 : : static int
923 [ # # ]: 0 : cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
924 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
925 : : struct rte_flow_error *error)
926 : : {
927 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
928 : : struct cnxk_eth_sec_sess *eth_sec = NULL;
929 : : uint32_t flow_flags = 0;
930 : :
931 [ # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY) {
932 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, actions[0].conf);
933 [ # # ]: 0 : if (eth_sec != NULL) {
934 [ # # ]: 0 : flow_flags = eth_sec->inb_oop ? CNXK_FLOW_NON_INPLACE : 0;
935 : 0 : flow_flags |= CNXK_FLOW_NO_SEC_ACTION;
936 : : }
937 : : }
938 : :
939 : 0 : return cnxk_flow_validate_common(eth_dev, attr, pattern, actions, error, false, flow_flags);
940 : : }
941 : :
942 : : struct roc_npc_flow *
943 : 0 : cnxk_flow_create_common(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
944 : : const struct rte_flow_item pattern[],
945 : : const struct rte_flow_action actions[], struct rte_flow_error *error,
946 : : bool is_rep, uint32_t flow_flags)
947 : : {
948 : 0 : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1] = {0};
949 : 0 : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT] = {0};
950 : : struct roc_npc_action_sample in_sample_action;
951 : : struct cnxk_rep_dev *rep_dev = NULL;
952 : : struct roc_npc_flow *flow = NULL;
953 : : struct cnxk_eth_dev *dev = NULL;
954 : 0 : uint64_t npc_default_action = 0;
955 : : struct roc_npc_attr in_attr;
956 : : struct roc_npc *npc = NULL;
957 : : uint64_t *free_allocs, sz;
958 : 0 : uint16_t dst_pf_func = 0;
959 : 0 : int errcode = 0;
960 : : int rc, j;
961 : :
962 : : /* is_rep set for operation performed via representor ports */
963 [ # # ]: 0 : if (!is_rep) {
964 : : dev = cnxk_eth_pmd_priv(eth_dev);
965 : 0 : npc = &dev->npc;
966 : : } else {
967 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
968 : 0 : npc = &rep_dev->parent_dev->npc;
969 : : }
970 : :
971 : : sz = ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1;
972 : 0 : free_allocs = plt_zmalloc(sz * sizeof(uint64_t), 0);
973 [ # # ]: 0 : if (!free_allocs) {
974 : 0 : rte_flow_error_set(error, -ENOMEM, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
975 : : "Failed to map flow data");
976 : 0 : return NULL;
977 : : }
978 : : memset(&in_sample_action, 0, sizeof(in_sample_action));
979 : : memset(&in_attr, 0, sizeof(struct roc_npc_attr));
980 : 0 : rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
981 : : &in_sample_action, &npc->flowkey_cfg_state, &dst_pf_func,
982 : : &npc_default_action, is_rep, free_allocs, flow_flags);
983 [ # # ]: 0 : if (rc) {
984 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
985 : : "Failed to map flow data");
986 : 0 : goto clean;
987 : : }
988 : :
989 : 0 : flow = roc_npc_flow_create(npc, &in_attr, in_pattern, in_actions, dst_pf_func,
990 : : npc_default_action, &errcode);
991 [ # # ]: 0 : if (errcode != 0) {
992 : 0 : rte_flow_error_set(error, errcode, errcode, NULL, roc_error_msg_get(errcode));
993 : 0 : goto clean;
994 : : }
995 : :
996 : 0 : clean:
997 : : /* Freeing the allocations done for additional patterns/actions */
998 [ # # # # ]: 0 : for (j = 0; (j < (int)sz) && free_allocs[j]; j++)
999 : 0 : plt_free((void *)free_allocs[j]);
1000 : 0 : plt_free(free_allocs);
1001 : :
1002 : 0 : return flow;
1003 : : }
1004 : :
1005 : : int
1006 : 0 : cnxk_flow_destroy_common(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
1007 : : struct rte_flow_error *error, bool is_rep)
1008 : : {
1009 : : struct cnxk_rep_dev *rep_dev;
1010 : : struct cnxk_eth_dev *dev;
1011 : : struct roc_npc *npc;
1012 : : int rc;
1013 : :
1014 : : /* is_rep set for operation performed via representor ports */
1015 [ # # ]: 0 : if (!is_rep) {
1016 : : dev = cnxk_eth_pmd_priv(eth_dev);
1017 : 0 : npc = &dev->npc;
1018 : : } else {
1019 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1020 : 0 : npc = &rep_dev->parent_dev->npc;
1021 : : }
1022 : :
1023 : 0 : rc = roc_npc_flow_destroy(npc, flow);
1024 [ # # ]: 0 : if (rc)
1025 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1026 : : "Flow Destroy failed");
1027 : 0 : return rc;
1028 : : }
1029 : :
1030 : : int
1031 : 0 : cnxk_flow_destroy(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
1032 : : struct rte_flow_error *error)
1033 : : {
1034 : 0 : return cnxk_flow_destroy_common(eth_dev, flow, error, false);
1035 : : }
1036 : :
1037 : : int
1038 : 0 : cnxk_flow_flush_common(struct rte_eth_dev *eth_dev, struct rte_flow_error *error, bool is_rep)
1039 : : {
1040 : : struct cnxk_rep_dev *rep_dev;
1041 : : struct cnxk_eth_dev *dev;
1042 : : struct roc_npc *npc;
1043 : : int rc;
1044 : :
1045 : : /* is_rep set for operation performed via representor ports */
1046 [ # # ]: 0 : if (!is_rep) {
1047 : : dev = cnxk_eth_pmd_priv(eth_dev);
1048 : 0 : npc = &dev->npc;
1049 : : } else {
1050 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1051 : 0 : npc = &rep_dev->parent_dev->npc;
1052 : : }
1053 : :
1054 : 0 : rc = roc_npc_mcam_free_all_resources(npc);
1055 [ # # ]: 0 : if (rc) {
1056 : 0 : rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1057 : : "Failed to flush filter");
1058 : 0 : return -rte_errno;
1059 : : }
1060 : :
1061 : : return 0;
1062 : : }
1063 : :
1064 : : static int
1065 : 0 : cnxk_flow_flush(struct rte_eth_dev *eth_dev, struct rte_flow_error *error)
1066 : : {
1067 : 0 : return cnxk_flow_flush_common(eth_dev, error, false);
1068 : : }
1069 : :
1070 : : int
1071 : 0 : cnxk_flow_query_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
1072 : : const struct rte_flow_action *action, void *data,
1073 : : struct rte_flow_error *error, bool is_rep)
1074 : : {
1075 : : struct rte_flow_query_count *query = data;
1076 : : struct roc_npc_flow *in_flow;
1077 : : struct cnxk_rep_dev *rep_dev;
1078 : : const char *errmsg = NULL;
1079 : : struct cnxk_eth_dev *dev;
1080 : : int errcode = ENOTSUP;
1081 : : struct roc_npc *npc;
1082 : : int rc;
1083 : :
1084 [ # # ]: 0 : if (flow == NULL) {
1085 : : errmsg = "Invalid flow handle";
1086 : : errcode = EINVAL;
1087 : 0 : goto err_exit;
1088 : : }
1089 : :
1090 : : /* is_rep set for operation performed via representor ports */
1091 [ # # ]: 0 : if (!is_rep) {
1092 : : dev = cnxk_eth_pmd_priv(eth_dev);
1093 : 0 : npc = &dev->npc;
1094 : : } else {
1095 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1096 : 0 : npc = &rep_dev->parent_dev->npc;
1097 : : }
1098 : :
1099 : : /* Let the roc layer resolve async/template handles to the underlying
1100 : : * roc_npc_flow (NULL until committed); else treat as a sync flow.
1101 : : */
1102 : 0 : in_flow = (struct roc_npc_flow *)flow;
1103 [ # # ]: 0 : if (!is_rep)
1104 : 0 : roc_npc_async_flow_resolve(npc, flow, &in_flow);
1105 : :
1106 [ # # ]: 0 : if (in_flow == NULL) {
1107 : : errmsg = "Flow is not committed yet";
1108 : : errcode = EINVAL;
1109 : 0 : goto err_exit;
1110 : : }
1111 : :
1112 [ # # ]: 0 : if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
1113 : : errmsg = "Only COUNT is supported in query";
1114 : 0 : goto err_exit;
1115 : : }
1116 : :
1117 [ # # ]: 0 : if (in_flow->ctr_id == NPC_COUNTER_NONE) {
1118 : : errmsg = "Counter is not available";
1119 : 0 : goto err_exit;
1120 : : }
1121 : :
1122 [ # # ]: 0 : if (in_flow->use_pre_alloc) {
1123 : 0 : rc = roc_npc_inl_mcam_read_counter(in_flow->ctr_id, &query->hits);
1124 : : } else {
1125 [ # # ]: 0 : if (roc_model_is_cn20k())
1126 : 0 : rc = roc_npc_mcam_get_stats(npc, in_flow, &query->hits);
1127 : : else
1128 : 0 : rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
1129 : : }
1130 [ # # ]: 0 : if (rc != 0) {
1131 : : errcode = EIO;
1132 : : errmsg = "Error reading flow counter";
1133 : 0 : goto err_exit;
1134 : : }
1135 : 0 : query->hits_set = 1;
1136 : 0 : query->bytes_set = 0;
1137 : :
1138 [ # # ]: 0 : if (query->reset) {
1139 [ # # ]: 0 : if (in_flow->use_pre_alloc)
1140 : 0 : rc = roc_npc_inl_mcam_clear_counter(in_flow->ctr_id);
1141 : : else
1142 : 0 : rc = roc_npc_mcam_clear_counter(npc, in_flow->ctr_id);
1143 : : }
1144 [ # # ]: 0 : if (rc != 0) {
1145 : : errcode = EIO;
1146 : : errmsg = "Error clearing flow counter";
1147 : 0 : goto err_exit;
1148 : : }
1149 : :
1150 : : return 0;
1151 : :
1152 : 0 : err_exit:
1153 : 0 : rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1154 : : NULL, errmsg);
1155 : 0 : return -rte_errno;
1156 : : }
1157 : :
1158 : : static int
1159 : 0 : cnxk_flow_query(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
1160 : : const struct rte_flow_action *action, void *data, struct rte_flow_error *error)
1161 : : {
1162 : 0 : return cnxk_flow_query_common(eth_dev, flow, action, data, error, false);
1163 : : }
1164 : :
1165 : : static int
1166 : 0 : cnxk_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused, int enable __rte_unused,
1167 : : struct rte_flow_error *error)
1168 : : {
1169 : : /* If we support, we need to un-install the default mcam
1170 : : * entry for this port.
1171 : : */
1172 : :
1173 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1174 : : "Flow isolation not supported");
1175 : :
1176 : 0 : return -rte_errno;
1177 : : }
1178 : :
1179 : : int
1180 : 0 : cnxk_flow_dev_dump_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow, FILE *file,
1181 : : struct rte_flow_error *error, bool is_rep)
1182 : : {
1183 : 0 : struct roc_npc_flow *in_flow = NULL;
1184 : : struct cnxk_eth_dev *dev = NULL;
1185 : : struct cnxk_rep_dev *rep_dev;
1186 : : struct roc_npc *npc;
1187 : :
1188 : : /* is_rep set for operation performed via representor ports */
1189 [ # # ]: 0 : if (!is_rep) {
1190 : : dev = cnxk_eth_pmd_priv(eth_dev);
1191 : 0 : npc = &dev->npc;
1192 : : } else {
1193 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1194 : 0 : npc = &rep_dev->parent_dev->npc;
1195 : : }
1196 : :
1197 [ # # ]: 0 : if (file == NULL) {
1198 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1199 : : "Invalid file");
1200 : 0 : return -rte_errno;
1201 : : }
1202 : :
1203 [ # # ]: 0 : if (flow != NULL) {
1204 : : /* Resolve async/template handles to the underlying roc_npc_flow;
1205 : : * else treat as a sync flow.
1206 : : */
1207 [ # # # # ]: 0 : if (is_rep || !roc_npc_async_flow_resolve(npc, flow, &in_flow))
1208 : 0 : in_flow = (struct roc_npc_flow *)flow;
1209 : :
1210 [ # # ]: 0 : if (in_flow == NULL)
1211 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1212 : : "flow is not committed yet");
1213 : :
1214 : 0 : roc_npc_flow_mcam_dump(file, npc, in_flow);
1215 : 0 : return 0;
1216 : : }
1217 : :
1218 : 0 : roc_npc_flow_dump(file, npc, -1);
1219 : :
1220 : 0 : return 0;
1221 : : }
1222 : : /* Configure async flow queues for the port. */
1223 : : int
1224 [ # # ]: 0 : cnxk_flow_configure(struct rte_eth_dev *eth_dev, const struct rte_flow_port_attr *port_attr,
1225 : : uint16_t nb_queue, const struct rte_flow_queue_attr *queue_attr[],
1226 : : struct rte_flow_error *err)
1227 : : {
1228 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1229 : : const struct roc_npc_flow_queue_attr **rptrs = NULL;
1230 : : struct roc_npc_flow_queue_attr *rattr = NULL;
1231 : 0 : struct roc_npc *npc = &dev->npc;
1232 : : uint16_t i;
1233 : : int rc;
1234 : :
1235 : : RTE_SET_USED(port_attr);
1236 : :
1237 : : /* Translate the rte queue attributes into roc_npc types; the roc
1238 : : * engine validates nb_queue == 0 and a NULL queue_attr.
1239 : : */
1240 [ # # ]: 0 : if (nb_queue != 0 && queue_attr != NULL) {
1241 : 0 : rattr = plt_zmalloc(nb_queue * sizeof(*rattr), 0);
1242 [ # # ]: 0 : if (rattr == NULL)
1243 : 0 : return rte_flow_error_set(err, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1244 : : NULL, "Failed to allocate flow queues");
1245 : :
1246 : 0 : rptrs = plt_zmalloc(nb_queue * sizeof(*rptrs), 0);
1247 [ # # ]: 0 : if (rptrs == NULL) {
1248 : 0 : plt_free(rattr);
1249 : 0 : return rte_flow_error_set(err, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1250 : : NULL, "Failed to allocate flow queues");
1251 : : }
1252 [ # # ]: 0 : for (i = 0; i < nb_queue; i++) {
1253 [ # # ]: 0 : if (queue_attr[i] != NULL) {
1254 : 0 : rattr[i].size = queue_attr[i]->size;
1255 : 0 : rptrs[i] = &rattr[i];
1256 : : } else {
1257 : 0 : rptrs[i] = NULL;
1258 : : }
1259 : : }
1260 : : }
1261 : :
1262 : 0 : rc = roc_npc_flow_configure(npc, nb_queue, rptrs);
1263 : :
1264 : 0 : plt_free(rattr);
1265 : 0 : plt_free(rptrs);
1266 : :
1267 [ # # ]: 0 : if (rc)
1268 : 0 : return rte_flow_error_set(err, -rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1269 : : "Failed to configure flow queues");
1270 : : return 0;
1271 : : }
1272 : :
1273 : : /* Deep-copy a spec/last/mask/conf payload into template-owned memory. */
1274 : : static int
1275 : 0 : cnxk_flow_dup_conf(void **copies, uint16_t *nb_copies, const void *src, size_t sz, const void **dst)
1276 : : {
1277 : : void *copy;
1278 : :
1279 [ # # ]: 0 : if (src == NULL || sz == 0) {
1280 : 0 : *dst = NULL;
1281 : 0 : return 0;
1282 : : }
1283 : 0 : copy = plt_zmalloc(sz, 0);
1284 [ # # ]: 0 : if (copy == NULL)
1285 : : return -ENOMEM;
1286 : : memcpy(copy, src, sz);
1287 : 0 : copies[(*nb_copies)++] = copy;
1288 : 0 : *dst = copy;
1289 : 0 : return 0;
1290 : : }
1291 : :
1292 : : struct rte_flow_pattern_template *
1293 [ # # ]: 0 : cnxk_flow_pattern_template_create(struct rte_eth_dev *eth_dev,
1294 : : const struct rte_flow_pattern_template_attr *attr,
1295 : : const struct rte_flow_item pattern[],
1296 : : struct rte_flow_error *error)
1297 : : {
1298 : : const char *errmsg = "Failed to allocate pattern template";
1299 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1300 : : struct cnxk_flow_pattern_template *tmpl = NULL;
1301 : : struct roc_npc_pattern_template_attr roc_attr;
1302 : : struct roc_npc_item_info *roc_pattern = NULL;
1303 : : int i, nb_items = 0, errcode = ENOMEM;
1304 : 0 : struct roc_npc *npc = &dev->npc;
1305 : : int roc_err;
1306 : :
1307 [ # # ]: 0 : if (attr == NULL) {
1308 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1309 : : "NULL template attr");
1310 : 0 : return NULL;
1311 : : }
1312 : :
1313 [ # # ]: 0 : if (pattern == NULL) {
1314 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1315 : : "NULL pattern");
1316 : 0 : return NULL;
1317 : : }
1318 : :
1319 [ # # ]: 0 : while (pattern[nb_items].type != RTE_FLOW_ITEM_TYPE_END)
1320 : 0 : nb_items++;
1321 : :
1322 : : /* Reject oversized templates; rules are built into fixed-size stack
1323 : : * arrays (combined_items[ROC_NPC_ITEM_TYPE_END + 1]).
1324 : : */
1325 [ # # ]: 0 : if (nb_items > ROC_NPC_ITEM_TYPE_END) {
1326 : : errcode = ENOTSUP;
1327 : : errmsg = "too many pattern items for hardware";
1328 : 0 : goto err_nomem;
1329 : : }
1330 : :
1331 : 0 : tmpl = plt_zmalloc(sizeof(*tmpl), 0);
1332 [ # # ]: 0 : if (tmpl == NULL)
1333 : 0 : goto err_nomem;
1334 : :
1335 : 0 : tmpl->attr = *attr;
1336 : 0 : tmpl->nb_items = nb_items;
1337 : :
1338 : 0 : tmpl->pattern = plt_zmalloc((nb_items + 1) * sizeof(struct rte_flow_item), 0);
1339 [ # # ]: 0 : if (tmpl->pattern == NULL)
1340 : 0 : goto err_free;
1341 : :
1342 : : /* At most 3 payload copies (spec/last/mask) per item. */
1343 : 0 : tmpl->copies = plt_zmalloc(3 * (nb_items + 1) * sizeof(void *), 0);
1344 [ # # ]: 0 : if (tmpl->copies == NULL)
1345 : 0 : goto err_free;
1346 : :
1347 [ # # ]: 0 : for (i = 0; i < nb_items; i++) {
1348 : 0 : enum rte_flow_item_type t = pattern[i].type;
1349 [ # # ]: 0 : size_t sz = (t < (int)RTE_DIM(term)) ? term[t].item_size : 0;
1350 : :
1351 : : /* Reject unrepresentable item types (sz 0), which would drop
1352 : : * spec/last/mask. VOID/ANY legitimately carry no payload.
1353 : : */
1354 [ # # # # ]: 0 : if (t != RTE_FLOW_ITEM_TYPE_VOID && t != RTE_FLOW_ITEM_TYPE_ANY && sz == 0) {
1355 : : errcode = ENOTSUP;
1356 : : errmsg = "unsupported pattern item type in template";
1357 : 0 : goto err_free;
1358 : : }
1359 : :
1360 : : /* Reject items with nested variable-length payloads; a flat
1361 : : * memcpy would retain a dangling pointer into caller memory.
1362 : : */
1363 [ # # ]: 0 : if (t == RTE_FLOW_ITEM_TYPE_RAW) {
1364 : : errcode = ENOTSUP;
1365 : : errmsg = "Item type with nested pointers is not supported "
1366 : : "in pattern template (e.g. RAW)";
1367 : 0 : goto err_free;
1368 : : }
1369 : :
1370 : 0 : tmpl->pattern[i].type = t;
1371 [ # # ]: 0 : if (cnxk_flow_dup_conf(tmpl->copies, &tmpl->nb_copies, pattern[i].spec, sz,
1372 [ # # ]: 0 : &tmpl->pattern[i].spec) ||
1373 : 0 : cnxk_flow_dup_conf(tmpl->copies, &tmpl->nb_copies, pattern[i].last, sz,
1374 [ # # ]: 0 : &tmpl->pattern[i].last) ||
1375 : 0 : cnxk_flow_dup_conf(tmpl->copies, &tmpl->nb_copies, pattern[i].mask, sz,
1376 : 0 : &tmpl->pattern[i].mask))
1377 : 0 : goto err_free;
1378 : : }
1379 : 0 : tmpl->pattern[nb_items].type = RTE_FLOW_ITEM_TYPE_END;
1380 : 0 : tmpl->roc_tmpl = NULL;
1381 : 0 : tmpl->refcnt = 0;
1382 : :
1383 : 0 : roc_pattern = plt_zmalloc((nb_items + 1) * sizeof(*roc_pattern), 0);
1384 [ # # ]: 0 : if (roc_pattern == NULL)
1385 : 0 : goto err_free;
1386 : :
1387 [ # # ]: 0 : for (i = 0; i < nb_items; i++) {
1388 : 0 : enum rte_flow_item_type t = tmpl->pattern[i].type;
1389 [ # # ]: 0 : size_t sz = (t < (int)RTE_DIM(term)) ? term[t].item_size : 0;
1390 : :
1391 : 0 : roc_pattern[i].type =
1392 [ # # ]: 0 : (t < (int)RTE_DIM(term)) ? term[t].item_type : ROC_NPC_ITEM_TYPE_VOID;
1393 : 0 : roc_pattern[i].size = sz;
1394 : 0 : roc_pattern[i].spec = tmpl->pattern[i].spec;
1395 : 0 : roc_pattern[i].last = tmpl->pattern[i].last;
1396 : 0 : roc_pattern[i].mask = tmpl->pattern[i].mask;
1397 : : }
1398 : 0 : roc_pattern[nb_items].type = ROC_NPC_ITEM_TYPE_END;
1399 : :
1400 : : memset(&roc_attr, 0, sizeof(roc_attr));
1401 : 0 : roc_attr.relaxed_matching = attr->relaxed_matching;
1402 : 0 : roc_attr.ingress = attr->ingress;
1403 : 0 : roc_attr.egress = attr->egress;
1404 : 0 : roc_attr.transfer = attr->transfer;
1405 : :
1406 : 0 : roc_err = 0;
1407 : 0 : tmpl->roc_tmpl = roc_npc_pattern_template_create(npc, &roc_attr, roc_pattern, &roc_err);
1408 [ # # ]: 0 : if (tmpl->roc_tmpl == NULL) {
1409 [ # # ]: 0 : errcode = (roc_err < 0) ? -roc_err : ENOMEM;
1410 : : errmsg = "Failed to create ROC pattern template";
1411 : 0 : goto err_free;
1412 : : }
1413 : :
1414 : 0 : plt_free(roc_pattern);
1415 : :
1416 : 0 : return (struct rte_flow_pattern_template *)tmpl;
1417 : :
1418 : 0 : err_free:
1419 : 0 : plt_free(roc_pattern);
1420 : : if (tmpl != NULL) {
1421 : : uint16_t j;
1422 [ # # ]: 0 : if (tmpl->roc_tmpl != NULL)
1423 : 0 : roc_npc_pattern_template_destroy(npc, tmpl->roc_tmpl);
1424 [ # # ]: 0 : for (j = 0; j < tmpl->nb_copies; j++)
1425 : 0 : plt_free(tmpl->copies[j]);
1426 : 0 : plt_free(tmpl->copies);
1427 : 0 : plt_free(tmpl->pattern);
1428 : 0 : plt_free(tmpl);
1429 : : }
1430 : 0 : err_nomem:
1431 : 0 : rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, errmsg);
1432 : 0 : return NULL;
1433 : : }
1434 : :
1435 : : int
1436 [ # # ]: 0 : cnxk_flow_pattern_template_destroy(struct rte_eth_dev *eth_dev,
1437 : : struct rte_flow_pattern_template *templ,
1438 : : struct rte_flow_error *error)
1439 : : {
1440 : : struct cnxk_flow_pattern_template *tmpl = (struct cnxk_flow_pattern_template *)templ;
1441 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1442 : 0 : struct roc_npc *npc = &dev->npc;
1443 : : uint16_t i;
1444 : : int rc;
1445 : :
1446 [ # # ]: 0 : if (tmpl == NULL)
1447 : : return 0;
1448 : :
1449 [ # # ]: 0 : if (tmpl->refcnt != 0)
1450 : 0 : return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1451 : : "pattern template still in use by a table");
1452 : :
1453 : 0 : rc = roc_npc_pattern_template_destroy(npc, tmpl->roc_tmpl);
1454 [ # # ]: 0 : if (rc)
1455 : 0 : return rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1456 : : "failed to destroy ROC pattern template");
1457 : :
1458 [ # # ]: 0 : for (i = 0; i < tmpl->nb_copies; i++)
1459 : 0 : plt_free(tmpl->copies[i]);
1460 : 0 : plt_free(tmpl->copies);
1461 : 0 : plt_free(tmpl->pattern);
1462 : 0 : plt_free(tmpl);
1463 : 0 : return 0;
1464 : : }
1465 : : /* Size of an action's conf for the v1-supported set; -1 = unsupported. */
1466 : : static int
1467 : : cnxk_flow_action_conf_size(enum rte_flow_action_type type)
1468 : : {
1469 : : switch (type) {
1470 : : case RTE_FLOW_ACTION_TYPE_VOID:
1471 : : case RTE_FLOW_ACTION_TYPE_DROP:
1472 : : case RTE_FLOW_ACTION_TYPE_PF:
1473 : : case RTE_FLOW_ACTION_TYPE_FLAG:
1474 : : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
1475 : : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
1476 : : return 0; /* no conf */
1477 : : case RTE_FLOW_ACTION_TYPE_QUEUE:
1478 : : return sizeof(struct rte_flow_action_queue);
1479 : : case RTE_FLOW_ACTION_TYPE_VF:
1480 : : return sizeof(struct rte_flow_action_vf);
1481 : : case RTE_FLOW_ACTION_TYPE_MARK:
1482 : : return sizeof(struct rte_flow_action_mark);
1483 : : case RTE_FLOW_ACTION_TYPE_COUNT:
1484 : : return sizeof(struct rte_flow_action_count);
1485 : : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
1486 : : return sizeof(struct rte_flow_action_of_push_vlan);
1487 : : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
1488 : : return sizeof(struct rte_flow_action_of_set_vlan_vid);
1489 : : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
1490 : : return sizeof(struct rte_flow_action_of_set_vlan_pcp);
1491 : : case RTE_FLOW_ACTION_TYPE_AGE:
1492 : : return sizeof(struct rte_flow_action_age);
1493 : : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
1494 : : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
1495 : : return sizeof(struct rte_flow_action_ethdev);
1496 : : case RTE_FLOW_ACTION_TYPE_PORT_ID:
1497 : : return sizeof(struct rte_flow_action_port_id);
1498 : : default:
1499 : : return -1;
1500 : : }
1501 : : }
1502 : :
1503 : : /* Deep-copy an action conf. RSS nests queue[]/key[] pointers, so pack them
1504 : : * into one blob and fix the pointers; other confs use a flat memcpy.
1505 : : */
1506 : : static void *
1507 : 0 : cnxk_flow_dup_action_conf(const struct rte_flow_action *act)
1508 : : {
1509 [ # # ]: 0 : if (act->conf == NULL)
1510 : : return NULL;
1511 : :
1512 [ # # ]: 0 : if (act->type == RTE_FLOW_ACTION_TYPE_RSS) {
1513 : : const struct rte_flow_action_rss *rss = act->conf;
1514 : : size_t rss_blob_bytes = sizeof(*rss);
1515 : 0 : size_t rss_queue_bytes = (size_t)rss->queue_num * sizeof(uint16_t);
1516 : 0 : size_t rss_key_bytes = rss->key_len;
1517 : : struct rte_flow_action_rss *rss_copy;
1518 : : uint8_t *rss_blob;
1519 : :
1520 : : /* Reject a non-zero length paired with a NULL pointer, which
1521 : : * would make the memcpy below dereference NULL.
1522 : : */
1523 [ # # # # : 0 : if ((rss_queue_bytes && rss->queue == NULL) || (rss_key_bytes && rss->key == NULL))
# # # # ]
1524 : : return NULL;
1525 : :
1526 : 0 : rss_blob = plt_zmalloc(rss_blob_bytes + rss_queue_bytes + rss_key_bytes, 0);
1527 [ # # ]: 0 : if (rss_blob == NULL)
1528 : : return NULL;
1529 : : rss_copy = (struct rte_flow_action_rss *)rss_blob;
1530 : 0 : *rss_copy = *rss;
1531 [ # # ]: 0 : if (rss_queue_bytes) {
1532 : 0 : memcpy(rss_blob + rss_blob_bytes, rss->queue, rss_queue_bytes);
1533 : 0 : rss_copy->queue = (const uint16_t *)(rss_blob + rss_blob_bytes);
1534 : : } else {
1535 : 0 : rss_copy->queue = NULL;
1536 : : }
1537 [ # # ]: 0 : if (rss_key_bytes) {
1538 : 0 : memcpy(rss_blob + rss_blob_bytes + rss_queue_bytes, rss->key,
1539 : : rss_key_bytes);
1540 : 0 : rss_copy->key =
1541 : : (const uint8_t *)(rss_blob + rss_blob_bytes + rss_queue_bytes);
1542 : : } else {
1543 : 0 : rss_copy->key = NULL;
1544 : : }
1545 : 0 : return rss_copy;
1546 : : }
1547 : :
1548 : : {
1549 : : int conf_size = cnxk_flow_action_conf_size(act->type);
1550 : : void *copy;
1551 : :
1552 [ # # ]: 0 : if (conf_size <= 0)
1553 : : return NULL;
1554 : 0 : copy = plt_zmalloc(conf_size, 0);
1555 [ # # ]: 0 : if (copy != NULL)
1556 : 0 : memcpy(copy, act->conf, conf_size);
1557 : : return copy;
1558 : : }
1559 : : }
1560 : :
1561 : : /* Map a supported rte_flow action type to its roc_npc action type, to mirror
1562 : : * the actions template into the roc engine for lifecycle/refcount ownership.
1563 : : */
1564 : : static int
1565 : 0 : cnxk_flow_roc_action_type(enum rte_flow_action_type type, enum roc_npc_action_type *roc_type)
1566 : : {
1567 [ # # # # : 0 : switch (type) {
# # # # #
# # # # #
# # ]
1568 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
1569 : : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
1570 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_VOID;
1571 : 0 : return 0;
1572 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
1573 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_DROP;
1574 : 0 : return 0;
1575 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
1576 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_PF;
1577 : 0 : return 0;
1578 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
1579 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_VF;
1580 : 0 : return 0;
1581 : 0 : case RTE_FLOW_ACTION_TYPE_FLAG:
1582 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_FLAG;
1583 : 0 : return 0;
1584 : 0 : case RTE_FLOW_ACTION_TYPE_MARK:
1585 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_MARK;
1586 : 0 : return 0;
1587 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
1588 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_COUNT;
1589 : 0 : return 0;
1590 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
1591 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_QUEUE;
1592 : 0 : return 0;
1593 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
1594 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_RSS;
1595 : 0 : return 0;
1596 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
1597 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
1598 : 0 : return 0;
1599 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
1600 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
1601 : 0 : return 0;
1602 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
1603 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
1604 : 0 : return 0;
1605 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
1606 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
1607 : 0 : return 0;
1608 : 0 : case RTE_FLOW_ACTION_TYPE_AGE:
1609 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_AGE;
1610 : 0 : return 0;
1611 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
1612 : : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
1613 : : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
1614 : 0 : *roc_type = ROC_NPC_ACTION_TYPE_PORT_ID;
1615 : 0 : return 0;
1616 : : default:
1617 : : return -1;
1618 : : }
1619 : : }
1620 : :
1621 : : struct rte_flow_actions_template *
1622 [ # # ]: 0 : cnxk_flow_actions_template_create(struct rte_eth_dev *eth_dev,
1623 : : const struct rte_flow_actions_template_attr *attr,
1624 : : const struct rte_flow_action actions[],
1625 : : const struct rte_flow_action masks[],
1626 : : struct rte_flow_error *error)
1627 : : {
1628 : : const char *errmsg = "Failed to allocate actions template";
1629 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1630 : : struct cnxk_flow_actions_template *tmpl = NULL;
1631 : : struct roc_npc_actions_template_attr roc_attr;
1632 : : struct roc_npc_action *roc_actions = NULL;
1633 : : int i, nb_actions = 0, errcode = ENOMEM;
1634 : 0 : struct roc_npc *npc = &dev->npc;
1635 : 0 : int roc_err = 0;
1636 : :
1637 [ # # ]: 0 : if (attr == NULL) {
1638 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1639 : : "NULL template attr");
1640 : 0 : return NULL;
1641 : : }
1642 : :
1643 [ # # ]: 0 : if (actions == NULL) {
1644 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1645 : : "NULL actions");
1646 : 0 : return NULL;
1647 : : }
1648 : :
1649 [ # # ]: 0 : while (actions[nb_actions].type != RTE_FLOW_ACTION_TYPE_END)
1650 : 0 : nb_actions++;
1651 : :
1652 : : /* Reject oversized templates; rules are built into fixed-size stack
1653 : : * arrays (combined_actions[ROC_NPC_MAX_ACTION_COUNT] plus END).
1654 : : */
1655 [ # # ]: 0 : if (nb_actions > ROC_NPC_MAX_ACTION_COUNT - 1) {
1656 : : errcode = ENOTSUP;
1657 : : errmsg = "too many actions for hardware";
1658 : 0 : goto err;
1659 : : }
1660 : :
1661 : 0 : tmpl = plt_zmalloc(sizeof(*tmpl), 0);
1662 [ # # ]: 0 : if (tmpl == NULL)
1663 : 0 : goto err;
1664 : :
1665 : 0 : tmpl->attr = *attr;
1666 : 0 : tmpl->nb_actions = nb_actions;
1667 : :
1668 : 0 : tmpl->actions = plt_zmalloc((nb_actions + 1) * sizeof(struct rte_flow_action), 0);
1669 [ # # ]: 0 : if (tmpl->actions == NULL)
1670 : 0 : goto err;
1671 : :
1672 : 0 : tmpl->masks = plt_zmalloc((nb_actions + 1) * sizeof(struct rte_flow_action), 0);
1673 [ # # ]: 0 : if (tmpl->masks == NULL)
1674 : 0 : goto err;
1675 : :
1676 : : /* up to 2 conf copies (action + mask) per action */
1677 : 0 : tmpl->copies = plt_zmalloc(2 * (nb_actions + 1) * sizeof(void *), 0);
1678 [ # # ]: 0 : if (tmpl->copies == NULL)
1679 : 0 : goto err;
1680 : :
1681 [ # # ]: 0 : for (i = 0; i < nb_actions; i++) {
1682 [ # # ]: 0 : enum rte_flow_action_type t = actions[i].type;
1683 : : int sz = cnxk_flow_action_conf_size(t);
1684 : :
1685 [ # # ]: 0 : if (sz < 0 && t != RTE_FLOW_ACTION_TYPE_RSS) {
1686 : : errcode = ENOTSUP;
1687 : : errmsg = "Unsupported action in template "
1688 : : "(supports VOID/DROP/QUEUE/PF/VF/MARK/FLAG/COUNT/RSS/"
1689 : : "OF_POP_VLAN/OF_PUSH_VLAN/OF_SET_VLAN_VID/"
1690 : : "OF_SET_VLAN_PCP/AGE/REPRESENTED_PORT/"
1691 : : "PORT_REPRESENTOR/PORT_ID/VXLAN_DECAP)";
1692 : 0 : goto err;
1693 : : }
1694 : :
1695 : 0 : tmpl->actions[i].type = t;
1696 : :
1697 [ # # ]: 0 : if (t == RTE_FLOW_ACTION_TYPE_RSS) {
1698 : : /* RSS has nested pointers — use deep-copy helper. */
1699 : 0 : void *copy = cnxk_flow_dup_action_conf(&actions[i]);
1700 : :
1701 [ # # # # ]: 0 : if (copy == NULL && actions[i].conf != NULL) {
1702 : : const struct rte_flow_action_rss *rss = actions[i].conf;
1703 : :
1704 : : /* Malformed conf vs allocation failure: report a
1705 : : * precise errno instead of the default ENOMEM.
1706 : : */
1707 [ # # # # ]: 0 : if ((rss->queue_num && rss->queue == NULL) ||
1708 [ # # # # ]: 0 : (rss->key_len && rss->key == NULL)) {
1709 : : errcode = EINVAL;
1710 : : errmsg = "Malformed RSS action conf in template";
1711 : : }
1712 : 0 : goto err;
1713 : : }
1714 : 0 : tmpl->actions[i].conf = copy;
1715 [ # # ]: 0 : if (copy)
1716 : 0 : tmpl->copies[tmpl->nb_copies++] = copy;
1717 : : } else {
1718 [ # # ]: 0 : if (cnxk_flow_dup_conf(tmpl->copies, &tmpl->nb_copies, actions[i].conf, sz,
1719 : : &tmpl->actions[i].conf))
1720 : 0 : goto err;
1721 : : }
1722 : :
1723 [ # # ]: 0 : if (masks != NULL) {
1724 [ # # ]: 0 : if (masks[i].type != t) {
1725 : : errcode = EINVAL;
1726 : : errmsg = "actions/masks type mismatch in template";
1727 : 0 : goto err;
1728 : : }
1729 : 0 : tmpl->masks[i].type = t;
1730 [ # # ]: 0 : if (t == RTE_FLOW_ACTION_TYPE_RSS) {
1731 : : /* RSS nests pointers and cannot be copied by the flat
1732 : : * helper; reject a non-NULL RSS mask.
1733 : : */
1734 [ # # ]: 0 : if (masks[i].conf != NULL) {
1735 : : errcode = ENOTSUP;
1736 : : errmsg = "Non-NULL RSS mask conf is not "
1737 : : "supported in template";
1738 : 0 : goto err;
1739 : : }
1740 : 0 : tmpl->masks[i].conf = NULL;
1741 [ # # ]: 0 : } else if (cnxk_flow_dup_conf(tmpl->copies, &tmpl->nb_copies, masks[i].conf,
1742 : 0 : sz > 0 ? sz : 0, &tmpl->masks[i].conf)) {
1743 : 0 : goto err;
1744 : : }
1745 : : }
1746 : : }
1747 : :
1748 : 0 : tmpl->actions[nb_actions].type = RTE_FLOW_ACTION_TYPE_END;
1749 : 0 : tmpl->masks[nb_actions].type = RTE_FLOW_ACTION_TYPE_END;
1750 : 0 : tmpl->roc_tmpl = NULL;
1751 : 0 : tmpl->refcnt = 0;
1752 : :
1753 : : /* Mirror only action types into the roc engine for template lifecycle
1754 : : * and refcount ownership; per-rule conf translation stays in cnxk.
1755 : : */
1756 : 0 : roc_actions = plt_zmalloc((nb_actions + 1) * sizeof(*roc_actions), 0);
1757 [ # # ]: 0 : if (roc_actions == NULL)
1758 : 0 : goto err;
1759 : :
1760 [ # # ]: 0 : for (i = 0; i < nb_actions; i++) {
1761 : : enum roc_npc_action_type rt;
1762 : :
1763 [ # # ]: 0 : if (cnxk_flow_roc_action_type(tmpl->actions[i].type, &rt)) {
1764 : : errcode = ENOTSUP;
1765 : : errmsg = "Unsupported action in template";
1766 : 0 : goto err;
1767 : : }
1768 : 0 : roc_actions[i].type = rt;
1769 : 0 : roc_actions[i].conf = NULL;
1770 : : }
1771 : 0 : roc_actions[nb_actions].type = ROC_NPC_ACTION_TYPE_END;
1772 : :
1773 : : memset(&roc_attr, 0, sizeof(roc_attr));
1774 : 0 : roc_attr.ingress = attr->ingress;
1775 : 0 : roc_attr.egress = attr->egress;
1776 : 0 : roc_attr.transfer = attr->transfer;
1777 : :
1778 : 0 : tmpl->roc_tmpl =
1779 : 0 : roc_npc_actions_template_create(npc, &roc_attr, roc_actions, NULL, &roc_err);
1780 : 0 : plt_free(roc_actions);
1781 : : roc_actions = NULL;
1782 [ # # ]: 0 : if (tmpl->roc_tmpl == NULL) {
1783 [ # # ]: 0 : errcode = (roc_err < 0) ? -roc_err : ENOMEM;
1784 : : errmsg = "Failed to create ROC actions template";
1785 : 0 : goto err;
1786 : : }
1787 : :
1788 : : return (struct rte_flow_actions_template *)tmpl;
1789 : :
1790 : 0 : err:
1791 : 0 : plt_free(roc_actions);
1792 [ # # ]: 0 : if (tmpl != NULL) {
1793 : : uint16_t j;
1794 [ # # ]: 0 : if (tmpl->roc_tmpl != NULL)
1795 : 0 : roc_npc_actions_template_destroy(npc, tmpl->roc_tmpl);
1796 [ # # ]: 0 : for (j = 0; j < tmpl->nb_copies; j++)
1797 : 0 : plt_free(tmpl->copies[j]);
1798 : 0 : plt_free(tmpl->copies);
1799 : 0 : plt_free(tmpl->masks);
1800 : 0 : plt_free(tmpl->actions);
1801 : 0 : plt_free(tmpl);
1802 : : }
1803 : 0 : rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, errmsg);
1804 : 0 : return NULL;
1805 : : }
1806 : :
1807 : : int
1808 [ # # ]: 0 : cnxk_flow_actions_template_destroy(struct rte_eth_dev *eth_dev,
1809 : : struct rte_flow_actions_template *templ,
1810 : : struct rte_flow_error *error)
1811 : : {
1812 : : struct cnxk_flow_actions_template *tmpl = (struct cnxk_flow_actions_template *)templ;
1813 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1814 : 0 : struct roc_npc *npc = &dev->npc;
1815 : : uint16_t i;
1816 : : int rc;
1817 : :
1818 [ # # ]: 0 : if (tmpl == NULL)
1819 : : return 0;
1820 : :
1821 [ # # ]: 0 : if (tmpl->refcnt != 0)
1822 : 0 : return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1823 : : "actions template still in use by a table");
1824 : :
1825 : 0 : rc = roc_npc_actions_template_destroy(npc, tmpl->roc_tmpl);
1826 [ # # ]: 0 : if (rc)
1827 : 0 : return rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1828 : : "failed to destroy ROC actions template");
1829 : :
1830 [ # # ]: 0 : for (i = 0; i < tmpl->nb_copies; i++)
1831 : 0 : plt_free(tmpl->copies[i]);
1832 : 0 : plt_free(tmpl->copies);
1833 : 0 : plt_free(tmpl->masks);
1834 : 0 : plt_free(tmpl->actions);
1835 : 0 : plt_free(tmpl);
1836 : 0 : return 0;
1837 : : }
1838 : :
1839 : : struct rte_flow_template_table *
1840 [ # # ]: 0 : cnxk_flow_template_table_create(struct rte_eth_dev *eth_dev,
1841 : : const struct rte_flow_template_table_attr *table_attr,
1842 : : struct rte_flow_pattern_template *pattern_templates[],
1843 : : uint8_t nb_pattern_templates,
1844 : : struct rte_flow_actions_template *actions_templates[],
1845 : : uint8_t nb_actions_templates, struct rte_flow_error *error)
1846 : : {
1847 : : struct roc_npc_pattern_template **roc_pattern_templates = NULL;
1848 : : struct roc_npc_actions_template **roc_actions_templates = NULL;
1849 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1850 : : struct roc_npc_template_table_attr roc_attr;
1851 : : enum rte_flow_table_insertion_type itype;
1852 : : const struct rte_flow_attr *fattr;
1853 : 0 : struct roc_npc *npc = &dev->npc;
1854 : : struct cnxk_flow_table *table;
1855 : : uint32_t nb_flows;
1856 : 0 : int errcode = 0;
1857 : : uint8_t i;
1858 : :
1859 [ # # ]: 0 : if (table_attr == NULL) {
1860 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1861 : : "NULL table_attr");
1862 : 0 : return NULL;
1863 : : }
1864 : :
1865 : 0 : itype = table_attr->insertion_type;
1866 : : fattr = &table_attr->flow_attr;
1867 : 0 : nb_flows = table_attr->nb_flows;
1868 : :
1869 [ # # ]: 0 : if (itype == RTE_FLOW_TABLE_INSERTION_TYPE_INDEX) {
1870 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1871 : : "pure-index insertion not supported; NPC is match-based");
1872 : 0 : return NULL;
1873 : : }
1874 : :
1875 : : /* Validate the template handles before allocating anything. */
1876 [ # # ]: 0 : for (i = 0; i < nb_pattern_templates; i++) {
1877 [ # # ]: 0 : if (pattern_templates[i] == NULL) {
1878 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1879 : : "invalid template handle");
1880 : 0 : return NULL;
1881 : : }
1882 : : }
1883 [ # # ]: 0 : for (i = 0; i < nb_actions_templates; i++) {
1884 [ # # ]: 0 : if (actions_templates[i] == NULL) {
1885 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1886 : : "invalid template handle");
1887 : 0 : return NULL;
1888 : : }
1889 : : }
1890 : :
1891 : 0 : table = plt_zmalloc(sizeof(*table), 0);
1892 [ # # ]: 0 : if (table == NULL)
1893 : 0 : goto enomem;
1894 : :
1895 : 0 : table->insertion_type = itype;
1896 : 0 : table->nb_flows = nb_flows;
1897 : :
1898 [ # # ]: 0 : memset(&table->flow_attr, 0, sizeof(table->flow_attr));
1899 : 0 : table->flow_attr.priority = fattr->priority;
1900 : 0 : table->flow_attr.ingress = fattr->ingress;
1901 : 0 : table->flow_attr.egress = fattr->egress;
1902 : 0 : table->transfer = fattr->transfer;
1903 : :
1904 [ # # ]: 0 : if (nb_pattern_templates != 0) {
1905 : 0 : table->pattern_templates =
1906 : 0 : plt_zmalloc(nb_pattern_templates * sizeof(*table->pattern_templates), 0);
1907 [ # # ]: 0 : if (table->pattern_templates == NULL)
1908 : 0 : goto free_table;
1909 : : roc_pattern_templates =
1910 : 0 : plt_zmalloc(nb_pattern_templates * sizeof(*roc_pattern_templates), 0);
1911 [ # # ]: 0 : if (roc_pattern_templates == NULL)
1912 : 0 : goto free_table;
1913 : : }
1914 [ # # ]: 0 : if (nb_actions_templates != 0) {
1915 : 0 : table->actions_templates =
1916 : 0 : plt_zmalloc(nb_actions_templates * sizeof(*table->actions_templates), 0);
1917 [ # # ]: 0 : if (table->actions_templates == NULL)
1918 : 0 : goto free_table;
1919 : : roc_actions_templates =
1920 : 0 : plt_zmalloc(nb_actions_templates * sizeof(*roc_actions_templates), 0);
1921 [ # # ]: 0 : if (roc_actions_templates == NULL)
1922 : 0 : goto free_table;
1923 : : }
1924 : :
1925 : : /* Hand the table to the roc engine, which owns rule storage, MCAM
1926 : : * reservation and the rule lifecycle; cnxk keeps per-rule translation.
1927 : : */
1928 : : memset(&roc_attr, 0, sizeof(roc_attr));
1929 : 0 : roc_attr.flow_attr = table->flow_attr;
1930 : 0 : roc_attr.transfer = table->transfer;
1931 : 0 : roc_attr.nb_flows = nb_flows;
1932 : 0 : roc_attr.insertion_type = (itype == RTE_FLOW_TABLE_INSERTION_TYPE_INDEX_WITH_PATTERN) ?
1933 : 0 : ROC_NPC_TEMPLATE_INSERTION_INDEX_WITH_PATTERN :
1934 : : ROC_NPC_TEMPLATE_INSERTION_PATTERN;
1935 : : /* Stash this wrapper as the table cookie so async_actions_update can
1936 : : * recover the rte templates from just the flow handle.
1937 : : */
1938 : 0 : roc_attr.cookie = table;
1939 : :
1940 [ # # ]: 0 : for (i = 0; i < nb_pattern_templates; i++) {
1941 : 0 : table->pattern_templates[i] =
1942 : 0 : (struct cnxk_flow_pattern_template *)pattern_templates[i];
1943 : 0 : roc_pattern_templates[i] = table->pattern_templates[i]->roc_tmpl;
1944 [ # # ]: 0 : if (roc_pattern_templates[i] == NULL)
1945 : 0 : goto bad_handle;
1946 : : }
1947 [ # # ]: 0 : for (i = 0; i < nb_actions_templates; i++) {
1948 : 0 : table->actions_templates[i] =
1949 : 0 : (struct cnxk_flow_actions_template *)actions_templates[i];
1950 : 0 : roc_actions_templates[i] = table->actions_templates[i]->roc_tmpl;
1951 [ # # ]: 0 : if (roc_actions_templates[i] == NULL)
1952 : 0 : goto bad_handle;
1953 : : }
1954 : :
1955 : : /* clang-format off */
1956 : 0 : table->roc_table = roc_npc_template_table_create(npc, &roc_attr,
1957 : : roc_pattern_templates, nb_pattern_templates,
1958 : : roc_actions_templates, nb_actions_templates, &errcode);
1959 : : /* clang-format on */
1960 : 0 : plt_free(roc_pattern_templates);
1961 : 0 : plt_free(roc_actions_templates);
1962 : : roc_pattern_templates = NULL;
1963 : : roc_actions_templates = NULL;
1964 [ # # ]: 0 : if (table->roc_table == NULL) {
1965 : 0 : plt_free(table->pattern_templates);
1966 : 0 : plt_free(table->actions_templates);
1967 : 0 : plt_free(table);
1968 [ # # ]: 0 : rte_flow_error_set(error, errcode < 0 ? -errcode : ENOMEM,
1969 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1970 : : "could not create template table");
1971 : 0 : return NULL;
1972 : : }
1973 : :
1974 [ # # ]: 0 : for (i = 0; i < nb_pattern_templates; i++)
1975 : 0 : table->pattern_templates[i]->refcnt++;
1976 : 0 : table->nb_pattern_templates = nb_pattern_templates;
1977 [ # # ]: 0 : for (i = 0; i < nb_actions_templates; i++)
1978 : 0 : table->actions_templates[i]->refcnt++;
1979 : 0 : table->nb_actions_templates = nb_actions_templates;
1980 : :
1981 : 0 : return (struct rte_flow_template_table *)table;
1982 : :
1983 : 0 : bad_handle:
1984 : 0 : plt_free(roc_pattern_templates);
1985 : 0 : plt_free(roc_actions_templates);
1986 : 0 : plt_free(table->pattern_templates);
1987 : 0 : plt_free(table->actions_templates);
1988 : 0 : plt_free(table);
1989 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1990 : : "invalid template handle");
1991 : 0 : return NULL;
1992 : :
1993 : 0 : free_table:
1994 : 0 : plt_free(roc_pattern_templates);
1995 : 0 : plt_free(roc_actions_templates);
1996 : 0 : plt_free(table->pattern_templates);
1997 : 0 : plt_free(table->actions_templates);
1998 : 0 : plt_free(table);
1999 : :
2000 : 0 : enomem:
2001 : 0 : rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "out of memory");
2002 : 0 : return NULL;
2003 : : }
2004 : :
2005 : : int
2006 [ # # ]: 0 : cnxk_flow_template_table_destroy(struct rte_eth_dev *eth_dev,
2007 : : struct rte_flow_template_table *tbl_handle,
2008 : : struct rte_flow_error *error)
2009 : : {
2010 : : struct cnxk_flow_table *table = (struct cnxk_flow_table *)tbl_handle;
2011 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2012 : 0 : struct roc_npc *npc = &dev->npc;
2013 : : uint8_t i;
2014 : : int rc;
2015 : :
2016 [ # # ]: 0 : if (table == NULL)
2017 : : return 0;
2018 : :
2019 : : /* The roc engine guards teardown: a busy table returns -EBUSY and
2020 : : * nothing is freed, so the cnxk wrapper and refcounts stay intact.
2021 : : */
2022 : 0 : rc = roc_npc_template_table_destroy(npc, table->roc_table);
2023 [ # # ]: 0 : if (rc == -EBUSY)
2024 : 0 : return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2025 : : "table still has live flows; destroy them first");
2026 [ # # ]: 0 : if (rc)
2027 : 0 : return rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2028 : : "failed to destroy template table");
2029 : :
2030 [ # # ]: 0 : for (i = 0; i < table->nb_pattern_templates; i++)
2031 : 0 : table->pattern_templates[i]->refcnt--;
2032 [ # # ]: 0 : for (i = 0; i < table->nb_actions_templates; i++)
2033 : 0 : table->actions_templates[i]->refcnt--;
2034 : :
2035 : 0 : plt_free(table->pattern_templates);
2036 : 0 : plt_free(table->actions_templates);
2037 : 0 : plt_free(table);
2038 : 0 : return 0;
2039 : : }
2040 : :
2041 : : /* Reject per-rule pattern/actions arrays whose types/order do not mirror the
2042 : : * chosen templates; the merge takes the type from the template but the
2043 : : * spec/conf from the per-rule array. A NULL array uses template defaults.
2044 : : */
2045 : : static int
2046 : : cnxk_flow_check_items(const struct cnxk_flow_pattern_template *pt,
2047 : : const struct rte_flow_item items[])
2048 : : {
2049 : : uint16_t k;
2050 : :
2051 : 0 : if (items == NULL)
2052 : : return 0;
2053 [ # # # # ]: 0 : for (k = 0; k < pt->nb_items; k++)
2054 [ # # # # ]: 0 : if (items[k].type != pt->pattern[k].type)
2055 : : return -EINVAL;
2056 [ # # # # ]: 0 : if (items[pt->nb_items].type != RTE_FLOW_ITEM_TYPE_END)
2057 : : return -EINVAL;
2058 : : return 0;
2059 : : }
2060 : :
2061 : : static int
2062 : : cnxk_flow_check_actions(const struct cnxk_flow_actions_template *at,
2063 : : const struct rte_flow_action actions[])
2064 : : {
2065 : : uint16_t k;
2066 : :
2067 [ # # # # ]: 0 : if (actions == NULL)
2068 : : return 0;
2069 [ # # # # : 0 : for (k = 0; k < at->nb_actions; k++)
# # ]
2070 [ # # # # : 0 : if (actions[k].type != at->actions[k].type)
# # ]
2071 : : return -EINVAL;
2072 [ # # # # : 0 : if (actions[at->nb_actions].type != RTE_FLOW_ACTION_TYPE_END)
# # ]
2073 : : return -EINVAL;
2074 : : return 0;
2075 : : }
2076 : :
2077 : : /* Enqueue a PATTERN create: merge the per-rule spec with the templates,
2078 : : * translate to roc_npc types, and hand to the roc engine (programmed at push).
2079 : : */
2080 : : struct rte_flow *
2081 [ # # ]: 0 : cnxk_flow_async_create(struct rte_eth_dev *eth_dev, uint32_t queue,
2082 : : const struct rte_flow_op_attr *attr,
2083 : : struct rte_flow_template_table *tbl_handle,
2084 : : const struct rte_flow_item items[], uint8_t pattern_template_index,
2085 : : const struct rte_flow_action actions[], uint8_t action_template_index,
2086 : : void *user_data, struct rte_flow_error *error)
2087 : : {
2088 : : struct cnxk_flow_table *table = (struct cnxk_flow_table *)tbl_handle;
2089 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2090 : : struct cnxk_flow_pattern_template *pt;
2091 : : struct cnxk_flow_actions_template *at;
2092 : : struct roc_npc_template_flow *flow;
2093 : 0 : struct roc_npc *npc = &dev->npc;
2094 : :
2095 : 0 : uint64_t free_allocs[ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1] = {0};
2096 : 0 : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1] = {0};
2097 : : struct rte_flow_action combined_actions[ROC_NPC_MAX_ACTION_COUNT];
2098 : 0 : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT] = {0};
2099 : : struct rte_flow_item combined_items[ROC_NPC_ITEM_TYPE_END + 1];
2100 : 0 : struct roc_npc_action_sample in_sample = {0};
2101 : : struct rte_flow_attr rte_attr;
2102 : : struct roc_npc_attr in_attr;
2103 : 0 : uint16_t dst_pf_func = 0;
2104 : 0 : uint64_t def_action = 0;
2105 : 0 : int errcode = 0;
2106 : : uint16_t k;
2107 : : int rc, j;
2108 : :
2109 : : RTE_SET_USED(attr);
2110 : :
2111 [ # # ]: 0 : if (table == NULL) {
2112 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2113 : : "bad table");
2114 : 0 : return NULL;
2115 : : }
2116 [ # # ]: 0 : if (table->insertion_type != RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN) {
2117 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2118 : : "table is index-insertion; use create_by_index_with_pattern");
2119 : 0 : return NULL;
2120 : : }
2121 [ # # ]: 0 : if (pattern_template_index >= table->nb_pattern_templates ||
2122 [ # # ]: 0 : action_template_index >= table->nb_actions_templates) {
2123 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2124 : : "template index out of range");
2125 : 0 : return NULL;
2126 : : }
2127 : :
2128 : 0 : pt = table->pattern_templates[pattern_template_index];
2129 [ # # ]: 0 : at = table->actions_templates[action_template_index];
2130 : :
2131 : : if (cnxk_flow_check_items(pt, items) != 0 || cnxk_flow_check_actions(at, actions) != 0) {
2132 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2133 : : "pattern/actions do not match the selected templates");
2134 : 0 : return NULL;
2135 : : }
2136 : :
2137 : : /* Merge: spec comes from the per-rule call, last/mask from the template. */
2138 [ # # ]: 0 : for (k = 0; k < pt->nb_items; k++) {
2139 : 0 : combined_items[k].type = pt->pattern[k].type;
2140 [ # # ]: 0 : combined_items[k].spec = items ? items[k].spec : NULL;
2141 : 0 : combined_items[k].last = pt->pattern[k].last;
2142 : 0 : combined_items[k].mask = pt->pattern[k].mask;
2143 : : }
2144 : 0 : combined_items[pt->nb_items].type = RTE_FLOW_ITEM_TYPE_END;
2145 : :
2146 : : /* Merge: per-rule conf overrides the template conf. */
2147 [ # # ]: 0 : for (k = 0; k < at->nb_actions; k++) {
2148 : 0 : combined_actions[k].type = at->actions[k].type;
2149 : 0 : combined_actions[k].conf =
2150 [ # # # # ]: 0 : (actions && actions[k].conf) ? actions[k].conf : at->actions[k].conf;
2151 : : }
2152 : 0 : combined_actions[at->nb_actions].type = RTE_FLOW_ACTION_TYPE_END;
2153 : :
2154 : : memset(&rte_attr, 0, sizeof(rte_attr));
2155 : 0 : rte_attr.priority = table->flow_attr.priority;
2156 : 0 : rte_attr.ingress = table->flow_attr.ingress;
2157 : 0 : rte_attr.egress = table->flow_attr.egress;
2158 : 0 : rte_attr.transfer = table->transfer;
2159 : :
2160 : : /* Translate into roc_npc types. The RSS flow key is stashed in
2161 : : * npc->flowkey_cfg_state so the engine can restore it at push().
2162 : : */
2163 : : memset(&in_attr, 0, sizeof(in_attr));
2164 : 0 : rc = cnxk_map_flow_data(eth_dev, &rte_attr, combined_items, combined_actions, &in_attr,
2165 : : in_pattern, in_actions, &in_sample, &npc->flowkey_cfg_state,
2166 : : &dst_pf_func, &def_action, false, free_allocs, 0);
2167 [ # # ]: 0 : if (rc == 0)
2168 : 0 : flow = roc_npc_async_flow_create(npc, queue, table->roc_table, in_pattern,
2169 : : in_actions, dst_pf_func, def_action, user_data,
2170 : : &errcode);
2171 : : else
2172 : : flow = NULL;
2173 : :
2174 [ # # # # ]: 0 : for (j = 0; j < (int)RTE_DIM(free_allocs) && free_allocs[j]; j++)
2175 : 0 : plt_free((void *)free_allocs[j]);
2176 : :
2177 [ # # ]: 0 : if (rc != 0) {
2178 : 0 : rte_flow_error_set(error, rc < 0 ? -rc : rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
2179 : : "Failed to map flow data");
2180 : 0 : return NULL;
2181 : : }
2182 [ # # ]: 0 : if (flow == NULL) {
2183 [ # # ]: 0 : rte_flow_error_set(error, errcode < 0 ? -errcode : EINVAL,
2184 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2185 : : "async flow create failed");
2186 : 0 : return NULL;
2187 : : }
2188 : :
2189 : : return (struct rte_flow *)flow;
2190 : : }
2191 : :
2192 : : /* Enqueue a destroy operation. */
2193 : : int
2194 : 0 : cnxk_flow_async_destroy(struct rte_eth_dev *eth_dev, uint32_t queue,
2195 : : const struct rte_flow_op_attr *attr, struct rte_flow *flow, void *user_data,
2196 : : struct rte_flow_error *error)
2197 : : {
2198 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2199 : 0 : struct roc_npc *npc = &dev->npc;
2200 : : int rc;
2201 : :
2202 : : RTE_SET_USED(attr);
2203 : :
2204 : 0 : rc = roc_npc_async_flow_destroy(npc, queue, (struct roc_npc_template_flow *)flow,
2205 : : user_data);
2206 [ # # ]: 0 : if (rc)
2207 : 0 : return rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2208 : : "bad queue or flow handle");
2209 : : return 0;
2210 : : }
2211 : :
2212 : : /* Flush all pending async operations to hardware in one batch. */
2213 : : int
2214 : 0 : cnxk_flow_push(struct rte_eth_dev *eth_dev, uint32_t queue, struct rte_flow_error *error)
2215 : : {
2216 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2217 : 0 : struct roc_npc *npc = &dev->npc;
2218 : : int rc;
2219 : :
2220 : 0 : rc = roc_npc_flow_push(npc, queue);
2221 [ # # ]: 0 : if (rc)
2222 : 0 : return rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2223 : : "bad queue");
2224 : : return 0;
2225 : : }
2226 : :
2227 : : /* Return results for completed ops back to the application. */
2228 : : int
2229 : 0 : cnxk_flow_pull(struct rte_eth_dev *eth_dev, uint32_t queue, struct rte_flow_op_result res[],
2230 : : uint16_t n_res, struct rte_flow_error *error)
2231 : : {
2232 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2233 : 0 : struct roc_npc *npc = &dev->npc;
2234 : : uint16_t done = 0;
2235 : :
2236 : : /* Drain roc engine results in fixed-size batches, translating each
2237 : : * roc op result into the rte op result without a per-pull allocation.
2238 : : */
2239 [ # # ]: 0 : while (done < n_res) {
2240 : : struct roc_npc_flow_op_result rres[64];
2241 : 0 : uint16_t batch = RTE_MIN((uint16_t)(n_res - done), (uint16_t)RTE_DIM(rres));
2242 : 0 : int got = roc_npc_flow_pull(npc, queue, rres, batch);
2243 : : uint16_t k;
2244 : :
2245 [ # # ]: 0 : if (got < 0) {
2246 [ # # ]: 0 : if (done != 0)
2247 : : break;
2248 : 0 : return rte_flow_error_set(error, -got, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2249 : : NULL, "bad queue");
2250 : : }
2251 : :
2252 [ # # ]: 0 : for (k = 0; k < (uint16_t)got; k++) {
2253 : 0 : res[done + k].status =
2254 : 0 : (rres[k].rc == 0) ? RTE_FLOW_OP_SUCCESS : RTE_FLOW_OP_ERROR;
2255 : 0 : res[done + k].user_data = rres[k].user_data;
2256 : : }
2257 : 0 : done += (uint16_t)got;
2258 : :
2259 [ # # ]: 0 : if (got < batch)
2260 : : break;
2261 : : }
2262 : :
2263 : 0 : return done;
2264 : : }
2265 : :
2266 : : struct rte_flow *
2267 : 0 : cnxk_flow_async_create_by_index(struct rte_eth_dev *eth_dev, uint32_t queue,
2268 : : const struct rte_flow_op_attr *attr,
2269 : : struct rte_flow_template_table *table, uint32_t rule_index,
2270 : : const struct rte_flow_action actions[],
2271 : : uint8_t action_template_index, void *user_data,
2272 : : struct rte_flow_error *error)
2273 : : {
2274 : : RTE_SET_USED(eth_dev);
2275 : : RTE_SET_USED(queue);
2276 : : RTE_SET_USED(attr);
2277 : : RTE_SET_USED(table);
2278 : : RTE_SET_USED(rule_index);
2279 : : RTE_SET_USED(actions);
2280 : : RTE_SET_USED(action_template_index);
2281 : : RTE_SET_USED(user_data);
2282 : :
2283 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2284 : : "index-only insertion needs a match key; NPC is match-based");
2285 : 0 : return NULL;
2286 : : }
2287 : :
2288 : : /* Like async_create but with an app-specified index; the app must avoid
2289 : : * concurrent creates to the same index and use a valid table index.
2290 : : */
2291 : : struct rte_flow *
2292 : : /* clang-format off */
2293 [ # # ]: 0 : cnxk_flow_async_create_by_index_with_pattern(struct rte_eth_dev *eth_dev,
2294 : : uint32_t queue, const struct rte_flow_op_attr *attr,
2295 : : struct rte_flow_template_table *tbl_handle, uint32_t rule_index,
2296 : : const struct rte_flow_item items[], uint8_t pattern_template_index,
2297 : : const struct rte_flow_action actions[],
2298 : : uint8_t action_template_index, void *user_data,
2299 : : struct rte_flow_error *error)
2300 : : /* clang-format on */
2301 : : {
2302 : : struct cnxk_flow_table *table = (struct cnxk_flow_table *)tbl_handle;
2303 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2304 : : struct cnxk_flow_pattern_template *pt;
2305 : : struct cnxk_flow_actions_template *at;
2306 : : struct roc_npc_template_flow *flow;
2307 : 0 : struct roc_npc *npc = &dev->npc;
2308 : :
2309 : 0 : uint64_t free_allocs[ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1] = {0};
2310 : 0 : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1] = {0};
2311 : : struct rte_flow_action combined_actions[ROC_NPC_MAX_ACTION_COUNT];
2312 : 0 : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT] = {0};
2313 : : struct rte_flow_item combined_items[ROC_NPC_ITEM_TYPE_END + 1];
2314 : 0 : struct roc_npc_action_sample in_sample = {0};
2315 : : struct rte_flow_attr rte_attr;
2316 : : struct roc_npc_attr in_attr;
2317 : 0 : uint32_t flowkey_cfg = 0;
2318 : 0 : uint16_t dst_pf_func = 0;
2319 : 0 : uint64_t def_action = 0;
2320 : 0 : int errcode = 0;
2321 : : uint16_t k;
2322 : : int rc, j;
2323 : :
2324 : : RTE_SET_USED(attr);
2325 : :
2326 [ # # ]: 0 : if (table == NULL) {
2327 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2328 : : "bad table");
2329 : 0 : return NULL;
2330 : : }
2331 [ # # ]: 0 : if (table->insertion_type != RTE_FLOW_TABLE_INSERTION_TYPE_INDEX_WITH_PATTERN) {
2332 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2333 : : "table is not index-with-pattern insertion");
2334 : 0 : return NULL;
2335 : : }
2336 [ # # ]: 0 : if (pattern_template_index >= table->nb_pattern_templates ||
2337 [ # # ]: 0 : action_template_index >= table->nb_actions_templates) {
2338 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2339 : : "template index out of range");
2340 : 0 : return NULL;
2341 : : }
2342 [ # # ]: 0 : if (rule_index >= table->nb_flows) {
2343 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2344 : : "rule_index out of range");
2345 : 0 : return NULL;
2346 : : }
2347 : :
2348 : 0 : pt = table->pattern_templates[pattern_template_index];
2349 [ # # ]: 0 : at = table->actions_templates[action_template_index];
2350 : :
2351 : : if (cnxk_flow_check_items(pt, items) != 0 || cnxk_flow_check_actions(at, actions) != 0) {
2352 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2353 : : "pattern/actions do not match the selected templates");
2354 : 0 : return NULL;
2355 : : }
2356 : :
2357 [ # # ]: 0 : for (k = 0; k < pt->nb_items; k++) {
2358 : 0 : combined_items[k].type = pt->pattern[k].type;
2359 [ # # ]: 0 : combined_items[k].spec = items ? items[k].spec : NULL;
2360 : 0 : combined_items[k].last = pt->pattern[k].last;
2361 : 0 : combined_items[k].mask = pt->pattern[k].mask;
2362 : : }
2363 : 0 : combined_items[pt->nb_items].type = RTE_FLOW_ITEM_TYPE_END;
2364 : :
2365 [ # # ]: 0 : for (k = 0; k < at->nb_actions; k++) {
2366 : 0 : combined_actions[k].type = at->actions[k].type;
2367 : 0 : combined_actions[k].conf =
2368 [ # # # # ]: 0 : (actions && actions[k].conf) ? actions[k].conf : at->actions[k].conf;
2369 : : }
2370 : 0 : combined_actions[at->nb_actions].type = RTE_FLOW_ACTION_TYPE_END;
2371 : :
2372 : : memset(&rte_attr, 0, sizeof(rte_attr));
2373 : 0 : rte_attr.priority = table->flow_attr.priority;
2374 : 0 : rte_attr.ingress = table->flow_attr.ingress;
2375 : 0 : rte_attr.egress = table->flow_attr.egress;
2376 : 0 : rte_attr.transfer = table->transfer;
2377 : :
2378 : : memset(&in_attr, 0, sizeof(in_attr));
2379 : 0 : rc = cnxk_map_flow_data(eth_dev, &rte_attr, combined_items, combined_actions, &in_attr,
2380 : : in_pattern, in_actions, &in_sample, &flowkey_cfg, &dst_pf_func,
2381 : : &def_action, false, free_allocs, 0);
2382 [ # # ]: 0 : if (rc == 0)
2383 : : /* clang-format off */
2384 : 0 : flow = roc_npc_async_flow_create_by_index_with_pattern(npc, queue,
2385 : : table->roc_table, rule_index, in_pattern, in_actions,
2386 : : user_data, &errcode);
2387 : : /* clang-format on */
2388 : : else
2389 : : flow = NULL;
2390 : :
2391 [ # # # # ]: 0 : for (j = 0; j < (int)RTE_DIM(free_allocs) && free_allocs[j]; j++)
2392 : 0 : plt_free((void *)free_allocs[j]);
2393 : :
2394 [ # # ]: 0 : if (rc != 0) {
2395 : 0 : rte_flow_error_set(error, rc < 0 ? -rc : rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
2396 : : "Failed to map flow data");
2397 : 0 : return NULL;
2398 : : }
2399 [ # # ]: 0 : if (flow == NULL) {
2400 [ # # ]: 0 : rte_flow_error_set(error, errcode < 0 ? -errcode : EINVAL,
2401 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "flow parse failed");
2402 : 0 : return NULL;
2403 : : }
2404 : :
2405 : : return (struct rte_flow *)flow;
2406 : : }
2407 : :
2408 : : /* Update the actions of an existing flow, keeping key/mask/mcam_id/enable. */
2409 : : int
2410 [ # # ]: 0 : cnxk_flow_async_actions_update(struct rte_eth_dev *eth_dev, uint32_t queue,
2411 : : const struct rte_flow_op_attr *attr, struct rte_flow *flow,
2412 : : const struct rte_flow_action actions[],
2413 : : uint8_t action_template_index, void *user_data,
2414 : : struct rte_flow_error *error)
2415 : : {
2416 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2417 : : struct cnxk_flow_actions_template *at;
2418 : 0 : struct roc_npc *npc = &dev->npc;
2419 : : struct cnxk_flow_table *table;
2420 : :
2421 : 0 : uint64_t free_allocs[ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1] = {0};
2422 : 0 : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1] = {0};
2423 : : struct rte_flow_action combined_actions[ROC_NPC_MAX_ACTION_COUNT];
2424 : 0 : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT] = {0};
2425 : 0 : struct roc_npc_action_sample in_sample = {0};
2426 : : struct rte_flow_item end_pattern[1];
2427 : : struct rte_flow_attr rte_attr;
2428 : : struct roc_npc_attr in_attr;
2429 : 0 : uint32_t flowkey_cfg = 0;
2430 : 0 : uint16_t dst_pf_func = 0;
2431 : 0 : uint64_t def_action = 0;
2432 : : uint16_t k;
2433 : : int rc, j;
2434 : :
2435 : : RTE_SET_USED(attr);
2436 : :
2437 [ # # ]: 0 : if (flow == NULL)
2438 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2439 : : "bad flow handle");
2440 : :
2441 : : /* Recover the cnxk table context from the cookie the engine kept for
2442 : : * this rule's table.
2443 : : */
2444 : 0 : table = roc_npc_async_flow_table_cookie((struct roc_npc_template_flow *)flow);
2445 [ # # ]: 0 : if (table == NULL)
2446 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2447 : : "flow handle has no associated table");
2448 [ # # ]: 0 : if (action_template_index >= table->nb_actions_templates)
2449 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2450 : : "actions template index out of range");
2451 : :
2452 [ # # ]: 0 : at = table->actions_templates[action_template_index];
2453 : :
2454 : : if (cnxk_flow_check_actions(at, actions) != 0)
2455 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
2456 : : "actions do not match the selected template");
2457 : :
2458 [ # # ]: 0 : for (k = 0; k < at->nb_actions; k++) {
2459 : 0 : combined_actions[k].type = at->actions[k].type;
2460 : 0 : combined_actions[k].conf =
2461 [ # # # # ]: 0 : (actions && actions[k].conf) ? actions[k].conf : at->actions[k].conf;
2462 : : }
2463 : 0 : combined_actions[at->nb_actions].type = RTE_FLOW_ACTION_TYPE_END;
2464 : :
2465 : 0 : end_pattern[0].type = RTE_FLOW_ITEM_TYPE_END;
2466 : :
2467 : : memset(&rte_attr, 0, sizeof(rte_attr));
2468 : 0 : rte_attr.priority = table->flow_attr.priority;
2469 : 0 : rte_attr.ingress = table->flow_attr.ingress;
2470 : 0 : rte_attr.egress = table->flow_attr.egress;
2471 : 0 : rte_attr.transfer = table->transfer;
2472 : :
2473 : : memset(&in_attr, 0, sizeof(in_attr));
2474 : 0 : rc = cnxk_map_flow_data(eth_dev, &rte_attr, end_pattern, combined_actions, &in_attr,
2475 : : in_pattern, in_actions, &in_sample, &flowkey_cfg, &dst_pf_func,
2476 : : &def_action, false, free_allocs, 0);
2477 [ # # ]: 0 : if (rc == 0)
2478 : : /* clang-format off */
2479 : 0 : rc = roc_npc_async_flow_actions_update(npc, queue,
2480 : : (struct roc_npc_template_flow *)flow, in_actions, user_data);
2481 : : /* clang-format on */
2482 : :
2483 [ # # # # ]: 0 : for (j = 0; j < (int)RTE_DIM(free_allocs) && free_allocs[j]; j++)
2484 : 0 : plt_free((void *)free_allocs[j]);
2485 : :
2486 [ # # ]: 0 : if (rc != 0)
2487 [ # # ]: 0 : return rte_flow_error_set(error, rc < 0 ? -rc : EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
2488 : : NULL, "failed to update flow actions");
2489 : :
2490 : : return 0;
2491 : : }
2492 : :
2493 : : static int
2494 : 0 : cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow, FILE *file,
2495 : : struct rte_flow_error *error)
2496 : : {
2497 : 0 : return cnxk_flow_dev_dump_common(eth_dev, flow, file, error, false);
2498 : : }
2499 : :
2500 : : static int
2501 [ # # ]: 0 : cnxk_flow_get_aged_flows(struct rte_eth_dev *eth_dev, void **context, uint32_t nb_contexts,
2502 : : struct rte_flow_error *err)
2503 : : {
2504 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
2505 : 0 : struct roc_npc *roc_npc = &dev->npc;
2506 : : struct roc_npc_flow_age *flow_age;
2507 : : uint32_t start_id;
2508 : : uint32_t end_id;
2509 : : int cnt = 0;
2510 : : uint32_t sn;
2511 : : uint32_t i;
2512 : :
2513 : : RTE_SET_USED(err);
2514 : :
2515 : : flow_age = &roc_npc->flow_age;
2516 : :
2517 [ # # ]: 0 : if (!flow_age->age_flow_refcnt)
2518 : : return 0;
2519 : :
2520 : : do {
2521 : : sn = plt_seqcount_read_begin(&flow_age->seq_cnt);
2522 : :
2523 [ # # ]: 0 : if (nb_contexts == 0) {
2524 : 0 : cnt = flow_age->aged_flows_cnt;
2525 : : } else {
2526 : 0 : start_id = flow_age->start_id;
2527 : 0 : end_id = flow_age->end_id;
2528 [ # # ]: 0 : for (i = start_id; i <= end_id; i++) {
2529 [ # # ]: 0 : if ((int)nb_contexts == cnt)
2530 : : break;
2531 [ # # ]: 0 : if (plt_bitmap_get(flow_age->aged_flows, i)) {
2532 : 0 : context[cnt] =
2533 : 0 : roc_npc_aged_flow_ctx_get(roc_npc, i);
2534 : 0 : cnt++;
2535 : : }
2536 : : }
2537 : : }
2538 [ # # ]: 0 : } while (plt_seqcount_read_retry(&flow_age->seq_cnt, sn));
2539 : :
2540 : : return cnt;
2541 : : }
2542 : :
2543 : : static int
2544 : 0 : cnxk_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev, struct rte_flow_tunnel *tunnel,
2545 : : struct rte_flow_action **pmd_actions, uint32_t *num_of_actions,
2546 : : __rte_unused struct rte_flow_error *err)
2547 : : {
2548 : : struct rte_flow_action *nfp_action;
2549 : :
2550 : 0 : nfp_action = rte_zmalloc("nfp_tun_action", sizeof(struct rte_flow_action), 0);
2551 [ # # ]: 0 : if (nfp_action == NULL) {
2552 : 0 : plt_err("Alloc memory for nfp tunnel action failed.");
2553 : 0 : return -ENOMEM;
2554 : : }
2555 : :
2556 [ # # ]: 0 : if (tunnel->is_ipv6)
2557 : 0 : nfp_action->conf = (void *)~0;
2558 : :
2559 [ # # ]: 0 : switch (tunnel->type) {
2560 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
2561 : 0 : nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
2562 : 0 : *pmd_actions = nfp_action;
2563 : 0 : *num_of_actions = 1;
2564 : 0 : break;
2565 : 0 : default:
2566 : 0 : *pmd_actions = NULL;
2567 : 0 : *num_of_actions = 0;
2568 : 0 : rte_free(nfp_action);
2569 : 0 : break;
2570 : : }
2571 : :
2572 : : return 0;
2573 : : }
2574 : :
2575 : : static int
2576 : 0 : cnxk_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
2577 : : struct rte_flow_action *pmd_actions, uint32_t num_of_actions,
2578 : : __rte_unused struct rte_flow_error *err)
2579 : : {
2580 : : uint32_t i;
2581 : : struct rte_flow_action *nfp_action;
2582 : :
2583 [ # # ]: 0 : for (i = 0; i < num_of_actions; i++) {
2584 : 0 : nfp_action = &pmd_actions[i];
2585 : 0 : nfp_action->conf = NULL;
2586 : 0 : rte_free(nfp_action);
2587 : : }
2588 : :
2589 : 0 : return 0;
2590 : : }
2591 : :
2592 : : static int
2593 : 0 : cnxk_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
2594 : : __rte_unused struct rte_flow_tunnel *tunnel,
2595 : : __rte_unused struct rte_flow_item **pmd_items, uint32_t *num_of_items,
2596 : : __rte_unused struct rte_flow_error *err)
2597 : : {
2598 : 0 : *num_of_items = 0;
2599 : :
2600 : 0 : return 0;
2601 : : }
2602 : :
2603 : : static int
2604 : 0 : cnxk_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
2605 : : __rte_unused struct rte_flow_item *pmd_items,
2606 : : __rte_unused uint32_t num_of_items,
2607 : : __rte_unused struct rte_flow_error *err)
2608 : : {
2609 : 0 : return 0;
2610 : : }
2611 : :
2612 : : struct rte_flow_ops cnxk_flow_ops = {
2613 : : .validate = cnxk_flow_validate,
2614 : : .flush = cnxk_flow_flush,
2615 : : .query = cnxk_flow_query,
2616 : : .isolate = cnxk_flow_isolate,
2617 : : .dev_dump = cnxk_flow_dev_dump,
2618 : : .get_aged_flows = cnxk_flow_get_aged_flows,
2619 : : .tunnel_match = cnxk_flow_tunnel_match,
2620 : : .tunnel_item_release = cnxk_flow_tunnel_item_release,
2621 : : .tunnel_decap_set = cnxk_flow_tunnel_decap_set,
2622 : : .tunnel_action_decap_release = cnxk_flow_tunnel_action_decap_release,
2623 : : };
|