Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Corigine, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_conntrack.h"
7 : :
8 : : #include <rte_malloc.h>
9 : : #include <rte_hash.h>
10 : : #include <rte_jhash.h>
11 : :
12 : : #include "../nfp_logs.h"
13 : : #include "nfp_flower_cmsg.h"
14 : : #include "nfp_flower_representor.h"
15 : :
16 : : struct ct_data {
17 : : uint8_t ct_state; /* Connection state. */
18 : : uint16_t ct_zone; /* Connection zone. */
19 : : };
20 : :
21 : : enum ct_entry_type {
22 : : CT_TYPE_PRE_CT,
23 : : CT_TYPE_POST_CT,
24 : : };
25 : :
26 : : struct nfp_initial_flow {
27 : : struct rte_flow_item *items;
28 : : struct rte_flow_action *actions;
29 : : uint8_t items_cnt;
30 : : uint8_t actions_cnt;
31 : : };
32 : :
33 : : struct nfp_ct_flow_entry {
34 : : uint64_t cookie;
35 : : LIST_ENTRY(nfp_ct_flow_entry) pre_ct_list;
36 : : LIST_ENTRY(nfp_ct_flow_entry) post_ct_list;
37 : : LIST_HEAD(, nfp_ct_merge_entry) children;
38 : : enum ct_entry_type type;
39 : : struct rte_eth_dev *dev;
40 : : struct nfp_ct_zone_entry *ze;
41 : : struct nfp_initial_flow rule;
42 : : struct nfp_fl_stats stats;
43 : : };
44 : :
45 : : struct nfp_ct_map_entry {
46 : : uint64_t cookie;
47 : : struct nfp_ct_flow_entry *fe;
48 : : };
49 : :
50 : : struct nfp_ct_zone_entry {
51 : : uint32_t zone;
52 : : struct nfp_flow_priv *priv;
53 : : LIST_HEAD(, nfp_ct_flow_entry) pre_ct_list;
54 : : LIST_HEAD(, nfp_ct_flow_entry) post_ct_list;
55 : : struct rte_hash *ct_merge_table;
56 : : };
57 : :
58 : : struct nfp_ct_merge_entry {
59 : : uint64_t cookie[2];
60 : : uint32_t ctx_id;
61 : : LIST_ENTRY(nfp_ct_merge_entry) pre_ct_list;
62 : : LIST_ENTRY(nfp_ct_merge_entry) post_ct_list;
63 : : struct nfp_initial_flow rule;
64 : : struct rte_flow *compiled_rule;
65 : : struct nfp_ct_zone_entry *ze;
66 : : struct nfp_ct_flow_entry *pre_ct_parent;
67 : : struct nfp_ct_flow_entry *post_ct_parent;
68 : : };
69 : :
70 : : /* OVS_KEY_ATTR_CT_STATE flags */
71 : : #define OVS_CS_F_NEW 0x01 /* Beginning of a new connection. */
72 : : #define OVS_CS_F_ESTABLISHED 0x02 /* Part of an existing connection. */
73 : : #define OVS_CS_F_RELATED 0x04 /* Related to an established connection. */
74 : : #define OVS_CS_F_REPLY_DIR 0x08 /* Flow is in the reply direction. */
75 : : #define OVS_CS_F_INVALID 0x10 /* Could not track connection. */
76 : : #define OVS_CS_F_TRACKED 0x20 /* Conntrack has occurred. */
77 : : #define OVS_CS_F_SRC_NAT 0x40 /* Packet's source address/port was mangled by NAT. */
78 : : #define OVS_CS_F_DST_NAT 0x80 /* Packet's destination address/port was mangled by NAT. */
79 : :
80 : : typedef void (*nfp_action_free_fn)(void *field);
81 : : typedef bool (*nfp_action_copy_fn)(const void *src, void *dst);
82 : :
83 : : static bool
84 : : is_pre_ct_flow(const struct ct_data *ct,
85 : : const struct rte_flow_action *actions)
86 : : {
87 : : const struct rte_flow_action *action;
88 : :
89 [ # # ]: 0 : if (ct == NULL)
90 : : return false;
91 : :
92 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
93 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK)
94 : : return true;
95 : : }
96 : :
97 : : return false;
98 : : }
99 : :
100 : : static bool
101 : : is_post_ct_flow(const struct ct_data *ct)
102 : : {
103 [ # # ]: 0 : if (ct == NULL)
104 : : return false;
105 : :
106 [ # # ]: 0 : if ((ct->ct_state & OVS_CS_F_ESTABLISHED) != 0)
107 : : return true;
108 : :
109 : : return false;
110 : : }
111 : :
112 : : static bool
113 : : is_ct_commit_flow(const struct ct_data *ct)
114 : : {
115 : 0 : if (ct == NULL)
116 : : return false;
117 : :
118 [ # # ]: 0 : if ((ct->ct_state & OVS_CS_F_NEW) != 0)
119 : : return true;
120 : :
121 : : return false;
122 : : }
123 : :
124 : : static struct nfp_ct_merge_entry *
125 : 0 : nfp_ct_merge_table_search(struct nfp_ct_zone_entry *ze,
126 : : char *hash_data,
127 : : uint32_t hash_len)
128 : : {
129 : : int index;
130 : : uint32_t hash_key;
131 : : struct nfp_ct_merge_entry *m_ent;
132 : :
133 : 0 : hash_key = rte_jhash(hash_data, hash_len, ze->priv->hash_seed);
134 : 0 : index = rte_hash_lookup_data(ze->ct_merge_table, &hash_key, (void **)&m_ent);
135 [ # # ]: 0 : if (index < 0) {
136 : 0 : PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_merge table.");
137 : 0 : return NULL;
138 : : }
139 : :
140 : 0 : return m_ent;
141 : : }
142 : :
143 : : static bool
144 : 0 : nfp_ct_merge_table_add(struct nfp_ct_zone_entry *ze,
145 : : struct nfp_ct_merge_entry *merge_entry)
146 : : {
147 : : int ret;
148 : : uint32_t hash_key;
149 : :
150 : 0 : hash_key = rte_jhash(merge_entry, sizeof(uint64_t) * 2, ze->priv->hash_seed);
151 : 0 : ret = rte_hash_add_key_data(ze->ct_merge_table, &hash_key, merge_entry);
152 [ # # ]: 0 : if (ret != 0) {
153 : 0 : PMD_DRV_LOG(ERR, "Add to ct_merge table failed.");
154 : 0 : return false;
155 : : }
156 : :
157 : : return true;
158 : : }
159 : :
160 : : static void
161 : 0 : nfp_ct_merge_table_delete(struct nfp_ct_zone_entry *ze,
162 : : struct nfp_ct_merge_entry *m_ent)
163 : : {
164 : : int ret;
165 : : uint32_t hash_key;
166 : :
167 : 0 : hash_key = rte_jhash(m_ent, sizeof(uint64_t) * 2, ze->priv->hash_seed);
168 : 0 : ret = rte_hash_del_key(ze->ct_merge_table, &hash_key);
169 [ # # ]: 0 : if (ret < 0)
170 : 0 : PMD_DRV_LOG(ERR, "Delete from ct_merge table failed, ret=%d.", ret);
171 : 0 : }
172 : :
173 : : static void
174 : 0 : nfp_ct_merge_entry_destroy(struct nfp_ct_merge_entry *m_ent)
175 : : {
176 : : struct nfp_ct_zone_entry *ze;
177 : :
178 : 0 : ze = m_ent->ze;
179 : 0 : nfp_ct_merge_table_delete(ze, m_ent);
180 : :
181 : 0 : rte_free(m_ent->rule.actions);
182 : 0 : rte_free(m_ent->rule.items);
183 [ # # ]: 0 : LIST_REMOVE(m_ent, pre_ct_list);
184 [ # # ]: 0 : LIST_REMOVE(m_ent, post_ct_list);
185 : 0 : rte_free(m_ent);
186 : 0 : }
187 : :
188 : : struct nfp_ct_map_entry *
189 : 0 : nfp_ct_map_table_search(struct nfp_flow_priv *priv,
190 : : char *hash_data,
191 : : uint32_t hash_len)
192 : : {
193 : : int index;
194 : : uint32_t hash_key;
195 : : struct nfp_ct_map_entry *me;
196 : :
197 : 0 : hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
198 : 0 : index = rte_hash_lookup_data(priv->ct_map_table, &hash_key, (void **)&me);
199 [ # # ]: 0 : if (index < 0) {
200 : 0 : PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_map table.");
201 : 0 : return NULL;
202 : : }
203 : :
204 : 0 : return me;
205 : : }
206 : :
207 : : static bool
208 : 0 : nfp_ct_map_table_add(struct nfp_flow_priv *priv,
209 : : struct nfp_ct_map_entry *me)
210 : : {
211 : : int ret;
212 : : uint32_t hash_key;
213 : :
214 : 0 : hash_key = rte_jhash(me, sizeof(uint64_t), priv->hash_seed);
215 : 0 : ret = rte_hash_add_key_data(priv->ct_map_table, &hash_key, me);
216 [ # # ]: 0 : if (ret != 0) {
217 : 0 : PMD_DRV_LOG(ERR, "Add to ct_map table failed.");
218 : 0 : return false;
219 : : }
220 : :
221 : : return true;
222 : : }
223 : :
224 : : static void
225 : 0 : nfp_ct_map_table_delete(struct nfp_flow_priv *priv,
226 : : struct nfp_ct_map_entry *me)
227 : : {
228 : : int ret;
229 : : uint32_t hash_key;
230 : :
231 : 0 : hash_key = rte_jhash(me, sizeof(uint64_t), priv->hash_seed);
232 : 0 : ret = rte_hash_del_key(priv->ct_map_table, &hash_key);
233 [ # # ]: 0 : if (ret < 0)
234 : 0 : PMD_DRV_LOG(ERR, "Delete form ct_map table failed.");
235 : 0 : }
236 : :
237 : : static void
238 : : nfp_ct_map_entry_destroy(struct nfp_ct_map_entry *me)
239 : : {
240 : 0 : rte_free(me);
241 : 0 : }
242 : :
243 : : static void
244 : 0 : nfp_ct_flow_item_free_real(void *field,
245 : : enum rte_flow_item_type type)
246 : : {
247 [ # # ]: 0 : switch (type) {
248 : : case RTE_FLOW_ITEM_TYPE_VOID:
249 : : break;
250 : 0 : case RTE_FLOW_ITEM_TYPE_ETH: /* FALLTHROUGH */
251 : : case RTE_FLOW_ITEM_TYPE_VLAN: /* FALLTHROUGH */
252 : : case RTE_FLOW_ITEM_TYPE_IPV4: /* FALLTHROUGH */
253 : : case RTE_FLOW_ITEM_TYPE_IPV6: /* FALLTHROUGH */
254 : : case RTE_FLOW_ITEM_TYPE_TCP: /* FALLTHROUGH */
255 : : case RTE_FLOW_ITEM_TYPE_UDP: /* FALLTHROUGH */
256 : : case RTE_FLOW_ITEM_TYPE_SCTP: /* FALLTHROUGH */
257 : : case RTE_FLOW_ITEM_TYPE_VXLAN: /* FALLTHROUGH */
258 : : case RTE_FLOW_ITEM_TYPE_GRE: /* FALLTHROUGH */
259 : : case RTE_FLOW_ITEM_TYPE_GRE_KEY: /* FALLTHROUGH */
260 : : case RTE_FLOW_ITEM_TYPE_GENEVE:
261 : 0 : rte_free(field);
262 : 0 : break;
263 : : default:
264 : : break;
265 : : }
266 : 0 : }
267 : :
268 : : static void
269 : 0 : nfp_ct_flow_item_free(struct rte_flow_item *item)
270 : : {
271 [ # # ]: 0 : if (item->spec != NULL)
272 : 0 : nfp_ct_flow_item_free_real((void *)(ptrdiff_t)item->spec, item->type);
273 : :
274 [ # # ]: 0 : if (item->mask != NULL)
275 : 0 : nfp_ct_flow_item_free_real((void *)(ptrdiff_t)item->mask, item->type);
276 : :
277 [ # # ]: 0 : if (item->last != NULL)
278 : 0 : nfp_ct_flow_item_free_real((void *)(ptrdiff_t)item->last, item->type);
279 : 0 : }
280 : :
281 : : static void
282 : : nfp_ct_flow_items_free(struct rte_flow_item *items,
283 : : uint8_t item_cnt)
284 : : {
285 : : uint8_t loop;
286 : :
287 [ # # # # : 0 : for (loop = 0; loop < item_cnt; ++loop)
# # # # ]
288 : 0 : nfp_ct_flow_item_free(items + loop);
289 : : }
290 : :
291 : : static bool
292 : 0 : nfp_flow_item_conf_size_get(enum rte_flow_item_type type,
293 : : size_t *size)
294 : : {
295 : : size_t len = 0;
296 : :
297 [ # # # # : 0 : switch (type) {
# # # # #
# # # # ]
298 : : case RTE_FLOW_ITEM_TYPE_VOID:
299 : : break;
300 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
301 : : len = sizeof(struct rte_flow_item_eth);
302 : 0 : break;
303 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
304 : : len = sizeof(struct rte_flow_item_vlan);
305 : 0 : break;
306 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
307 : : len = sizeof(struct rte_flow_item_ipv4);
308 : 0 : break;
309 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
310 : : len = sizeof(struct rte_flow_item_ipv6);
311 : 0 : break;
312 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
313 : : len = sizeof(struct rte_flow_item_tcp);
314 : 0 : break;
315 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
316 : : len = sizeof(struct rte_flow_item_udp);
317 : 0 : break;
318 : 0 : case RTE_FLOW_ITEM_TYPE_SCTP:
319 : : len = sizeof(struct rte_flow_item_sctp);
320 : 0 : break;
321 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
322 : : len = sizeof(struct rte_flow_item_vxlan);
323 : 0 : break;
324 : 0 : case RTE_FLOW_ITEM_TYPE_GRE:
325 : : len = sizeof(struct rte_flow_item_gre);
326 : 0 : break;
327 : 0 : case RTE_FLOW_ITEM_TYPE_GRE_KEY:
328 : : len = sizeof(rte_be32_t);
329 : 0 : break;
330 : 0 : case RTE_FLOW_ITEM_TYPE_GENEVE:
331 : : len = sizeof(struct rte_flow_item_geneve);
332 : 0 : break;
333 : 0 : default:
334 : 0 : PMD_DRV_LOG(ERR, "Unsupported item type: %d.", type);
335 : 0 : *size = 0;
336 : 0 : return false;
337 : : }
338 : :
339 : 0 : *size = len;
340 : :
341 : 0 : return true;
342 : : }
343 : :
344 : : static void *
345 : 0 : nfp_ct_flow_item_copy_real(const void *src,
346 : : enum rte_flow_item_type type)
347 : : {
348 : : bool ret;
349 : : void *dst;
350 : : size_t len;
351 : :
352 : 0 : ret = nfp_flow_item_conf_size_get(type, &len);
353 [ # # ]: 0 : if (!ret) {
354 : 0 : PMD_DRV_LOG(ERR, "Get flow item conf size failed.");
355 : 0 : return NULL;
356 : : }
357 : :
358 : 0 : dst = rte_zmalloc("flow_item", len, 0);
359 [ # # ]: 0 : if (dst == NULL) {
360 : 0 : PMD_DRV_LOG(ERR, "Malloc memory for ct item failed.");
361 : 0 : return NULL;
362 : : }
363 : :
364 : : rte_memcpy(dst, src, len);
365 : :
366 : : return dst;
367 : : }
368 : :
369 : : static bool
370 : 0 : nfp_ct_flow_item_copy(const struct rte_flow_item *src,
371 : : struct rte_flow_item *dst)
372 : : {
373 : 0 : dst->type = src->type;
374 : :
375 [ # # ]: 0 : if (src->spec != NULL) {
376 : 0 : dst->spec = nfp_ct_flow_item_copy_real(src->spec, src->type);
377 [ # # ]: 0 : if (dst->spec == NULL) {
378 : 0 : PMD_DRV_LOG(ERR, "Copy spec of ct item failed.");
379 : 0 : goto end;
380 : : }
381 : : }
382 : :
383 [ # # ]: 0 : if (src->mask != NULL) {
384 : 0 : dst->mask = nfp_ct_flow_item_copy_real(src->mask, src->type);
385 [ # # ]: 0 : if (dst->mask == NULL) {
386 : 0 : PMD_DRV_LOG(ERR, "Copy mask of ct item failed.");
387 : 0 : goto free_spec;
388 : : }
389 : : }
390 : :
391 [ # # ]: 0 : if (src->last != NULL) {
392 : 0 : dst->last = nfp_ct_flow_item_copy_real(src->last, src->type);
393 [ # # ]: 0 : if (dst->last == NULL) {
394 : 0 : PMD_DRV_LOG(ERR, "Copy last of ct item failed.");
395 : 0 : goto free_mask;
396 : : }
397 : : }
398 : :
399 : : return true;
400 : :
401 : : free_mask:
402 : 0 : nfp_ct_flow_item_free_real((void *)(ptrdiff_t)dst->mask, dst->type);
403 : 0 : free_spec:
404 : 0 : nfp_ct_flow_item_free_real((void *)(ptrdiff_t)dst->spec, dst->type);
405 : : end:
406 : : return false;
407 : : }
408 : :
409 : : static bool
410 : 0 : nfp_ct_flow_items_copy(const struct rte_flow_item *src,
411 : : struct rte_flow_item *dst,
412 : : uint8_t item_cnt)
413 : : {
414 : : bool ret;
415 : : uint8_t loop;
416 : :
417 [ # # ]: 0 : for (loop = 0; loop < item_cnt; ++loop) {
418 : 0 : ret = nfp_ct_flow_item_copy(src + loop, dst + loop);
419 [ # # ]: 0 : if (!ret) {
420 : 0 : PMD_DRV_LOG(ERR, "Copy ct item failed.");
421 : : nfp_ct_flow_items_free(dst, loop);
422 : : return false;
423 : : }
424 : : }
425 : :
426 : : return true;
427 : : }
428 : :
429 : : static void
430 : : nfp_ct_flow_action_free_real(void *field,
431 : : nfp_action_free_fn func)
432 : : {
433 : : if (func != NULL)
434 : 0 : func(field);
435 : :
436 : 0 : rte_free(field);
437 : 0 : }
438 : :
439 : : static void
440 : 0 : nfp_ct_flow_action_free_vxlan(void *field)
441 : : {
442 : : struct vxlan_data *vxlan = field;
443 : :
444 : 0 : nfp_ct_flow_items_free(vxlan->items, ACTION_VXLAN_ENCAP_ITEMS_NUM);
445 : 0 : }
446 : :
447 : : static void
448 : 0 : nfp_ct_flow_action_free_raw(void *field)
449 : : {
450 : : struct rte_flow_action_raw_encap *raw_encap = field;
451 : :
452 : 0 : rte_free(raw_encap->data);
453 : 0 : }
454 : :
455 : : static void
456 : 0 : nfp_ct_flow_action_free(struct rte_flow_action *action)
457 : : {
458 : : nfp_action_free_fn func = NULL;
459 : :
460 [ # # ]: 0 : if (action->conf == NULL)
461 : : return;
462 : :
463 [ # # # # : 0 : switch (action->type) {
# ]
464 : : case RTE_FLOW_ACTION_TYPE_VOID: /* FALLTHROUGH */
465 : : case RTE_FLOW_ACTION_TYPE_DROP: /* FALLTHROUGH */
466 : : case RTE_FLOW_ACTION_TYPE_COUNT: /* FALLTHROUGH */
467 : : case RTE_FLOW_ACTION_TYPE_JUMP: /* FALLTHROUGH */
468 : : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: /* FALLTHROUGH */
469 : : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: /* FALLTHROUGH */
470 : : case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
471 : : return;
472 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: /* FALLTHROUGH */
473 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: /* FALLTHROUGH */
474 : : case RTE_FLOW_ACTION_TYPE_PORT_ID: /* FALLTHROUGH */
475 : : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: /* FALLTHROUGH */
476 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: /* FALLTHROUGH */
477 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: /* FALLTHROUGH */
478 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: /* FALLTHROUGH */
479 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP: /* FALLTHROUGH */
480 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: /* FALLTHROUGH */
481 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: /* FALLTHROUGH */
482 : : case RTE_FLOW_ACTION_TYPE_SET_TTL: /* FALLTHROUGH */
483 : : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: /* FALLTHROUGH */
484 : : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
485 : : break;
486 : : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
487 : : func = nfp_ct_flow_action_free_vxlan;
488 : : break;
489 : 0 : case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
490 : : func = nfp_ct_flow_action_free_raw;
491 : 0 : break;
492 : 0 : default:
493 : 0 : PMD_DRV_LOG(ERR, "Unsupported action type: %d.", action->type);
494 : : break;
495 : : }
496 : :
497 : 0 : nfp_ct_flow_action_free_real((void *)(ptrdiff_t)action->conf, func);
498 : : }
499 : :
500 : : static void
501 : : nfp_ct_flow_actions_free(struct rte_flow_action *actions,
502 : : uint8_t action_cnt)
503 : : {
504 : : uint8_t loop;
505 : :
506 [ # # # # : 0 : for (loop = 0; loop < action_cnt; ++loop)
# # ]
507 : 0 : nfp_ct_flow_action_free(actions + loop);
508 : : }
509 : :
510 : : static void *
511 : 0 : nfp_ct_flow_action_copy_real(const void *src,
512 : : size_t len,
513 : : nfp_action_copy_fn func)
514 : : {
515 : : bool ret;
516 : : void *dst;
517 : :
518 : 0 : dst = rte_zmalloc("flow_action", len, 0);
519 [ # # ]: 0 : if (dst == NULL) {
520 : 0 : PMD_DRV_LOG(ERR, "Malloc memory for ct action failed.");
521 : 0 : return NULL;
522 : : }
523 : :
524 [ # # ]: 0 : if (func != NULL) {
525 : 0 : ret = func(src, dst);
526 [ # # ]: 0 : if (!ret) {
527 : 0 : PMD_DRV_LOG(ERR, "Copy ct action failed.");
528 : 0 : return NULL;
529 : : }
530 : :
531 : : return dst;
532 : : }
533 : :
534 : : rte_memcpy(dst, src, len);
535 : :
536 : : return dst;
537 : : }
538 : :
539 : : static bool
540 : 0 : nfp_ct_flow_action_copy_vxlan(const void *src,
541 : : void *dst)
542 : : {
543 : : struct vxlan_data *vxlan_dst = dst;
544 : : const struct vxlan_data *vxlan_src = src;
545 : :
546 : 0 : vxlan_dst->conf.definition = vxlan_dst->items;
547 : 0 : return nfp_ct_flow_items_copy(vxlan_src->items, vxlan_dst->items,
548 : : ACTION_VXLAN_ENCAP_ITEMS_NUM);
549 : : }
550 : :
551 : : static bool
552 : 0 : nfp_ct_flow_action_copy_raw(const void *src,
553 : : void *dst)
554 : : {
555 : : struct rte_flow_action_raw_encap *raw_dst = dst;
556 : : const struct rte_flow_action_raw_encap *raw_src = src;
557 : :
558 : 0 : raw_dst->size = raw_src->size;
559 : 0 : raw_dst->data = nfp_ct_flow_action_copy_real(raw_src->data,
560 : : raw_src->size, NULL);
561 [ # # ]: 0 : if (raw_dst->data == NULL) {
562 : 0 : PMD_DRV_LOG(ERR, "Copy ct action process failed.");
563 : 0 : return false;
564 : : }
565 : :
566 : : return true;
567 : : }
568 : :
569 : : static bool
570 : 0 : nfp_ct_flow_action_copy(const struct rte_flow_action *src,
571 : : struct rte_flow_action *dst)
572 : : {
573 : : size_t len;
574 : : nfp_action_copy_fn func = NULL;
575 : :
576 : 0 : dst->type = src->type;
577 : :
578 [ # # ]: 0 : if (src->conf == NULL)
579 : : return true;
580 : :
581 [ # # # # : 0 : switch (src->type) {
# # # # #
# # # ]
582 : : case RTE_FLOW_ACTION_TYPE_VOID: /* FALLTHROUGH */
583 : : case RTE_FLOW_ACTION_TYPE_DROP: /* FALLTHROUGH */
584 : : case RTE_FLOW_ACTION_TYPE_COUNT: /* FALLTHROUGH */
585 : : case RTE_FLOW_ACTION_TYPE_JUMP: /* FALLTHROUGH */
586 : : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: /* FALLTHROUGH */
587 : : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: /* FALLTHROUGH */
588 : : case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
589 : : return true;
590 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: /* FALLTHROUGH */
591 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
592 : : len = sizeof(struct rte_flow_action_set_mac);
593 : : break;
594 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
595 : : len = sizeof(struct rte_flow_action_port_id);
596 : 0 : break;
597 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
598 : : len = sizeof(struct rte_flow_action_of_push_vlan);
599 : 0 : break;
600 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: /* FALLTHROUGH */
601 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
602 : : len = sizeof(struct rte_flow_action_set_ipv4);
603 : 0 : break;
604 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: /* FALLTHROUGH */
605 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
606 : : len = sizeof(struct rte_flow_action_set_dscp);
607 : 0 : break;
608 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: /* FALLTHROUGH */
609 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
610 : : len = sizeof(struct rte_flow_action_set_ipv6);
611 : 0 : break;
612 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TTL:
613 : : len = sizeof(struct rte_flow_action_set_ttl);
614 : 0 : break;
615 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: /* FALLTHROUGH */
616 : : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
617 : : len = sizeof(struct rte_flow_action_set_tp);
618 : 0 : break;
619 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
620 : : len = sizeof(struct vxlan_data);
621 : : func = nfp_ct_flow_action_copy_vxlan;
622 : 0 : break;
623 : 0 : case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
624 : : len = sizeof(struct rte_flow_action_raw_encap);
625 : : func = nfp_ct_flow_action_copy_raw;
626 : 0 : break;
627 : 0 : default:
628 : 0 : PMD_DRV_LOG(DEBUG, "Unsupported action type: %d.", src->type);
629 : 0 : return false;
630 : : }
631 : :
632 : 0 : dst->conf = nfp_ct_flow_action_copy_real(src->conf, len, func);
633 [ # # ]: 0 : if (dst->conf == NULL) {
634 : 0 : PMD_DRV_LOG(DEBUG, "Copy ct action process failed.");
635 : 0 : return false;
636 : : }
637 : :
638 : : return true;
639 : : }
640 : :
641 : : static bool
642 : 0 : nfp_ct_flow_actions_copy(const struct rte_flow_action *src,
643 : : struct rte_flow_action *dst,
644 : : uint8_t action_cnt)
645 : : {
646 : : bool ret;
647 : : uint8_t loop;
648 : :
649 [ # # ]: 0 : for (loop = 0; loop < action_cnt; ++loop) {
650 : 0 : ret = nfp_ct_flow_action_copy(src + loop, dst + loop);
651 [ # # ]: 0 : if (!ret) {
652 : 0 : PMD_DRV_LOG(DEBUG, "Copy ct action failed.");
653 : : nfp_ct_flow_actions_free(dst, loop);
654 : : return false;
655 : : }
656 : : }
657 : :
658 : : return true;
659 : : }
660 : :
661 : : static struct nfp_ct_flow_entry *
662 : 0 : nfp_ct_flow_entry_get(struct nfp_ct_zone_entry *ze,
663 : : struct rte_eth_dev *dev,
664 : : const struct rte_flow_item items[],
665 : : const struct rte_flow_action actions[],
666 : : uint64_t cookie)
667 : : {
668 : : bool ret;
669 : : uint8_t loop;
670 : : uint8_t item_cnt = 1; /* The RTE_FLOW_ITEM_TYPE_END */
671 : : uint8_t action_cnt = 1; /* The RTE_FLOW_ACTION_TYPE_END */
672 : : struct nfp_flow_priv *priv;
673 : : struct nfp_ct_map_entry *me;
674 : : struct nfp_ct_flow_entry *fe;
675 : : struct nfp_flower_representor *repr;
676 : :
677 : 0 : fe = rte_zmalloc("ct_flow_entry", sizeof(*fe), 0);
678 [ # # ]: 0 : if (fe == NULL) {
679 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct_flow entry.");
680 : 0 : return NULL;
681 : : }
682 : :
683 : 0 : fe->ze = ze;
684 : 0 : fe->dev = dev;
685 : 0 : fe->cookie = cookie;
686 : 0 : LIST_INIT(&fe->children);
687 : :
688 [ # # ]: 0 : for (loop = 0; (items + loop)->type != RTE_FLOW_ITEM_TYPE_END; loop++)
689 : 0 : item_cnt++;
690 [ # # ]: 0 : for (loop = 0; (actions + loop)->type != RTE_FLOW_ACTION_TYPE_END; loop++)
691 : 0 : action_cnt++;
692 : :
693 : 0 : fe->rule.items = rte_zmalloc("ct_flow_item",
694 : : sizeof(struct rte_flow_item) * item_cnt, 0);
695 [ # # ]: 0 : if (fe->rule.items == NULL) {
696 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct flow items.");
697 : 0 : goto free_flow_entry;
698 : : }
699 : :
700 : 0 : fe->rule.actions = rte_zmalloc("ct_flow_action",
701 : : sizeof(struct rte_flow_action) * action_cnt, 0);
702 [ # # ]: 0 : if (fe->rule.actions == NULL) {
703 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct flow actions.");
704 : 0 : goto free_flow_item;
705 : : }
706 : :
707 : : /* Deep copy of items */
708 : 0 : ret = nfp_ct_flow_items_copy(items, fe->rule.items, item_cnt);
709 [ # # ]: 0 : if (!ret) {
710 : 0 : PMD_DRV_LOG(ERR, "Could not deep copy ct flow items.");
711 : 0 : goto free_flow_action;
712 : : }
713 : :
714 : : /* Deep copy of actions */
715 : 0 : ret = nfp_ct_flow_actions_copy(actions, fe->rule.actions, action_cnt);
716 [ # # ]: 0 : if (!ret) {
717 : 0 : PMD_DRV_LOG(ERR, "Could not deep copy ct flow actions.");
718 : 0 : goto free_copied_items;
719 : : }
720 : :
721 : 0 : fe->rule.items_cnt = item_cnt;
722 : 0 : fe->rule.actions_cnt = action_cnt;
723 : :
724 : : /* Now add a ct map entry */
725 : 0 : me = rte_zmalloc("ct_map_entry", sizeof(*me), 0);
726 [ # # ]: 0 : if (me == NULL) {
727 : 0 : PMD_DRV_LOG(ERR, "Malloc memory for ct map entry failed.");
728 : 0 : goto free_copied_actions;
729 : : }
730 : :
731 : 0 : me->cookie = fe->cookie;
732 : 0 : me->fe = fe;
733 : :
734 : 0 : repr = dev->data->dev_private;
735 : 0 : priv = repr->app_fw_flower->flow_priv;
736 : 0 : ret = nfp_ct_map_table_add(priv, me);
737 [ # # ]: 0 : if (!ret) {
738 : 0 : PMD_DRV_LOG(ERR, "Add into ct map table failed.");
739 : 0 : goto free_map_entry;
740 : : }
741 : :
742 : : return fe;
743 : :
744 : : free_map_entry:
745 : : nfp_ct_map_entry_destroy(me);
746 : 0 : free_copied_actions:
747 : 0 : nfp_ct_flow_actions_free(fe->rule.actions, action_cnt);
748 : 0 : free_copied_items:
749 : 0 : nfp_ct_flow_items_free(fe->rule.items, item_cnt);
750 : 0 : free_flow_action:
751 : 0 : rte_free(fe->rule.actions);
752 : 0 : free_flow_item:
753 : 0 : rte_free(fe->rule.items);
754 : 0 : free_flow_entry:
755 : 0 : rte_free(fe);
756 : :
757 : 0 : return NULL;
758 : : }
759 : :
760 : : static void
761 : 0 : nfp_flow_children_merge_free(struct nfp_ct_flow_entry *fe)
762 : : {
763 : : struct nfp_ct_merge_entry *m_ent;
764 : :
765 [ # # # ]: 0 : switch (fe->type) {
766 : 0 : case CT_TYPE_PRE_CT:
767 [ # # ]: 0 : LIST_FOREACH(m_ent, &fe->children, pre_ct_list)
768 : 0 : nfp_ct_merge_entry_destroy(m_ent);
769 : : break;
770 : 0 : case CT_TYPE_POST_CT:
771 [ # # ]: 0 : LIST_FOREACH(m_ent, &fe->children, post_ct_list)
772 : 0 : nfp_ct_merge_entry_destroy(m_ent);
773 : : break;
774 : : default:
775 : : break;
776 : : }
777 : 0 : }
778 : :
779 : : static void
780 : 0 : nfp_ct_flow_entry_destroy_partly(struct nfp_ct_flow_entry *fe)
781 : : {
782 : : struct nfp_ct_map_entry *me;
783 : :
784 [ # # ]: 0 : if (!LIST_EMPTY(&fe->children))
785 : 0 : nfp_flow_children_merge_free(fe);
786 : :
787 : 0 : me = nfp_ct_map_table_search(fe->ze->priv, (char *)&fe->cookie, sizeof(uint64_t));
788 [ # # ]: 0 : if (me != NULL) {
789 : 0 : nfp_ct_map_table_delete(fe->ze->priv, me);
790 : : nfp_ct_map_entry_destroy(me);
791 : : }
792 : :
793 : 0 : nfp_ct_flow_actions_free(fe->rule.actions, fe->rule.actions_cnt);
794 : 0 : nfp_ct_flow_items_free(fe->rule.items, fe->rule.items_cnt);
795 : 0 : rte_free(fe->rule.actions);
796 : 0 : rte_free(fe->rule.items);
797 : 0 : rte_free(fe);
798 : 0 : }
799 : :
800 : : static void
801 : 0 : nfp_ct_flow_entry_destroy(struct nfp_ct_flow_entry *fe)
802 : : {
803 [ # # ]: 0 : LIST_REMOVE(fe, pre_ct_list);
804 [ # # ]: 0 : LIST_REMOVE(fe, post_ct_list);
805 : :
806 : 0 : nfp_ct_flow_entry_destroy_partly(fe);
807 : 0 : }
808 : :
809 : : static struct nfp_ct_zone_entry *
810 : 0 : nfp_ct_zone_table_search(struct nfp_flow_priv *priv,
811 : : char *hash_data,
812 : : uint32_t hash_len)
813 : : {
814 : : int index;
815 : : uint32_t hash_key;
816 : : struct nfp_ct_zone_entry *ze;
817 : :
818 : 0 : hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
819 : 0 : index = rte_hash_lookup_data(priv->ct_zone_table, &hash_key, (void **)&ze);
820 [ # # ]: 0 : if (index < 0) {
821 : 0 : PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_zone table.");
822 : 0 : return NULL;
823 : : }
824 : :
825 : 0 : return ze;
826 : : }
827 : :
828 : : static bool
829 : 0 : nfp_ct_zone_table_add(struct nfp_flow_priv *priv,
830 : : struct nfp_ct_zone_entry *ze)
831 : : {
832 : : int ret;
833 : : uint32_t hash_key;
834 : :
835 : 0 : hash_key = rte_jhash(ze, sizeof(uint32_t), priv->hash_seed);
836 : 0 : ret = rte_hash_add_key_data(priv->ct_zone_table, &hash_key, ze);
837 [ # # ]: 0 : if (ret != 0) {
838 : 0 : PMD_DRV_LOG(ERR, "Add to the ct_zone table failed.");
839 : 0 : return false;
840 : : }
841 : :
842 : : return true;
843 : : }
844 : :
845 : : static void
846 : 0 : nfp_ct_zone_table_delete(struct nfp_flow_priv *priv,
847 : : struct nfp_ct_zone_entry *ze)
848 : : {
849 : : int ret;
850 : : uint32_t hash_key;
851 : :
852 : 0 : hash_key = rte_jhash(ze, sizeof(uint32_t), priv->hash_seed);
853 : 0 : ret = rte_hash_del_key(priv->ct_zone_table, &hash_key);
854 [ # # ]: 0 : if (ret < 0)
855 : 0 : PMD_DRV_LOG(ERR, "Delete from the ct_zone table failed.");
856 : 0 : }
857 : :
858 : : static bool
859 : 0 : nfp_ct_zone_entry_init(struct nfp_ct_zone_entry *ze,
860 : : struct nfp_flow_priv *priv,
861 : : uint32_t zone,
862 : : bool wildcard)
863 : : {
864 : : char hash_name[RTE_HASH_NAMESIZE];
865 : 0 : struct rte_hash_parameters ct_merge_hash_params = {
866 : : .entries = 1000,
867 : : .hash_func = rte_jhash,
868 : 0 : .socket_id = rte_socket_id(),
869 : : .key_len = sizeof(uint32_t),
870 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
871 : : };
872 : :
873 [ # # ]: 0 : if (wildcard) {
874 : 0 : ct_merge_hash_params.name = "ct_wc_merge_table";
875 : : } else {
876 : 0 : snprintf(hash_name, sizeof(hash_name), "ct_%d_merge_table", ze->zone);
877 : 0 : ct_merge_hash_params.name = hash_name;
878 : : }
879 : :
880 : 0 : ct_merge_hash_params.hash_func_init_val = priv->hash_seed;
881 : 0 : ze->ct_merge_table = rte_hash_create(&ct_merge_hash_params);
882 [ # # ]: 0 : if (ze->ct_merge_table == NULL) {
883 : 0 : PMD_DRV_LOG(ERR, "CT merge table creation failed.");
884 : 0 : return false;
885 : : }
886 : :
887 : 0 : ze->zone = zone;
888 : 0 : ze->priv = priv;
889 : 0 : LIST_INIT(&ze->pre_ct_list);
890 : 0 : LIST_INIT(&ze->post_ct_list);
891 : :
892 : 0 : return true;
893 : : }
894 : :
895 : : static void
896 : 0 : nfp_ct_zone_entry_destroy(struct nfp_ct_zone_entry *ze)
897 : : {
898 : : struct nfp_ct_flow_entry *fe;
899 : :
900 [ # # ]: 0 : if (ze == NULL)
901 : : return;
902 : :
903 : 0 : rte_hash_free(ze->ct_merge_table);
904 : :
905 [ # # ]: 0 : LIST_FOREACH(fe, &ze->pre_ct_list, pre_ct_list)
906 : 0 : nfp_ct_flow_entry_destroy(fe);
907 : :
908 [ # # ]: 0 : LIST_FOREACH(fe, &ze->post_ct_list, post_ct_list)
909 : 0 : nfp_ct_flow_entry_destroy(fe);
910 : :
911 : 0 : rte_free(ze);
912 : : }
913 : :
914 : : static struct nfp_ct_zone_entry *
915 : 0 : nfp_ct_zone_entry_get(struct nfp_flow_priv *priv,
916 : : uint32_t zone,
917 : : bool wildcard)
918 : : {
919 : : bool is_ok;
920 : : struct nfp_ct_zone_entry *ze;
921 : :
922 [ # # ]: 0 : if (wildcard) {
923 [ # # ]: 0 : if (priv->ct_zone_wc != NULL)
924 : : return priv->ct_zone_wc;
925 : :
926 : 0 : ze = rte_zmalloc("ct_zone_wc", sizeof(*ze), 0);
927 [ # # ]: 0 : if (ze == NULL) {
928 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct_zone_wc entry.");
929 : 0 : return NULL;
930 : : }
931 : :
932 : 0 : is_ok = nfp_ct_zone_entry_init(ze, priv, zone, true);
933 [ # # ]: 0 : if (!is_ok) {
934 : 0 : PMD_DRV_LOG(ERR, "Init ct zone wc entry failed.");
935 : 0 : goto free_ct_zone_entry;
936 : : }
937 : :
938 : 0 : priv->ct_zone_wc = ze;
939 : : } else {
940 : 0 : ze = nfp_ct_zone_table_search(priv, (char *)&zone, sizeof(uint32_t));
941 [ # # ]: 0 : if (ze != NULL)
942 : : return ze;
943 : :
944 : 0 : ze = rte_zmalloc("ct_zone_entry", sizeof(*ze), 0);
945 [ # # ]: 0 : if (ze == NULL) {
946 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct_zone entry.");
947 : 0 : return NULL;
948 : : }
949 : :
950 : 0 : is_ok = nfp_ct_zone_entry_init(ze, priv, zone, false);
951 [ # # ]: 0 : if (!is_ok) {
952 : 0 : PMD_DRV_LOG(ERR, "Init ct zone entry failed.");
953 : 0 : goto free_ct_zone_entry;
954 : : }
955 : :
956 : 0 : is_ok = nfp_ct_zone_table_add(priv, ze);
957 [ # # ]: 0 : if (!is_ok) {
958 : 0 : PMD_DRV_LOG(ERR, "Add into ct zone table failed.");
959 : 0 : goto free_ct_zone_entry;
960 : : }
961 : : }
962 : :
963 : : return ze;
964 : :
965 : 0 : free_ct_zone_entry:
966 : 0 : nfp_ct_zone_entry_destroy(ze);
967 : :
968 : 0 : return NULL;
969 : : }
970 : :
971 : : static void
972 : 0 : nfp_ct_zone_entry_free(struct nfp_ct_zone_entry *ze,
973 : : bool wildcard)
974 : : {
975 [ # # # # ]: 0 : if (LIST_EMPTY(&ze->pre_ct_list) && LIST_EMPTY(&ze->post_ct_list)) {
976 [ # # ]: 0 : if (!wildcard)
977 : 0 : nfp_ct_zone_table_delete(ze->priv, ze);
978 : :
979 : 0 : nfp_ct_zone_entry_destroy(ze);
980 : : }
981 : 0 : }
982 : :
983 : : static int
984 : 0 : nfp_ct_offload_add(struct rte_eth_dev *dev,
985 : : struct nfp_ct_merge_entry *merge_entry)
986 : : {
987 : : int ret;
988 : : uint64_t cookie;
989 : : struct rte_flow *nfp_flow;
990 : : struct nfp_flow_priv *priv;
991 : : const struct rte_flow_item *items;
992 : : struct nfp_flower_representor *repr;
993 : : const struct rte_flow_action *actions;
994 : :
995 : 0 : cookie = rte_rand();
996 : 0 : items = merge_entry->rule.items;
997 : 0 : actions = merge_entry->rule.actions;
998 : 0 : nfp_flow = nfp_flow_process(dev, items, actions, false, cookie, true, true);
999 [ # # ]: 0 : if (nfp_flow == NULL) {
1000 : 0 : PMD_DRV_LOG(ERR, "Process the merged flow rule failed.");
1001 : 0 : return -EINVAL;
1002 : : }
1003 : :
1004 [ # # ]: 0 : merge_entry->ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id);
1005 : :
1006 : : /* Add the flow to hardware */
1007 : 0 : repr = dev->data->dev_private;
1008 : 0 : priv = repr->app_fw_flower->flow_priv;
1009 : 0 : ret = nfp_flower_cmsg_flow_add(repr->app_fw_flower, nfp_flow);
1010 [ # # ]: 0 : if (ret != 0) {
1011 : 0 : PMD_DRV_LOG(ERR, "Add the merged flow to firmware failed.");
1012 : 0 : goto flow_teardown;
1013 : : }
1014 : :
1015 : : /* Add the flow to flow hash table */
1016 : 0 : ret = nfp_flow_table_add_merge(priv, nfp_flow);
1017 [ # # ]: 0 : if (ret != 0) {
1018 : 0 : PMD_DRV_LOG(ERR, "Add the merged flow to flow table failed.");
1019 : 0 : goto flow_teardown;
1020 : : }
1021 : :
1022 : 0 : merge_entry->compiled_rule = nfp_flow;
1023 : :
1024 : 0 : return 0;
1025 : :
1026 : 0 : flow_teardown:
1027 : 0 : nfp_flow_teardown(repr->app_fw_flower, nfp_flow, false);
1028 : 0 : nfp_flow_free(nfp_flow);
1029 : :
1030 : 0 : return ret;
1031 : : }
1032 : :
1033 : : int
1034 : 0 : nfp_ct_offload_del(struct rte_eth_dev *dev,
1035 : : struct nfp_ct_map_entry *me,
1036 : : struct rte_flow_error *error)
1037 : : {
1038 : : int ret;
1039 : : struct nfp_ct_flow_entry *fe;
1040 : : struct nfp_ct_merge_entry *m_ent;
1041 : :
1042 : 0 : fe = me->fe;
1043 : :
1044 [ # # ]: 0 : if (fe->type == CT_TYPE_PRE_CT) {
1045 [ # # ]: 0 : LIST_FOREACH(m_ent, &fe->children, pre_ct_list) {
1046 [ # # ]: 0 : if (m_ent->compiled_rule != NULL) {
1047 : 0 : ret = nfp_flow_destroy(dev, m_ent->compiled_rule, error);
1048 [ # # ]: 0 : if (ret != 0) {
1049 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct_flow_item.");
1050 : 0 : return -EINVAL;
1051 : : }
1052 : 0 : m_ent->compiled_rule = NULL;
1053 : : }
1054 : :
1055 : 0 : m_ent->pre_ct_parent = NULL;
1056 [ # # ]: 0 : LIST_REMOVE(m_ent, pre_ct_list);
1057 [ # # ]: 0 : if (m_ent->post_ct_parent == NULL)
1058 : 0 : nfp_ct_merge_entry_destroy(m_ent);
1059 : : }
1060 : : } else {
1061 [ # # ]: 0 : LIST_FOREACH(m_ent, &fe->children, post_ct_list) {
1062 [ # # ]: 0 : if (m_ent->compiled_rule != NULL) {
1063 : 0 : ret = nfp_flow_destroy(dev, m_ent->compiled_rule, error);
1064 [ # # ]: 0 : if (ret != 0) {
1065 : 0 : PMD_DRV_LOG(ERR, "Could not alloc ct_flow_item.");
1066 : 0 : return -EINVAL;
1067 : : }
1068 : 0 : m_ent->compiled_rule = NULL;
1069 : : }
1070 : :
1071 : 0 : m_ent->post_ct_parent = NULL;
1072 [ # # ]: 0 : LIST_REMOVE(m_ent, post_ct_list);
1073 [ # # ]: 0 : if (m_ent->pre_ct_parent == NULL)
1074 : 0 : nfp_ct_merge_entry_destroy(m_ent);
1075 : : }
1076 : : }
1077 : :
1078 : 0 : nfp_ct_flow_entry_destroy_partly(fe);
1079 : :
1080 : 0 : return 0;
1081 : : }
1082 : :
1083 : : static inline bool
1084 : 0 : is_item_check_pass(const struct rte_flow_item *item1,
1085 : : const struct rte_flow_item *item2,
1086 : : uint8_t *cnt_same)
1087 : : {
1088 : : bool pass;
1089 : : uint32_t i;
1090 : : size_t size;
1091 : 0 : const char *key1 = item1->spec;
1092 : 0 : const char *key2 = item2->spec;
1093 : 0 : const char *mask1 = item1->mask;
1094 : 0 : const char *mask2 = item2->mask;
1095 : :
1096 [ # # ]: 0 : if (item1->type != item2->type)
1097 : : return true;
1098 : :
1099 : 0 : pass = nfp_flow_item_conf_size_get(item1->type, &size);
1100 [ # # ]: 0 : if (!pass)
1101 : : return false;
1102 : :
1103 [ # # ]: 0 : for (i = 0; i < size; i++) {
1104 [ # # ]: 0 : if ((key1[i] & mask1[i] & mask2[i]) ^ (key2[i] & mask1[i] & mask2[i]))
1105 : : return false;
1106 : : }
1107 : :
1108 : 0 : *cnt_same = *cnt_same + 1;
1109 : :
1110 : 0 : return true;
1111 : : }
1112 : :
1113 : : static bool
1114 : 0 : nfp_ct_merge_items_check(struct rte_flow_item *items1,
1115 : : struct rte_flow_item *items2,
1116 : : uint8_t *cnt_same)
1117 : : {
1118 : : bool pass;
1119 : : bool is_tun_flow_1;
1120 : : bool is_tun_flow_2;
1121 : : const struct rte_flow_item *item1;
1122 : : const struct rte_flow_item *item2;
1123 : 0 : const struct rte_flow_item *inner_item1 = NULL;
1124 : 0 : const struct rte_flow_item *inner_item2 = NULL;
1125 : :
1126 : 0 : is_tun_flow_1 = nfp_flow_inner_item_get(items1, &inner_item1);
1127 : 0 : is_tun_flow_2 = nfp_flow_inner_item_get(items2, &inner_item2);
1128 : :
1129 [ # # ]: 0 : if (is_tun_flow_1) {
1130 [ # # ]: 0 : if (is_tun_flow_2) {
1131 : : /* Outer layer */
1132 [ # # ]: 0 : for (item1 = items1; item1 != inner_item1; item1++) {
1133 [ # # ]: 0 : for (item2 = items2; item2 != inner_item2; item2++) {
1134 : 0 : pass = is_item_check_pass(item1, item2, cnt_same);
1135 [ # # ]: 0 : if (!pass)
1136 : : return false;
1137 : : }
1138 : : }
1139 : : /* Inner layer */
1140 [ # # ]: 0 : for (item1 = inner_item1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
1141 [ # # ]: 0 : for (item2 = inner_item2; item2->type != RTE_FLOW_ITEM_TYPE_END;
1142 : 0 : item2++) {
1143 : 0 : pass = is_item_check_pass(item1, item2, cnt_same);
1144 [ # # ]: 0 : if (!pass)
1145 : : return false;
1146 : : }
1147 : : }
1148 : : } else {
1149 [ # # ]: 0 : for (item1 = items1; item1 != inner_item1; item1++) {
1150 [ # # ]: 0 : for (item2 = items2; item2->type != RTE_FLOW_ITEM_TYPE_END;
1151 : 0 : item2++) {
1152 : 0 : pass = is_item_check_pass(item1, item2, cnt_same);
1153 [ # # ]: 0 : if (!pass)
1154 : : return false;
1155 : : }
1156 : : }
1157 : : }
1158 : : } else {
1159 [ # # ]: 0 : if (is_tun_flow_2) {
1160 [ # # ]: 0 : for (item1 = items1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
1161 [ # # ]: 0 : for (item2 = items2; item2 != inner_item2; item2++) {
1162 : 0 : pass = is_item_check_pass(item1, item2, cnt_same);
1163 [ # # ]: 0 : if (!pass)
1164 : : return false;
1165 : : }
1166 : : }
1167 : : } else {
1168 [ # # ]: 0 : for (item1 = items1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
1169 [ # # ]: 0 : for (item2 = items2; item2->type != RTE_FLOW_ITEM_TYPE_END;
1170 : 0 : item2++) {
1171 : 0 : pass = is_item_check_pass(item1, item2, cnt_same);
1172 [ # # ]: 0 : if (!pass)
1173 : : return false;
1174 : : }
1175 : : }
1176 : : }
1177 : : }
1178 : :
1179 : : return true;
1180 : : }
1181 : :
1182 : : static inline bool
1183 : : is_action_pattern_check_pass(struct rte_flow_item *items,
1184 : : enum rte_flow_item_type type)
1185 : : {
1186 : : struct rte_flow_item *item;
1187 : :
1188 [ # # # # : 0 : for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
# # # # #
# # # ]
1189 [ # # # # : 0 : if (item->type == type)
# # # # #
# # # ]
1190 : : return false;
1191 : : }
1192 : :
1193 : : return true;
1194 : : }
1195 : :
1196 : : static bool
1197 : 0 : nfp_ct_merge_action_check(struct rte_flow_action *action,
1198 : : struct rte_flow_item *items)
1199 : : {
1200 : : bool pass = true;
1201 : :
1202 [ # # # # : 0 : switch (action->type) {
# ]
1203 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: /* FALLTHROUGH */
1204 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
1205 : : pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_ETH);
1206 : : break;
1207 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: /* FALLTHROUGH */
1208 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: /* FALLTHROUGH */
1209 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
1210 : : pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_IPV4);
1211 : : break;
1212 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: /* FALLTHROUGH */
1213 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: /* FALLTHROUGH */
1214 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
1215 : : pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_IPV6);
1216 : : break;
1217 : : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: /* FALLTHROUGH */
1218 : : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
1219 : : pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_UDP);
1220 : 0 : pass |= is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_TCP);
1221 : 0 : pass |= is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_SCTP);
1222 : 0 : break;
1223 : : default:
1224 : : break;
1225 : : }
1226 : :
1227 : 0 : return pass;
1228 : : }
1229 : :
1230 : : static bool
1231 : 0 : nfp_ct_merge_actions_check(struct rte_flow_action *actions,
1232 : : struct rte_flow_item *items,
1233 : : uint8_t *cnt_same)
1234 : : {
1235 : : bool pass = true;
1236 : : struct rte_flow_action *action;
1237 : :
1238 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
1239 [ # # # ]: 0 : switch (action->type) {
1240 : 0 : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: /* FALLTHROUGH */
1241 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: /* FALLTHROUGH */
1242 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: /* FALLTHROUGH */
1243 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: /* FALLTHROUGH */
1244 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: /* FALLTHROUGH */
1245 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: /* FALLTHROUGH */
1246 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: /* FALLTHROUGH */
1247 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP: /* FALLTHROUGH */
1248 : : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: /* FALLTHROUGH */
1249 : : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
1250 : 0 : pass = nfp_ct_merge_action_check(action, items);
1251 : 0 : break;
1252 : 0 : case RTE_FLOW_ACTION_TYPE_CONNTRACK: /* FALLTHROUGH */
1253 : : case RTE_FLOW_ACTION_TYPE_JUMP: /* FALLTHROUGH */
1254 : : case RTE_FLOW_ACTION_TYPE_COUNT: /* FALLTHROUGH */
1255 : : case RTE_FLOW_ACTION_TYPE_DROP: /* FALLTHROUGH */
1256 : : case RTE_FLOW_ACTION_TYPE_VOID:
1257 : 0 : *cnt_same = *cnt_same + 1;
1258 : 0 : break;
1259 : : default:
1260 : : pass = false;
1261 : : break;
1262 : : }
1263 : : }
1264 : :
1265 : 0 : return pass;
1266 : : }
1267 : :
1268 : : static void
1269 : 0 : nfp_ct_merge_item_real(const struct rte_flow_item *item_src,
1270 : : struct rte_flow_item *item_dst)
1271 : : {
1272 : : uint32_t i;
1273 : : char *key_dst;
1274 : : char *mask_dst;
1275 : 0 : size_t size = 0;
1276 : : const char *key_src;
1277 : : const char *mask_src;
1278 : :
1279 : 0 : key_src = item_src->spec;
1280 : 0 : mask_src = item_src->mask;
1281 : 0 : key_dst = (char *)(ptrdiff_t)item_dst->spec;
1282 : 0 : mask_dst = (char *)(ptrdiff_t)item_dst->mask;
1283 : 0 : nfp_flow_item_conf_size_get(item_src->type, &size);
1284 : :
1285 [ # # ]: 0 : for (i = 0; i < size; i++) {
1286 : 0 : key_dst[i] |= key_src[i];
1287 : 0 : mask_dst[i] |= mask_src[i];
1288 : : }
1289 : 0 : }
1290 : :
1291 : : static bool
1292 : 0 : nfp_ct_merge_item(uint32_t index,
1293 : : const struct rte_flow_item *item1,
1294 : : const struct rte_flow_item *item2_start,
1295 : : const struct rte_flow_item *item2_end,
1296 : : struct nfp_ct_merge_entry *merge_entry)
1297 : : {
1298 : : struct rte_flow_item *item;
1299 : : const struct rte_flow_item *item2;
1300 : :
1301 : : /* Copy to the merged items */
1302 : 0 : item = &merge_entry->rule.items[index];
1303 : 0 : *item = *item1;
1304 : :
1305 : : item2 = item2_start;
1306 [ # # ]: 0 : if (item2_end != NULL) {
1307 [ # # ]: 0 : for (; item2 != item2_end; item2++) {
1308 [ # # ]: 0 : if (item1->type == item2->type) {
1309 : 0 : nfp_ct_merge_item_real(item2, item);
1310 : 0 : return true;
1311 : : }
1312 : : }
1313 : : } else {
1314 [ # # ]: 0 : for (; item2->type != RTE_FLOW_ITEM_TYPE_END; item2++) {
1315 [ # # ]: 0 : if (item1->type == item2->type) {
1316 : 0 : nfp_ct_merge_item_real(item2, item);
1317 : 0 : return true;
1318 : : }
1319 : : }
1320 : : }
1321 : :
1322 : : return false;
1323 : : }
1324 : :
1325 : : static void
1326 : 0 : nfp_ct_merge_items(struct nfp_ct_merge_entry *merge_entry)
1327 : : {
1328 : : uint32_t index = 0;
1329 : : bool is_tun_flow_1;
1330 : : bool is_tun_flow_2;
1331 : : struct rte_flow_item *items1;
1332 : : struct rte_flow_item *items2;
1333 : : struct rte_flow_item *merge_item;
1334 : : const struct rte_flow_item *item;
1335 : 0 : const struct rte_flow_item *inner1 = NULL;
1336 : 0 : const struct rte_flow_item *inner2 = NULL;
1337 : :
1338 : 0 : items1 = merge_entry->pre_ct_parent->rule.items;
1339 : 0 : items2 = merge_entry->post_ct_parent->rule.items;
1340 : 0 : is_tun_flow_1 = nfp_flow_inner_item_get(items1, &inner1);
1341 : 0 : is_tun_flow_2 = nfp_flow_inner_item_get(items2, &inner2);
1342 : :
1343 [ # # ]: 0 : if (is_tun_flow_1) {
1344 [ # # ]: 0 : if (is_tun_flow_2) {
1345 : : /* Outer layer */
1346 [ # # ]: 0 : for (item = items1; item != inner1; item++, index++) {
1347 [ # # ]: 0 : if (nfp_ct_merge_item(index, item, items2, inner2, merge_entry))
1348 : 0 : items2++;
1349 : : }
1350 : :
1351 : : /* Copy the remainning outer layer items */
1352 [ # # ]: 0 : for (item = items2; item != inner2; item++, index++) {
1353 : 0 : merge_item = &merge_entry->rule.items[index];
1354 : 0 : *merge_item = *item;
1355 : : }
1356 : :
1357 : : /* Inner layer */
1358 [ # # ]: 0 : for (item = inner1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1359 [ # # ]: 0 : if (nfp_ct_merge_item(index, item, inner2, NULL, merge_entry))
1360 : 0 : items2++;
1361 : : }
1362 : :
1363 : : /* Copy the remainning inner layer items */
1364 [ # # ]: 0 : for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1365 : 0 : merge_item = &merge_entry->rule.items[index];
1366 : 0 : *merge_item = *item;
1367 : : }
1368 : : } else {
1369 [ # # ]: 0 : for (item = items1; item != inner1; item++, index++) {
1370 [ # # ]: 0 : if (nfp_ct_merge_item(index, item, items2, NULL, merge_entry))
1371 : 0 : items2++;
1372 : : }
1373 : :
1374 : : /* Copy the remainning items */
1375 [ # # ]: 0 : for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1376 : 0 : merge_item = &merge_entry->rule.items[index];
1377 : 0 : *merge_item = *item;
1378 : : }
1379 : :
1380 : : /* Copy the inner layer items */
1381 [ # # ]: 0 : for (item = inner1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1382 : 0 : merge_item = &merge_entry->rule.items[index];
1383 : 0 : *merge_item = *item;
1384 : : }
1385 : : }
1386 : : } else {
1387 [ # # ]: 0 : if (is_tun_flow_2) {
1388 [ # # ]: 0 : for (item = items1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1389 [ # # ]: 0 : if (nfp_ct_merge_item(index, item, items2, inner2, merge_entry))
1390 : 0 : items2++;
1391 : : }
1392 : :
1393 : : /* Copy the remainning items */
1394 [ # # ]: 0 : for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1395 : 0 : merge_item = &merge_entry->rule.items[index];
1396 : 0 : *merge_item = *item;
1397 : : }
1398 : : } else {
1399 [ # # ]: 0 : for (item = items1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1400 [ # # ]: 0 : if (nfp_ct_merge_item(index, item, items2, NULL, merge_entry))
1401 : 0 : items2++;
1402 : : }
1403 : :
1404 : : /* Copy the remainning items */
1405 [ # # ]: 0 : for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
1406 : 0 : merge_item = &merge_entry->rule.items[index];
1407 : 0 : *merge_item = *item;
1408 : : }
1409 : : }
1410 : : }
1411 : 0 : }
1412 : :
1413 : : static void
1414 : 0 : nfp_ct_merge_actions(struct nfp_ct_merge_entry *merge_entry)
1415 : : {
1416 : : struct rte_flow_action *action;
1417 : : struct rte_flow_action *merge_actions;
1418 : :
1419 : 0 : merge_actions = merge_entry->rule.actions;
1420 : :
1421 : 0 : action = merge_entry->pre_ct_parent->rule.actions;
1422 [ # # ]: 0 : for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
1423 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK ||
1424 : : action->type == RTE_FLOW_ACTION_TYPE_JUMP)
1425 : 0 : continue;
1426 : :
1427 : 0 : *merge_actions = *action;
1428 : 0 : merge_actions++;
1429 : : }
1430 : :
1431 : 0 : action = merge_entry->post_ct_parent->rule.actions;
1432 [ # # ]: 0 : for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
1433 : 0 : *merge_actions = *action;
1434 : 0 : merge_actions++;
1435 : : }
1436 : 0 : }
1437 : :
1438 : : static bool
1439 : 0 : nfp_ct_do_flow_merge(struct nfp_ct_zone_entry *ze,
1440 : : struct nfp_ct_flow_entry *pre_ct_entry,
1441 : : struct nfp_ct_flow_entry *post_ct_entry)
1442 : : {
1443 : : bool ret;
1444 : : uint64_t new_cookie[2];
1445 : 0 : uint8_t cnt_same_item = 0;
1446 : 0 : uint8_t cnt_same_action = 0;
1447 : : struct nfp_ct_merge_entry *merge_entry;
1448 : :
1449 [ # # ]: 0 : if (pre_ct_entry->dev != post_ct_entry->dev)
1450 : : return true;
1451 : :
1452 : 0 : ret = nfp_ct_merge_items_check(pre_ct_entry->rule.items,
1453 : : post_ct_entry->rule.items, &cnt_same_item);
1454 [ # # ]: 0 : if (!ret)
1455 : : return true;
1456 : :
1457 : 0 : ret = nfp_ct_merge_actions_check(pre_ct_entry->rule.actions,
1458 : : post_ct_entry->rule.items, &cnt_same_action);
1459 [ # # ]: 0 : if (!ret)
1460 : : return true;
1461 : :
1462 : 0 : new_cookie[0] = pre_ct_entry->cookie;
1463 : 0 : new_cookie[1] = post_ct_entry->cookie;
1464 : 0 : merge_entry = nfp_ct_merge_table_search(ze, (char *)&new_cookie, sizeof(uint64_t) * 2);
1465 [ # # ]: 0 : if (merge_entry != NULL)
1466 : : return true;
1467 : :
1468 : 0 : merge_entry = rte_zmalloc("ct_merge_entry", sizeof(*merge_entry), 0);
1469 [ # # ]: 0 : if (merge_entry == NULL) {
1470 : 0 : PMD_DRV_LOG(ERR, "Malloc memory for ct merge entry failed.");
1471 : 0 : return false;
1472 : : }
1473 : :
1474 : 0 : merge_entry->ze = ze;
1475 : 0 : merge_entry->pre_ct_parent = pre_ct_entry;
1476 : 0 : merge_entry->post_ct_parent = post_ct_entry;
1477 [ # # ]: 0 : rte_memcpy(merge_entry->cookie, new_cookie, sizeof(new_cookie));
1478 : 0 : merge_entry->rule.items_cnt = pre_ct_entry->rule.items_cnt +
1479 : 0 : post_ct_entry->rule.items_cnt - cnt_same_item - 1;
1480 : 0 : merge_entry->rule.actions_cnt = pre_ct_entry->rule.actions_cnt +
1481 : 0 : post_ct_entry->rule.actions_cnt - cnt_same_action - 1;
1482 : :
1483 : 0 : merge_entry->rule.items = rte_zmalloc("ct_flow_item",
1484 : 0 : sizeof(struct rte_flow_item) * merge_entry->rule.items_cnt, 0);
1485 [ # # ]: 0 : if (merge_entry->rule.items == NULL) {
1486 : 0 : PMD_DRV_LOG(ERR, "Could not alloc items for merged flow.");
1487 : 0 : goto merge_exit;
1488 : : }
1489 : :
1490 : 0 : merge_entry->rule.actions = rte_zmalloc("ct_flow_action",
1491 : 0 : sizeof(struct rte_flow_action) * merge_entry->rule.actions_cnt, 0);
1492 [ # # ]: 0 : if (merge_entry->rule.actions == NULL) {
1493 : 0 : PMD_DRV_LOG(ERR, "Could not alloc actions for merged flow.");
1494 : 0 : goto free_items;
1495 : : }
1496 : :
1497 : 0 : nfp_ct_merge_items(merge_entry);
1498 : 0 : nfp_ct_merge_actions(merge_entry);
1499 : :
1500 : : /* Add this entry to the pre_ct and post_ct lists */
1501 [ # # ]: 0 : LIST_INSERT_HEAD(&pre_ct_entry->children, merge_entry, pre_ct_list);
1502 [ # # ]: 0 : LIST_INSERT_HEAD(&post_ct_entry->children, merge_entry, post_ct_list);
1503 : :
1504 : 0 : ret = nfp_ct_merge_table_add(ze, merge_entry);
1505 [ # # ]: 0 : if (!ret) {
1506 : 0 : PMD_DRV_LOG(ERR, "Add into ct merge table failed.");
1507 : 0 : goto free_actions;
1508 : : }
1509 : :
1510 : : /* Send to firmware */
1511 : 0 : ret = nfp_ct_offload_add(pre_ct_entry->dev, merge_entry);
1512 [ # # ]: 0 : if (ret != 0) {
1513 : 0 : PMD_DRV_LOG(ERR, "Send the merged flow to firmware failed.");
1514 : 0 : goto merge_table_del;
1515 : : }
1516 : :
1517 : : return true;
1518 : :
1519 : : merge_table_del:
1520 : 0 : nfp_ct_merge_table_delete(ze, merge_entry);
1521 : 0 : free_actions:
1522 : 0 : rte_free(merge_entry->rule.actions);
1523 : 0 : free_items:
1524 : 0 : rte_free(merge_entry->rule.items);
1525 : 0 : merge_exit:
1526 [ # # ]: 0 : LIST_REMOVE(merge_entry, post_ct_list);
1527 [ # # ]: 0 : LIST_REMOVE(merge_entry, pre_ct_list);
1528 : 0 : rte_free(merge_entry);
1529 : :
1530 : 0 : return ret;
1531 : : }
1532 : :
1533 : : static bool
1534 : 0 : nfp_ct_merge_flow_entries(struct nfp_ct_flow_entry *fe,
1535 : : struct nfp_ct_zone_entry *ze_src,
1536 : : struct nfp_ct_zone_entry *ze_dst)
1537 : : {
1538 : : bool ret;
1539 : : struct nfp_ct_flow_entry *fe_tmp;
1540 : :
1541 [ # # ]: 0 : if (fe->type == CT_TYPE_PRE_CT) {
1542 [ # # ]: 0 : LIST_FOREACH(fe_tmp, &ze_src->post_ct_list, post_ct_list) {
1543 : 0 : ret = nfp_ct_do_flow_merge(ze_dst, fe, fe_tmp);
1544 [ # # ]: 0 : if (!ret) {
1545 : 0 : PMD_DRV_LOG(ERR, "Merge for ct pre flow failed.");
1546 : 0 : return false;
1547 : : }
1548 : : }
1549 : : } else {
1550 [ # # ]: 0 : LIST_FOREACH(fe_tmp, &ze_src->pre_ct_list, pre_ct_list) {
1551 : 0 : ret = nfp_ct_do_flow_merge(ze_dst, fe_tmp, fe);
1552 [ # # ]: 0 : if (!ret) {
1553 : 0 : PMD_DRV_LOG(ERR, "Merge for ct post flow failed.");
1554 : 0 : return false;
1555 : : }
1556 : : }
1557 : : }
1558 : :
1559 : : return true;
1560 : : }
1561 : :
1562 : : static bool
1563 : 0 : nfp_flow_handle_pre_ct(const struct rte_flow_item *ct_item,
1564 : : struct rte_eth_dev *dev,
1565 : : const struct rte_flow_item items[],
1566 : : const struct rte_flow_action actions[],
1567 : : uint64_t cookie)
1568 : : {
1569 : : bool ret;
1570 : : struct nfp_flow_priv *priv;
1571 : : struct nfp_ct_zone_entry *ze;
1572 : : struct nfp_ct_flow_entry *fe;
1573 : 0 : const struct ct_data *ct = ct_item->spec;
1574 : : struct nfp_flower_representor *representor;
1575 : :
1576 : 0 : representor = dev->data->dev_private;
1577 : 0 : priv = representor->app_fw_flower->flow_priv;
1578 : 0 : ze = nfp_ct_zone_entry_get(priv, ct->ct_zone, false);
1579 [ # # ]: 0 : if (ze == NULL) {
1580 : 0 : PMD_DRV_LOG(ERR, "Could not get ct zone entry.");
1581 : 0 : return false;
1582 : : }
1583 : :
1584 : : /* Add entry to pre_ct_list */
1585 : 0 : fe = nfp_ct_flow_entry_get(ze, dev, items, actions, cookie);
1586 [ # # ]: 0 : if (fe == NULL) {
1587 : 0 : PMD_DRV_LOG(ERR, "Could not get ct flow entry.");
1588 : 0 : goto ct_zone_entry_free;
1589 : : }
1590 : :
1591 : 0 : fe->type = CT_TYPE_PRE_CT;
1592 [ # # ]: 0 : LIST_INSERT_HEAD(&ze->pre_ct_list, fe, pre_ct_list);
1593 : :
1594 : 0 : ret = nfp_ct_merge_flow_entries(fe, ze, ze);
1595 [ # # ]: 0 : if (!ret) {
1596 : 0 : PMD_DRV_LOG(ERR, "Merge ct flow entries failed.");
1597 : 0 : goto ct_flow_entry_free;
1598 : : }
1599 : :
1600 : : /* Need to check and merge with tables in the wc_zone as well */
1601 [ # # ]: 0 : if (priv->ct_zone_wc != NULL) {
1602 : 0 : ret = nfp_ct_merge_flow_entries(fe, priv->ct_zone_wc, ze);
1603 [ # # ]: 0 : if (!ret) {
1604 : 0 : PMD_DRV_LOG(ERR, "Merge ct flow entries wildcast failed.");
1605 : 0 : goto ct_flow_entry_free;
1606 : : }
1607 : : }
1608 : :
1609 : : return true;
1610 : :
1611 : 0 : ct_flow_entry_free:
1612 : 0 : nfp_ct_flow_entry_destroy(fe);
1613 : :
1614 : 0 : ct_zone_entry_free:
1615 : 0 : nfp_ct_zone_entry_free(ze, false);
1616 : :
1617 : 0 : return false;
1618 : : }
1619 : :
1620 : : static bool
1621 : 0 : nfp_flow_handle_post_ct(const struct rte_flow_item *ct_item,
1622 : : struct rte_eth_dev *dev,
1623 : : const struct rte_flow_item items[],
1624 : : const struct rte_flow_action actions[],
1625 : : uint64_t cookie)
1626 : : {
1627 : : bool ret;
1628 : : void *next_data;
1629 : 0 : uint32_t iter = 0;
1630 : : const void *next_key;
1631 : : bool wildcard = false;
1632 : : struct nfp_flow_priv *priv;
1633 : : struct nfp_ct_zone_entry *ze;
1634 : : struct nfp_ct_flow_entry *fe;
1635 : : struct nfp_flower_representor *representor;
1636 : 0 : const struct ct_data *ct = ct_item->spec;
1637 : 0 : const struct ct_data *ct_mask = ct_item->mask;
1638 : :
1639 [ # # ]: 0 : if (ct_mask->ct_zone == 0) {
1640 : : wildcard = true;
1641 [ # # ]: 0 : } else if (ct_mask->ct_zone != UINT16_MAX) {
1642 : 0 : PMD_DRV_LOG(ERR, "Partially wildcard ct_zone is not supported.");
1643 : 0 : return false;
1644 : : }
1645 : :
1646 : 0 : representor = dev->data->dev_private;
1647 : 0 : priv = representor->app_fw_flower->flow_priv;
1648 : 0 : ze = nfp_ct_zone_entry_get(priv, ct->ct_zone, wildcard);
1649 [ # # ]: 0 : if (ze == NULL) {
1650 : 0 : PMD_DRV_LOG(ERR, "Could not get ct zone entry.");
1651 : 0 : return false;
1652 : : }
1653 : :
1654 : : /* Add entry to post_ct_list */
1655 : 0 : fe = nfp_ct_flow_entry_get(ze, dev, items, actions, cookie);
1656 [ # # ]: 0 : if (fe == NULL) {
1657 : 0 : PMD_DRV_LOG(ERR, "Could not get ct flow entry.");
1658 : 0 : goto ct_zone_entry_free;
1659 : : }
1660 : :
1661 : 0 : fe->type = CT_TYPE_POST_CT;
1662 [ # # ]: 0 : LIST_INSERT_HEAD(&ze->post_ct_list, fe, post_ct_list);
1663 : :
1664 [ # # ]: 0 : if (wildcard) {
1665 [ # # ]: 0 : while (rte_hash_iterate(priv->ct_zone_table, &next_key, &next_data, &iter) >= 0) {
1666 : 0 : ze = (struct nfp_ct_zone_entry *)next_data;
1667 : 0 : ret = nfp_ct_merge_flow_entries(fe, ze, ze);
1668 [ # # ]: 0 : if (!ret) {
1669 : 0 : PMD_DRV_LOG(ERR, "Merge ct flow entries wildcast failed.");
1670 : 0 : break;
1671 : : }
1672 : : }
1673 : : } else {
1674 : 0 : ret = nfp_ct_merge_flow_entries(fe, ze, ze);
1675 : : }
1676 : :
1677 [ # # ]: 0 : if (!ret)
1678 : 0 : goto ct_flow_entry_free;
1679 : :
1680 : : return true;
1681 : :
1682 : : ct_flow_entry_free:
1683 : 0 : nfp_ct_flow_entry_destroy(fe);
1684 : :
1685 : 0 : ct_zone_entry_free:
1686 : 0 : nfp_ct_zone_entry_free(ze, wildcard);
1687 : :
1688 : 0 : return false;
1689 : : }
1690 : :
1691 : : struct rte_flow *
1692 : 0 : nfp_ct_flow_setup(struct rte_eth_dev *dev,
1693 : : const struct rte_flow_item items[],
1694 : : const struct rte_flow_action actions[],
1695 : : const struct rte_flow_item *ct_item,
1696 : : bool validate_flag,
1697 : : uint64_t cookie)
1698 : : {
1699 : : const struct ct_data *ct;
1700 : :
1701 [ # # ]: 0 : if (ct_item == NULL)
1702 : : return NULL;
1703 : :
1704 [ # # ]: 0 : ct = ct_item->spec;
1705 : :
1706 : : if (is_ct_commit_flow(ct)) {
1707 : 0 : return nfp_flow_process(dev, &items[1], actions,
1708 : : validate_flag, cookie, false, false);
1709 : : }
1710 : :
1711 : : if (is_post_ct_flow(ct)) {
1712 [ # # ]: 0 : if (nfp_flow_handle_post_ct(ct_item, dev, &items[1],
1713 : : actions, cookie)) {
1714 : 0 : return nfp_flow_process(dev, &items[1], actions,
1715 : : validate_flag, cookie, false, false);
1716 : : }
1717 : :
1718 : 0 : PMD_DRV_LOG(ERR, "Handle NFP post ct flow failed.");
1719 : 0 : return NULL;
1720 : : }
1721 : :
1722 [ # # ]: 0 : if (is_pre_ct_flow(ct, actions)) {
1723 [ # # ]: 0 : if (nfp_flow_handle_pre_ct(ct_item, dev, &items[1],
1724 : : actions, cookie)) {
1725 : 0 : return nfp_flow_process(dev, &items[1], actions,
1726 : : validate_flag, cookie, false, false);
1727 : : }
1728 : :
1729 : 0 : PMD_DRV_LOG(ERR, "Handle NFP pre ct flow failed.");
1730 : 0 : return NULL;
1731 : : }
1732 : :
1733 : 0 : PMD_DRV_LOG(ERR, "Unsupported ct flow type.");
1734 : 0 : return NULL;
1735 : : }
1736 : :
1737 : : static inline void
1738 : 0 : nfp_ct_flow_stats_update(struct nfp_flow_priv *priv,
1739 : : struct nfp_ct_merge_entry *m_ent)
1740 : : {
1741 : : uint32_t ctx_id;
1742 : : struct nfp_fl_stats *merge_stats;
1743 : :
1744 : 0 : ctx_id = m_ent->ctx_id;
1745 : 0 : merge_stats = &priv->stats[ctx_id];
1746 : :
1747 : 0 : m_ent->pre_ct_parent->stats.bytes += merge_stats->bytes;
1748 : 0 : m_ent->pre_ct_parent->stats.pkts += merge_stats->pkts;
1749 : 0 : m_ent->post_ct_parent->stats.bytes += merge_stats->bytes;
1750 : 0 : m_ent->post_ct_parent->stats.pkts += merge_stats->pkts;
1751 : :
1752 : 0 : merge_stats->bytes = 0;
1753 : 0 : merge_stats->pkts = 0;
1754 : 0 : }
1755 : :
1756 : : struct nfp_fl_stats *
1757 : 0 : nfp_ct_flow_stats_get(struct nfp_flow_priv *priv,
1758 : : struct nfp_ct_map_entry *me)
1759 : : {
1760 : : struct nfp_ct_merge_entry *m_ent;
1761 : :
1762 : 0 : rte_spinlock_lock(&priv->stats_lock);
1763 : :
1764 [ # # ]: 0 : if (me->fe->type == CT_TYPE_PRE_CT) {
1765 [ # # ]: 0 : LIST_FOREACH(m_ent, &me->fe->children, pre_ct_list)
1766 : 0 : nfp_ct_flow_stats_update(priv, m_ent);
1767 : : } else {
1768 [ # # ]: 0 : LIST_FOREACH(m_ent, &me->fe->children, post_ct_list)
1769 : 0 : nfp_ct_flow_stats_update(priv, m_ent);
1770 : : }
1771 : :
1772 : : rte_spinlock_unlock(&priv->stats_lock);
1773 : :
1774 : 0 : return &me->fe->stats;
1775 : : }
|