Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 Corigine, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_flow.h"
7 : :
8 : : #include <rte_flow_driver.h>
9 : : #include <rte_hash.h>
10 : : #include <rte_jhash.h>
11 : : #include <rte_malloc.h>
12 : :
13 : : #include "flower/nfp_conntrack.h"
14 : : #include "flower/nfp_flower_representor.h"
15 : : #include "nfpcore/nfp_rtsym.h"
16 : : #include "nfp_logs.h"
17 : : #include "nfp_mtr.h"
18 : :
19 : : #define NFP_FLOWER_LAYER_EXT_META RTE_BIT32(0)
20 : : #define NFP_FLOWER_LAYER_PORT RTE_BIT32(1)
21 : : #define NFP_FLOWER_LAYER_MAC RTE_BIT32(2)
22 : : #define NFP_FLOWER_LAYER_TP RTE_BIT32(3)
23 : : #define NFP_FLOWER_LAYER_IPV4 RTE_BIT32(4)
24 : : #define NFP_FLOWER_LAYER_IPV6 RTE_BIT32(5)
25 : : #define NFP_FLOWER_LAYER_CT RTE_BIT32(6)
26 : : #define NFP_FLOWER_LAYER_VXLAN RTE_BIT32(7)
27 : :
28 : : #define NFP_FLOWER_LAYER2_GRE RTE_BIT32(0)
29 : : #define NFP_FLOWER_LAYER2_QINQ RTE_BIT32(4)
30 : : #define NFP_FLOWER_LAYER2_GENEVE RTE_BIT32(5)
31 : : #define NFP_FLOWER_LAYER2_GENEVE_OP RTE_BIT32(6)
32 : : #define NFP_FLOWER_LAYER2_TUN_IPV6 RTE_BIT32(7)
33 : :
34 : : /* Compressed HW representation of TCP Flags */
35 : : #define NFP_FL_TCP_FLAG_FIN RTE_BIT32(0)
36 : : #define NFP_FL_TCP_FLAG_SYN RTE_BIT32(1)
37 : : #define NFP_FL_TCP_FLAG_RST RTE_BIT32(2)
38 : : #define NFP_FL_TCP_FLAG_PSH RTE_BIT32(3)
39 : : #define NFP_FL_TCP_FLAG_URG RTE_BIT32(4)
40 : :
41 : : #define NFP_FL_META_FLAG_MANAGE_MASK RTE_BIT32(7)
42 : :
43 : : #define NFP_FLOWER_MASK_VLAN_CFI RTE_BIT32(12)
44 : :
45 : : #define NFP_MASK_TABLE_ENTRIES 1024
46 : :
47 : : /* The maximum action list size (in bytes) supported by the NFP. */
48 : : #define NFP_FL_MAX_A_SIZ 1216
49 : :
50 : : #define NFP_FL_SC_ACT_DROP 0x80000000
51 : : #define NFP_FL_SC_ACT_USER 0x7D000000
52 : : #define NFP_FL_SC_ACT_POPV 0x6A000000
53 : : #define NFP_FL_SC_ACT_NULL 0x00000000
54 : :
55 : : /* GRE Tunnel flags */
56 : : #define NFP_FL_GRE_FLAG_KEY (1 << 2)
57 : :
58 : : /* Action opcodes */
59 : : #define NFP_FL_ACTION_OPCODE_OUTPUT 0
60 : : #define NFP_FL_ACTION_OPCODE_PUSH_VLAN 1
61 : : #define NFP_FL_ACTION_OPCODE_POP_VLAN 2
62 : : #define NFP_FL_ACTION_OPCODE_PUSH_MPLS 3
63 : : #define NFP_FL_ACTION_OPCODE_POP_MPLS 4
64 : : #define NFP_FL_ACTION_OPCODE_USERSPACE 5
65 : : #define NFP_FL_ACTION_OPCODE_SET_TUNNEL 6
66 : : #define NFP_FL_ACTION_OPCODE_SET_ETHERNET 7
67 : : #define NFP_FL_ACTION_OPCODE_SET_MPLS 8
68 : : #define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS 9
69 : : #define NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS 10
70 : : #define NFP_FL_ACTION_OPCODE_SET_IPV6_SRC 11
71 : : #define NFP_FL_ACTION_OPCODE_SET_IPV6_DST 12
72 : : #define NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL 13
73 : : #define NFP_FL_ACTION_OPCODE_SET_UDP 14
74 : : #define NFP_FL_ACTION_OPCODE_SET_TCP 15
75 : : #define NFP_FL_ACTION_OPCODE_PRE_LAG 16
76 : : #define NFP_FL_ACTION_OPCODE_PRE_TUNNEL 17
77 : : #define NFP_FL_ACTION_OPCODE_PRE_GS 18
78 : : #define NFP_FL_ACTION_OPCODE_GS 19
79 : : #define NFP_FL_ACTION_OPCODE_PUSH_NSH 20
80 : : #define NFP_FL_ACTION_OPCODE_POP_NSH 21
81 : : #define NFP_FL_ACTION_OPCODE_SET_QUEUE 22
82 : : #define NFP_FL_ACTION_OPCODE_CONNTRACK 23
83 : : #define NFP_FL_ACTION_OPCODE_METER 24
84 : : #define NFP_FL_ACTION_OPCODE_CT_NAT_EXT 25
85 : : #define NFP_FL_ACTION_OPCODE_PUSH_GENEVE 26
86 : : #define NFP_FL_ACTION_OPCODE_NUM 32
87 : :
88 : : #define NFP_FL_OUT_FLAGS_LAST RTE_BIT32(15)
89 : :
90 : : /* Tunnel ports */
91 : : #define NFP_FL_PORT_TYPE_TUN 0x50000000
92 : :
93 : : /* Static initializer for a list of subsequent item types */
94 : : #define NEXT_ITEM(...) \
95 : : ((const enum rte_flow_item_type []){ \
96 : : __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
97 : : })
98 : :
99 : : /* Data length of various conf of raw encap action */
100 : : #define GENEVE_V4_LEN (sizeof(struct rte_ether_hdr) + \
101 : : sizeof(struct rte_ipv4_hdr) + \
102 : : sizeof(struct rte_udp_hdr) + \
103 : : sizeof(struct rte_flow_item_geneve))
104 : : #define GENEVE_V6_LEN (sizeof(struct rte_ether_hdr) + \
105 : : sizeof(struct rte_ipv6_hdr) + \
106 : : sizeof(struct rte_udp_hdr) + \
107 : : sizeof(struct rte_flow_item_geneve))
108 : : #define NVGRE_V4_LEN (sizeof(struct rte_ether_hdr) + \
109 : : sizeof(struct rte_ipv4_hdr) + \
110 : : sizeof(struct rte_flow_item_gre) + \
111 : : sizeof(rte_be32_t)) /* Gre key */
112 : : #define NVGRE_V6_LEN (sizeof(struct rte_ether_hdr) + \
113 : : sizeof(struct rte_ipv6_hdr) + \
114 : : sizeof(struct rte_flow_item_gre) + \
115 : : sizeof(rte_be32_t)) /* Gre key */
116 : :
117 : : /* Process structure associated with a flow item */
118 : : struct nfp_flow_item_proc {
119 : : /** Bit-mask for fields supported by this PMD. */
120 : : const void *mask_support;
121 : : /** Bit-mask to use when @p item->mask is not provided. */
122 : : const void *mask_default;
123 : : /** Size in bytes for @p mask_support and @p mask_default. */
124 : : const size_t mask_sz;
125 : : /** Merge a pattern item into a flow rule handle. */
126 : : int (*merge)(struct nfp_app_fw_flower *app_fw_flower,
127 : : struct rte_flow *nfp_flow,
128 : : char **mbuf_off,
129 : : const struct rte_flow_item *item,
130 : : const struct nfp_flow_item_proc *proc,
131 : : bool is_mask,
132 : : bool is_outer_layer);
133 : : /** List of possible subsequent items. */
134 : : const enum rte_flow_item_type *const next_item;
135 : : };
136 : :
137 : : struct nfp_mask_id_entry {
138 : : uint32_t hash_key;
139 : : uint32_t ref_cnt;
140 : : uint8_t mask_id;
141 : : };
142 : :
143 : : struct nfp_pre_tun_entry {
144 : : uint16_t mac_index;
145 : : uint16_t ref_cnt;
146 : : struct rte_ether_addr mac_addr;
147 : : } __rte_aligned(32);
148 : :
149 : : static inline struct nfp_flow_priv *
150 : : nfp_flow_dev_to_priv(struct rte_eth_dev *dev)
151 : : {
152 : : struct nfp_flower_representor *repr;
153 : :
154 : 0 : repr = dev->data->dev_private;
155 : 0 : return repr->app_fw_flower->flow_priv;
156 : : }
157 : :
158 : : static int
159 : 0 : nfp_mask_id_alloc(struct nfp_flow_priv *priv,
160 : : uint8_t *mask_id)
161 : : {
162 : : uint8_t temp_id;
163 : : uint8_t freed_id;
164 : : struct circ_buf *ring;
165 : :
166 : : /* Checking for unallocated entries first. */
167 [ # # ]: 0 : if (priv->mask_ids.init_unallocated > 0) {
168 : 0 : *mask_id = priv->mask_ids.init_unallocated;
169 : 0 : priv->mask_ids.init_unallocated--;
170 : 0 : return 0;
171 : : }
172 : :
173 : : /* Checking if buffer is empty. */
174 : 0 : freed_id = NFP_FLOWER_MASK_ENTRY_RS - 1;
175 : : ring = &priv->mask_ids.free_list;
176 [ # # ]: 0 : if (ring->head == ring->tail) {
177 : 0 : *mask_id = freed_id;
178 : 0 : return -ENOENT;
179 : : }
180 : :
181 [ # # ]: 0 : rte_memcpy(&temp_id, &ring->buf[ring->tail], NFP_FLOWER_MASK_ELEMENT_RS);
182 : 0 : *mask_id = temp_id;
183 : :
184 [ # # ]: 0 : rte_memcpy(&ring->buf[ring->tail], &freed_id, NFP_FLOWER_MASK_ELEMENT_RS);
185 : 0 : ring->tail = (ring->tail + NFP_FLOWER_MASK_ELEMENT_RS) %
186 : : (NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS);
187 : :
188 : 0 : return 0;
189 : : }
190 : :
191 : : static int
192 : : nfp_mask_id_free(struct nfp_flow_priv *priv,
193 : : uint8_t mask_id)
194 : : {
195 : : struct circ_buf *ring;
196 : :
197 : : ring = &priv->mask_ids.free_list;
198 : :
199 : : /* Checking if buffer is full. */
200 [ # # ]: 0 : if (CIRC_SPACE(ring->head, ring->tail, NFP_FLOWER_MASK_ENTRY_RS) == 0)
201 : : return -ENOBUFS;
202 : :
203 [ # # # # ]: 0 : rte_memcpy(&ring->buf[ring->head], &mask_id, NFP_FLOWER_MASK_ELEMENT_RS);
204 : 0 : ring->head = (ring->head + NFP_FLOWER_MASK_ELEMENT_RS) %
205 : : (NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS);
206 : :
207 : 0 : return 0;
208 : : }
209 : :
210 : : static int
211 : 0 : nfp_mask_table_add(struct nfp_flow_priv *priv,
212 : : char *mask_data,
213 : : uint32_t mask_len,
214 : : uint8_t *id)
215 : : {
216 : : int ret;
217 : : uint8_t mask_id;
218 : : uint32_t hash_key;
219 : : struct nfp_mask_id_entry *mask_entry;
220 : :
221 : 0 : mask_entry = rte_zmalloc("mask_entry", sizeof(struct nfp_mask_id_entry), 0);
222 [ # # ]: 0 : if (mask_entry == NULL) {
223 : : ret = -ENOMEM;
224 : 0 : goto exit;
225 : : }
226 : :
227 : 0 : ret = nfp_mask_id_alloc(priv, &mask_id);
228 [ # # ]: 0 : if (ret != 0)
229 : 0 : goto mask_entry_free;
230 : :
231 : 0 : hash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);
232 : 0 : mask_entry->mask_id = mask_id;
233 : 0 : mask_entry->hash_key = hash_key;
234 : 0 : mask_entry->ref_cnt = 1;
235 : 0 : PMD_DRV_LOG(DEBUG, "hash_key=%#x id=%u ref=%u", hash_key,
236 : : mask_id, mask_entry->ref_cnt);
237 : :
238 : 0 : ret = rte_hash_add_key_data(priv->mask_table, &hash_key, mask_entry);
239 [ # # ]: 0 : if (ret != 0) {
240 : 0 : PMD_DRV_LOG(ERR, "Add to mask table failed.");
241 [ # # ]: 0 : goto mask_id_free;
242 : : }
243 : :
244 : 0 : *id = mask_id;
245 : 0 : return 0;
246 : :
247 : : mask_id_free:
248 : 0 : nfp_mask_id_free(priv, mask_id);
249 : 0 : mask_entry_free:
250 : 0 : rte_free(mask_entry);
251 : : exit:
252 : : return ret;
253 : : }
254 : :
255 : : static int
256 : 0 : nfp_mask_table_del(struct nfp_flow_priv *priv,
257 : : char *mask_data,
258 : : uint32_t mask_len,
259 : : uint8_t id)
260 : : {
261 : : int ret;
262 : : uint32_t hash_key;
263 : :
264 : 0 : hash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);
265 : 0 : ret = rte_hash_del_key(priv->mask_table, &hash_key);
266 [ # # ]: 0 : if (ret < 0) {
267 : 0 : PMD_DRV_LOG(ERR, "Delete from mask table failed.");
268 : 0 : return ret;
269 : : }
270 : :
271 : 0 : ret = nfp_mask_id_free(priv, id);
272 : : if (ret != 0) {
273 : 0 : PMD_DRV_LOG(ERR, "Free mask id failed.");
274 : 0 : return ret;
275 : : }
276 : :
277 : : return 0;
278 : : }
279 : :
280 : : static struct nfp_mask_id_entry *
281 : 0 : nfp_mask_table_search(struct nfp_flow_priv *priv,
282 : : char *mask_data,
283 : : uint32_t mask_len)
284 : : {
285 : : int index;
286 : : uint32_t hash_key;
287 : : struct nfp_mask_id_entry *entry;
288 : :
289 : 0 : hash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);
290 : 0 : index = rte_hash_lookup_data(priv->mask_table, &hash_key, (void **)&entry);
291 [ # # ]: 0 : if (index < 0) {
292 : 0 : PMD_DRV_LOG(DEBUG, "Data NOT found in the mask table.");
293 : 0 : return NULL;
294 : : }
295 : :
296 : 0 : return entry;
297 : : }
298 : :
299 : : static bool
300 : 0 : nfp_check_mask_add(struct nfp_flow_priv *priv,
301 : : char *mask_data,
302 : : uint32_t mask_len,
303 : : uint8_t *meta_flags,
304 : : uint8_t *mask_id)
305 : : {
306 : : int ret;
307 : : struct nfp_mask_id_entry *mask_entry;
308 : :
309 : 0 : mask_entry = nfp_mask_table_search(priv, mask_data, mask_len);
310 [ # # ]: 0 : if (mask_entry == NULL) {
311 : : /* Mask entry does not exist, let's create one */
312 : 0 : ret = nfp_mask_table_add(priv, mask_data, mask_len, mask_id);
313 [ # # ]: 0 : if (ret != 0)
314 : : return false;
315 : : } else {
316 : : /* Mask entry already exist */
317 : 0 : mask_entry->ref_cnt++;
318 : 0 : *mask_id = mask_entry->mask_id;
319 : : }
320 : :
321 : 0 : *meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK;
322 : :
323 : 0 : return true;
324 : : }
325 : :
326 : : static bool
327 : 0 : nfp_check_mask_remove(struct nfp_flow_priv *priv,
328 : : char *mask_data,
329 : : uint32_t mask_len,
330 : : uint8_t *meta_flags)
331 : : {
332 : : int ret;
333 : : struct nfp_mask_id_entry *mask_entry;
334 : :
335 : 0 : mask_entry = nfp_mask_table_search(priv, mask_data, mask_len);
336 [ # # ]: 0 : if (mask_entry == NULL)
337 : : return false;
338 : :
339 : 0 : mask_entry->ref_cnt--;
340 [ # # ]: 0 : if (mask_entry->ref_cnt == 0) {
341 : 0 : ret = nfp_mask_table_del(priv, mask_data, mask_len,
342 : 0 : mask_entry->mask_id);
343 [ # # ]: 0 : if (ret != 0)
344 : : return false;
345 : :
346 : 0 : rte_free(mask_entry);
347 [ # # ]: 0 : if (meta_flags)
348 : 0 : *meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK;
349 : : }
350 : :
351 : : return true;
352 : : }
353 : :
354 : : static int
355 : 0 : nfp_flow_table_add(struct nfp_flow_priv *priv,
356 : : struct rte_flow *nfp_flow)
357 : : {
358 : : int ret;
359 : :
360 : 0 : ret = rte_hash_add_key_data(priv->flow_table, &nfp_flow->hash_key, nfp_flow);
361 [ # # ]: 0 : if (ret != 0) {
362 : 0 : PMD_DRV_LOG(ERR, "Add to flow table failed.");
363 : 0 : return ret;
364 : : }
365 : :
366 : : return 0;
367 : : }
368 : :
369 : : static int
370 : 0 : nfp_flow_table_delete(struct nfp_flow_priv *priv,
371 : : struct rte_flow *nfp_flow)
372 : : {
373 : : int ret;
374 : :
375 : 0 : ret = rte_hash_del_key(priv->flow_table, &nfp_flow->hash_key);
376 [ # # ]: 0 : if (ret < 0) {
377 : 0 : PMD_DRV_LOG(ERR, "Delete from flow table failed.");
378 : 0 : return ret;
379 : : }
380 : :
381 : : return 0;
382 : : }
383 : :
384 : : static struct rte_flow *
385 : 0 : nfp_flow_table_search(struct nfp_flow_priv *priv,
386 : : struct rte_flow *nfp_flow)
387 : : {
388 : : int index;
389 : : struct rte_flow *flow_find;
390 : :
391 : 0 : index = rte_hash_lookup_data(priv->flow_table, &nfp_flow->hash_key,
392 : : (void **)&flow_find);
393 [ # # ]: 0 : if (index < 0) {
394 : 0 : PMD_DRV_LOG(DEBUG, "Data NOT found in the flow table.");
395 : 0 : return NULL;
396 : : }
397 : :
398 : 0 : return flow_find;
399 : : }
400 : :
401 : : int
402 : 0 : nfp_flow_table_add_merge(struct nfp_flow_priv *priv,
403 : : struct rte_flow *nfp_flow)
404 : : {
405 : : struct rte_flow *flow_find;
406 : :
407 : 0 : flow_find = nfp_flow_table_search(priv, nfp_flow);
408 [ # # ]: 0 : if (flow_find != NULL) {
409 [ # # # # ]: 0 : if (nfp_flow->merge_flag || flow_find->merge_flag) {
410 : 0 : flow_find->merge_flag = true;
411 : 0 : flow_find->ref_cnt++;
412 : 0 : return 0;
413 : : }
414 : :
415 : 0 : PMD_DRV_LOG(ERR, "Add to flow table failed.");
416 : 0 : return -EINVAL;
417 : : }
418 : :
419 : 0 : return nfp_flow_table_add(priv, nfp_flow);
420 : : }
421 : :
422 : : static int
423 : 0 : nfp_flow_table_delete_merge(struct nfp_flow_priv *priv,
424 : : struct rte_flow *nfp_flow)
425 : : {
426 : : struct rte_flow *flow_find;
427 : :
428 : 0 : flow_find = nfp_flow_table_search(priv, nfp_flow);
429 [ # # ]: 0 : if (flow_find == NULL) {
430 : 0 : PMD_DRV_LOG(ERR, "Can't delete a non-existing flow.");
431 : 0 : return -EINVAL;
432 : : }
433 : :
434 [ # # # # ]: 0 : if (nfp_flow->merge_flag || flow_find->merge_flag) {
435 : 0 : flow_find->ref_cnt--;
436 [ # # ]: 0 : if (flow_find->ref_cnt > 0)
437 : : return 0;
438 : : }
439 : :
440 : 0 : return nfp_flow_table_delete(priv, nfp_flow);
441 : : }
442 : :
443 : : static struct rte_flow *
444 : 0 : nfp_flow_alloc(struct nfp_fl_key_ls *key_layer, uint32_t port_id)
445 : : {
446 : : char *tmp;
447 : : size_t len;
448 : : struct rte_flow *nfp_flow;
449 : : struct nfp_fl_payload *payload;
450 : :
451 : 0 : nfp_flow = rte_zmalloc("nfp_flow", sizeof(struct rte_flow), 0);
452 [ # # ]: 0 : if (nfp_flow == NULL)
453 : 0 : goto exit;
454 : :
455 : 0 : len = key_layer->key_size + key_layer->key_size + key_layer->act_size;
456 : 0 : tmp = rte_zmalloc("nfp_flow_payload", len + sizeof(struct nfp_fl_rule_metadata), 0);
457 [ # # ]: 0 : if (tmp == NULL)
458 : 0 : goto free_flow;
459 : :
460 : 0 : nfp_flow->length = len;
461 : 0 : nfp_flow->mtr_id = NFP_MAX_MTR_CNT;
462 : 0 : nfp_flow->port_id = port_id;
463 : : payload = &nfp_flow->payload;
464 : 0 : payload->meta = (struct nfp_fl_rule_metadata *)tmp;
465 : 0 : payload->unmasked_data = tmp + sizeof(struct nfp_fl_rule_metadata);
466 : 0 : payload->mask_data = payload->unmasked_data + key_layer->key_size;
467 : 0 : payload->action_data = payload->mask_data + key_layer->key_size;
468 : :
469 : 0 : return nfp_flow;
470 : :
471 : : free_flow:
472 : 0 : rte_free(nfp_flow);
473 : : exit:
474 : : return NULL;
475 : : }
476 : :
477 : : void
478 : 0 : nfp_flow_free(struct rte_flow *nfp_flow)
479 : : {
480 : 0 : rte_free(nfp_flow->payload.meta);
481 : 0 : rte_free(nfp_flow);
482 : 0 : }
483 : :
484 : : static int
485 : 0 : nfp_stats_id_alloc(struct nfp_flow_priv *priv, uint32_t *ctx)
486 : : {
487 : : struct circ_buf *ring;
488 : : uint32_t temp_stats_id;
489 : : uint32_t freed_stats_id;
490 : :
491 : : /* Check for unallocated entries first. */
492 [ # # ]: 0 : if (priv->stats_ids.init_unallocated > 0) {
493 : 0 : *ctx = ((priv->stats_ids.init_unallocated - 1) & NFP_FL_STAT_ID_STAT) |
494 : 0 : (priv->active_mem_unit & NFP_FL_STAT_ID_MU_NUM);
495 [ # # ]: 0 : if (++priv->active_mem_unit == priv->total_mem_units) {
496 : 0 : priv->stats_ids.init_unallocated--;
497 : 0 : priv->active_mem_unit = 0;
498 : : }
499 : :
500 : 0 : return 0;
501 : : }
502 : :
503 : : /* Check if buffer is empty */
504 : : ring = &priv->stats_ids.free_list;
505 : 0 : freed_stats_id = priv->stats_ring_size;
506 [ # # ]: 0 : if (ring->head == ring->tail) {
507 : 0 : *ctx = freed_stats_id;
508 : 0 : return -ENOENT;
509 : : }
510 : :
511 : 0 : memcpy(&temp_stats_id, &ring->buf[ring->tail], NFP_FL_STATS_ELEM_RS);
512 : 0 : *ctx = temp_stats_id;
513 : 0 : memcpy(&ring->buf[ring->tail], &freed_stats_id, NFP_FL_STATS_ELEM_RS);
514 : 0 : ring->tail = (ring->tail + NFP_FL_STATS_ELEM_RS) %
515 : 0 : (priv->stats_ring_size * NFP_FL_STATS_ELEM_RS);
516 : :
517 : 0 : return 0;
518 : : }
519 : :
520 : : static int
521 : 0 : nfp_stats_id_free(struct nfp_flow_priv *priv, uint32_t ctx)
522 : : {
523 : : struct circ_buf *ring;
524 : :
525 : : /* Check if buffer is full */
526 : : ring = &priv->stats_ids.free_list;
527 [ # # ]: 0 : if (CIRC_SPACE(ring->head, ring->tail, priv->stats_ring_size *
528 : : NFP_FL_STATS_ELEM_RS - NFP_FL_STATS_ELEM_RS + 1) == 0)
529 : : return -ENOBUFS;
530 : :
531 : 0 : memcpy(&ring->buf[ring->head], &ctx, NFP_FL_STATS_ELEM_RS);
532 : 0 : ring->head = (ring->head + NFP_FL_STATS_ELEM_RS) %
533 : 0 : (priv->stats_ring_size * NFP_FL_STATS_ELEM_RS);
534 : :
535 : 0 : return 0;
536 : : }
537 : :
538 : : static int
539 : 0 : nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
540 : : rte_be32_t ipv4)
541 : : {
542 : : struct nfp_flow_priv *priv;
543 : : struct nfp_ipv4_addr_entry *entry;
544 : : struct nfp_ipv4_addr_entry *tmp_entry;
545 : :
546 : 0 : priv = app_fw_flower->flow_priv;
547 : :
548 : 0 : rte_spinlock_lock(&priv->ipv4_off_lock);
549 [ # # ]: 0 : LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
550 [ # # ]: 0 : if (entry->ipv4_addr == ipv4) {
551 : 0 : entry->ref_count++;
552 : : rte_spinlock_unlock(&priv->ipv4_off_lock);
553 : 0 : return 0;
554 : : }
555 : : }
556 : : rte_spinlock_unlock(&priv->ipv4_off_lock);
557 : :
558 : 0 : tmp_entry = rte_zmalloc("nfp_ipv4_off", sizeof(struct nfp_ipv4_addr_entry), 0);
559 [ # # ]: 0 : if (tmp_entry == NULL) {
560 : 0 : PMD_DRV_LOG(ERR, "Mem error when offloading IP address.");
561 : 0 : return -ENOMEM;
562 : : }
563 : :
564 : 0 : tmp_entry->ipv4_addr = ipv4;
565 : 0 : tmp_entry->ref_count = 1;
566 : :
567 : : rte_spinlock_lock(&priv->ipv4_off_lock);
568 [ # # ]: 0 : LIST_INSERT_HEAD(&priv->ipv4_off_list, tmp_entry, next);
569 : : rte_spinlock_unlock(&priv->ipv4_off_lock);
570 : :
571 : 0 : return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
572 : : }
573 : :
574 : : static int
575 : 0 : nfp_tun_del_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
576 : : rte_be32_t ipv4)
577 : : {
578 : : struct nfp_flow_priv *priv;
579 : : struct nfp_ipv4_addr_entry *entry;
580 : :
581 : 0 : priv = app_fw_flower->flow_priv;
582 : :
583 : 0 : rte_spinlock_lock(&priv->ipv4_off_lock);
584 [ # # ]: 0 : LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
585 [ # # ]: 0 : if (entry->ipv4_addr == ipv4) {
586 : 0 : entry->ref_count--;
587 [ # # ]: 0 : if (entry->ref_count == 0) {
588 [ # # ]: 0 : LIST_REMOVE(entry, next);
589 : 0 : rte_free(entry);
590 : : rte_spinlock_unlock(&priv->ipv4_off_lock);
591 : 0 : return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
592 : : }
593 : : break;
594 : : }
595 : : }
596 : : rte_spinlock_unlock(&priv->ipv4_off_lock);
597 : :
598 : 0 : return 0;
599 : : }
600 : :
601 : : static int
602 : 0 : nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
603 : : uint8_t ipv6[])
604 : : {
605 : : struct nfp_flow_priv *priv;
606 : : struct nfp_ipv6_addr_entry *entry;
607 : : struct nfp_ipv6_addr_entry *tmp_entry;
608 : :
609 : 0 : priv = app_fw_flower->flow_priv;
610 : :
611 : 0 : rte_spinlock_lock(&priv->ipv6_off_lock);
612 [ # # ]: 0 : LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
613 [ # # ]: 0 : if (memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr)) == 0) {
614 : 0 : entry->ref_count++;
615 : : rte_spinlock_unlock(&priv->ipv6_off_lock);
616 : 0 : return 0;
617 : : }
618 : : }
619 : : rte_spinlock_unlock(&priv->ipv6_off_lock);
620 : :
621 : 0 : tmp_entry = rte_zmalloc("nfp_ipv6_off", sizeof(struct nfp_ipv6_addr_entry), 0);
622 [ # # ]: 0 : if (tmp_entry == NULL) {
623 : 0 : PMD_DRV_LOG(ERR, "Mem error when offloading IP6 address.");
624 : 0 : return -ENOMEM;
625 : : }
626 : :
627 : 0 : memcpy(tmp_entry->ipv6_addr, ipv6, sizeof(tmp_entry->ipv6_addr));
628 : 0 : tmp_entry->ref_count = 1;
629 : :
630 : : rte_spinlock_lock(&priv->ipv6_off_lock);
631 [ # # ]: 0 : LIST_INSERT_HEAD(&priv->ipv6_off_list, tmp_entry, next);
632 : : rte_spinlock_unlock(&priv->ipv6_off_lock);
633 : :
634 : 0 : return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
635 : : }
636 : :
637 : : static int
638 : 0 : nfp_tun_del_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
639 : : uint8_t ipv6[])
640 : : {
641 : : struct nfp_flow_priv *priv;
642 : : struct nfp_ipv6_addr_entry *entry;
643 : :
644 : 0 : priv = app_fw_flower->flow_priv;
645 : :
646 : 0 : rte_spinlock_lock(&priv->ipv6_off_lock);
647 [ # # ]: 0 : LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
648 [ # # ]: 0 : if (memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr)) == 0) {
649 : 0 : entry->ref_count--;
650 [ # # ]: 0 : if (entry->ref_count == 0) {
651 [ # # ]: 0 : LIST_REMOVE(entry, next);
652 : 0 : rte_free(entry);
653 : : rte_spinlock_unlock(&priv->ipv6_off_lock);
654 : 0 : return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
655 : : }
656 : : break;
657 : : }
658 : : }
659 : : rte_spinlock_unlock(&priv->ipv6_off_lock);
660 : :
661 : 0 : return 0;
662 : : }
663 : :
664 : : static int
665 : 0 : nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
666 : : struct rte_flow *nfp_flow)
667 : : {
668 : : int ret;
669 : : uint32_t key_layer2 = 0;
670 : : struct nfp_flower_ipv4_udp_tun *udp4;
671 : : struct nfp_flower_ipv6_udp_tun *udp6;
672 : : struct nfp_flower_ipv4_gre_tun *gre4;
673 : : struct nfp_flower_ipv6_gre_tun *gre6;
674 : : struct nfp_flower_meta_tci *meta_tci;
675 : : struct nfp_flower_ext_meta *ext_meta = NULL;
676 : :
677 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
678 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) != 0)
679 : 0 : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
680 : :
681 : : if (ext_meta != NULL)
682 [ # # ]: 0 : key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
683 : :
684 [ # # ]: 0 : if ((key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) != 0) {
685 [ # # ]: 0 : if ((key_layer2 & NFP_FLOWER_LAYER2_GRE) != 0) {
686 : 0 : gre6 = (struct nfp_flower_ipv6_gre_tun *)(nfp_flow->payload.mask_data -
687 : : sizeof(struct nfp_flower_ipv6_gre_tun));
688 : 0 : ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, gre6->ipv6.ipv6_dst);
689 : : } else {
690 : 0 : udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
691 : : sizeof(struct nfp_flower_ipv6_udp_tun));
692 : 0 : ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
693 : : }
694 : : } else {
695 [ # # ]: 0 : if ((key_layer2 & NFP_FLOWER_LAYER2_GRE) != 0) {
696 : 0 : gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
697 : : sizeof(struct nfp_flower_ipv4_gre_tun));
698 : 0 : ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, gre4->ipv4.dst);
699 : : } else {
700 : 0 : udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
701 : : sizeof(struct nfp_flower_ipv4_udp_tun));
702 : 0 : ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
703 : : }
704 : : }
705 : :
706 : 0 : return ret;
707 : : }
708 : :
709 : : static void
710 : : nfp_flower_compile_meta_tci(char *mbuf_off,
711 : : struct nfp_fl_key_ls *key_layer)
712 : : {
713 : : struct nfp_flower_meta_tci *tci_meta;
714 : :
715 : : tci_meta = (struct nfp_flower_meta_tci *)mbuf_off;
716 : 0 : tci_meta->nfp_flow_key_layer = key_layer->key_layer;
717 : 0 : tci_meta->mask_id = ~0;
718 [ # # ]: 0 : tci_meta->tci = rte_cpu_to_be_16(key_layer->vlan);
719 : : }
720 : :
721 : : static void
722 : : nfp_flower_update_meta_tci(char *exact,
723 : : uint8_t mask_id)
724 : : {
725 : : struct nfp_flower_meta_tci *meta_tci;
726 : :
727 : : meta_tci = (struct nfp_flower_meta_tci *)exact;
728 : 0 : meta_tci->mask_id = mask_id;
729 : : }
730 : :
731 : : static void
732 : : nfp_flower_compile_ext_meta(char *mbuf_off,
733 : : struct nfp_fl_key_ls *key_layer)
734 : : {
735 : : struct nfp_flower_ext_meta *ext_meta;
736 : :
737 : : ext_meta = (struct nfp_flower_ext_meta *)mbuf_off;
738 [ # # # # ]: 0 : ext_meta->nfp_flow_key_layer2 = rte_cpu_to_be_32(key_layer->key_layer_two);
739 : : }
740 : :
741 : : static void
742 : 0 : nfp_compile_meta_port(char *mbuf_off,
743 : : struct nfp_fl_key_ls *key_layer,
744 : : bool is_mask)
745 : : {
746 : : struct nfp_flower_in_port *port_meta;
747 : :
748 : : port_meta = (struct nfp_flower_in_port *)mbuf_off;
749 : :
750 [ # # ]: 0 : if (is_mask)
751 : 0 : port_meta->in_port = rte_cpu_to_be_32(~0);
752 [ # # ]: 0 : else if (key_layer->tun_type)
753 [ # # ]: 0 : port_meta->in_port = rte_cpu_to_be_32(NFP_FL_PORT_TYPE_TUN |
754 : : key_layer->tun_type);
755 : : else
756 [ # # ]: 0 : port_meta->in_port = rte_cpu_to_be_32(key_layer->port);
757 : 0 : }
758 : :
759 : : static void
760 : 0 : nfp_flow_compile_metadata(struct nfp_flow_priv *priv,
761 : : struct rte_flow *nfp_flow,
762 : : struct nfp_fl_key_ls *key_layer,
763 : : uint32_t stats_ctx,
764 : : uint64_t cookie)
765 : : {
766 : : char *mbuf_off_mask;
767 : : char *mbuf_off_exact;
768 : : struct nfp_fl_rule_metadata *nfp_flow_meta;
769 : :
770 : : /*
771 : : * Convert to long words as firmware expects
772 : : * lengths in units of NFP_FL_LW_SIZ.
773 : : */
774 : 0 : nfp_flow_meta = nfp_flow->payload.meta;
775 : 0 : nfp_flow_meta->key_len = key_layer->key_size >> NFP_FL_LW_SIZ;
776 : 0 : nfp_flow_meta->mask_len = key_layer->key_size >> NFP_FL_LW_SIZ;
777 : 0 : nfp_flow_meta->act_len = key_layer->act_size >> NFP_FL_LW_SIZ;
778 : 0 : nfp_flow_meta->flags = 0;
779 [ # # ]: 0 : nfp_flow_meta->host_ctx_id = rte_cpu_to_be_32(stats_ctx);
780 [ # # ]: 0 : nfp_flow_meta->host_cookie = rte_cpu_to_be_64(cookie);
781 [ # # ]: 0 : nfp_flow_meta->flow_version = rte_cpu_to_be_64(priv->flower_version);
782 : :
783 : 0 : mbuf_off_exact = nfp_flow->payload.unmasked_data;
784 [ # # ]: 0 : mbuf_off_mask = nfp_flow->payload.mask_data;
785 : :
786 : : /* Populate Metadata */
787 : : nfp_flower_compile_meta_tci(mbuf_off_exact, key_layer);
788 : : nfp_flower_compile_meta_tci(mbuf_off_mask, key_layer);
789 : 0 : mbuf_off_exact += sizeof(struct nfp_flower_meta_tci);
790 : 0 : mbuf_off_mask += sizeof(struct nfp_flower_meta_tci);
791 : :
792 : : /* Populate Extended Metadata if required */
793 [ # # ]: 0 : if ((key_layer->key_layer & NFP_FLOWER_LAYER_EXT_META) != 0) {
794 : : nfp_flower_compile_ext_meta(mbuf_off_exact, key_layer);
795 : : nfp_flower_compile_ext_meta(mbuf_off_mask, key_layer);
796 : 0 : mbuf_off_exact += sizeof(struct nfp_flower_ext_meta);
797 : 0 : mbuf_off_mask += sizeof(struct nfp_flower_ext_meta);
798 : : }
799 : :
800 : : /* Populate Port Data */
801 : 0 : nfp_compile_meta_port(mbuf_off_exact, key_layer, false);
802 : 0 : nfp_compile_meta_port(mbuf_off_mask, key_layer, true);
803 : : mbuf_off_exact += sizeof(struct nfp_flower_in_port);
804 : : mbuf_off_mask += sizeof(struct nfp_flower_in_port);
805 : 0 : }
806 : :
807 : : static int
808 : 0 : nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
809 : : struct nfp_fl_key_ls *key_ls)
810 : : {
811 : : struct rte_eth_dev *ethdev;
812 : : bool outer_ip4_flag = false;
813 : : bool outer_ip6_flag = false;
814 : : const struct rte_flow_item *item;
815 : : struct nfp_flower_representor *representor;
816 : : const struct rte_flow_item_port_id *port_id;
817 : :
818 [ # # ]: 0 : for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
819 [ # # # # : 0 : switch (item->type) {
# # # # #
# # # # ]
820 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
821 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_ETH detected");
822 : : /*
823 : : * Eth is set with no specific params.
824 : : * NFP does not need this.
825 : : */
826 [ # # ]: 0 : if (item->spec == NULL)
827 : 0 : continue;
828 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_MAC;
829 : 0 : key_ls->key_size += sizeof(struct nfp_flower_mac_mpls);
830 : 0 : break;
831 : 0 : case RTE_FLOW_ITEM_TYPE_PORT_ID:
832 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_PORT_ID detected");
833 : 0 : port_id = item->spec;
834 [ # # ]: 0 : if (port_id->id >= RTE_MAX_ETHPORTS)
835 : : return -ERANGE;
836 : : ethdev = &rte_eth_devices[port_id->id];
837 : 0 : representor = ethdev->data->dev_private;
838 : 0 : key_ls->port = representor->port_id;
839 : 0 : break;
840 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
841 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VLAN detected");
842 : 0 : key_ls->vlan = NFP_FLOWER_MASK_VLAN_CFI;
843 : 0 : break;
844 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
845 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV4 detected");
846 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_IPV4;
847 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv4);
848 : : if (!outer_ip4_flag)
849 : : outer_ip4_flag = true;
850 : : break;
851 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
852 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
853 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_IPV6;
854 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv6);
855 : : if (!outer_ip6_flag)
856 : : outer_ip6_flag = true;
857 : : break;
858 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
859 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_TCP detected");
860 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_TP;
861 : 0 : key_ls->key_size += sizeof(struct nfp_flower_tp_ports);
862 : 0 : break;
863 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
864 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_UDP detected");
865 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_TP;
866 : 0 : key_ls->key_size += sizeof(struct nfp_flower_tp_ports);
867 : 0 : break;
868 : 0 : case RTE_FLOW_ITEM_TYPE_SCTP:
869 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_SCTP detected");
870 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_TP;
871 : 0 : key_ls->key_size += sizeof(struct nfp_flower_tp_ports);
872 : 0 : break;
873 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
874 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
875 : : /* Clear IPv4 and IPv6 bits */
876 : 0 : key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
877 : 0 : key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
878 : 0 : key_ls->tun_type = NFP_FL_TUN_VXLAN;
879 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
880 [ # # ]: 0 : if (outer_ip4_flag) {
881 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
882 : : /*
883 : : * The outer l3 layer information is
884 : : * in `struct nfp_flower_ipv4_udp_tun`.
885 : : */
886 : 0 : key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
887 [ # # ]: 0 : } else if (outer_ip6_flag) {
888 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
889 : 0 : key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
890 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
891 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
892 : : /*
893 : : * The outer l3 layer information is
894 : : * in `struct nfp_flower_ipv6_udp_tun`.
895 : : */
896 : 0 : key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
897 : : } else {
898 : 0 : PMD_DRV_LOG(ERR, "No outer IP layer for VXLAN tunnel.");
899 : 0 : return -EINVAL;
900 : : }
901 : : break;
902 : 0 : case RTE_FLOW_ITEM_TYPE_GENEVE:
903 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
904 : : /* Clear IPv4 and IPv6 bits */
905 : 0 : key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
906 : 0 : key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
907 : 0 : key_ls->tun_type = NFP_FL_TUN_GENEVE;
908 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
909 : 0 : key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
910 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
911 [ # # ]: 0 : if (outer_ip4_flag) {
912 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
913 : : /*
914 : : * The outer l3 layer information is
915 : : * in `struct nfp_flower_ipv4_udp_tun`.
916 : : */
917 : 0 : key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
918 [ # # ]: 0 : } else if (outer_ip6_flag) {
919 : 0 : key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
920 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
921 : : /*
922 : : * The outer l3 layer information is
923 : : * in `struct nfp_flower_ipv6_udp_tun`.
924 : : */
925 : 0 : key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
926 : : } else {
927 : 0 : PMD_DRV_LOG(ERR, "No outer IP layer for GENEVE tunnel.");
928 : 0 : return -EINVAL;
929 : : }
930 : : break;
931 : 0 : case RTE_FLOW_ITEM_TYPE_GRE:
932 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
933 : : /* Clear IPv4 and IPv6 bits */
934 : 0 : key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
935 : 0 : key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
936 : 0 : key_ls->tun_type = NFP_FL_TUN_GRE;
937 : 0 : key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
938 : 0 : key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
939 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
940 [ # # ]: 0 : if (outer_ip4_flag) {
941 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv4_gre_tun);
942 : : /*
943 : : * The outer l3 layer information is
944 : : * in `struct nfp_flower_ipv4_gre_tun`.
945 : : */
946 : 0 : key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
947 [ # # ]: 0 : } else if (outer_ip6_flag) {
948 : 0 : key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
949 : 0 : key_ls->key_size += sizeof(struct nfp_flower_ipv6_gre_tun);
950 : : /*
951 : : * The outer l3 layer information is
952 : : * in `struct nfp_flower_ipv6_gre_tun`.
953 : : */
954 : 0 : key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
955 : : } else {
956 : 0 : PMD_DRV_LOG(ERR, "No outer IP layer for GRE tunnel.");
957 : 0 : return -1;
958 : : }
959 : : break;
960 : 0 : case RTE_FLOW_ITEM_TYPE_GRE_KEY:
961 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE_KEY detected");
962 : 0 : break;
963 : 0 : default:
964 : 0 : PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
965 : 0 : return -ENOTSUP;
966 : : }
967 : : }
968 : :
969 : : return 0;
970 : : }
971 : :
972 : : static int
973 : 0 : nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[],
974 : : struct nfp_fl_key_ls *key_ls)
975 : : {
976 : : int ret = 0;
977 : : bool meter_flag = false;
978 : : bool tc_hl_flag = false;
979 : : bool ip_set_flag = false;
980 : : bool tp_set_flag = false;
981 : : bool mac_set_flag = false;
982 : : bool ttl_tos_flag = false;
983 : : const struct rte_flow_action *action;
984 : :
985 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
986 : : /* Make sure actions length no longer than NFP_FL_MAX_A_SIZ */
987 [ # # ]: 0 : if (key_ls->act_size > NFP_FL_MAX_A_SIZ) {
988 : 0 : PMD_DRV_LOG(ERR, "The action list is too long.");
989 : : ret = -ERANGE;
990 : 0 : break;
991 : : }
992 : :
993 [ # # # # : 0 : switch (action->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
994 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
995 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VOID detected");
996 : 0 : break;
997 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
998 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_DROP detected");
999 : 0 : break;
1000 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
1001 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_COUNT detected");
1002 : 0 : break;
1003 : 0 : case RTE_FLOW_ACTION_TYPE_JUMP:
1004 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_JUMP detected");
1005 : 0 : break;
1006 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
1007 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_PORT_ID detected");
1008 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_output);
1009 : 0 : break;
1010 : 0 : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
1011 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT detected");
1012 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_output);
1013 : 0 : break;
1014 : 0 : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
1015 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_MAC_SRC detected");
1016 [ # # ]: 0 : if (!mac_set_flag) {
1017 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_eth);
1018 : : mac_set_flag = true;
1019 : : }
1020 : : break;
1021 : 0 : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
1022 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_MAC_DST detected");
1023 [ # # ]: 0 : if (!mac_set_flag) {
1024 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_eth);
1025 : : mac_set_flag = true;
1026 : : }
1027 : : break;
1028 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
1029 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_OF_POP_VLAN detected");
1030 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_pop_vlan);
1031 : 0 : break;
1032 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
1033 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN detected");
1034 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_push_vlan);
1035 : 0 : break;
1036 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
1037 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID detected");
1038 : 0 : break;
1039 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
1040 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP detected");
1041 : 0 : break;
1042 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
1043 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC detected");
1044 [ # # ]: 0 : if (!ip_set_flag) {
1045 : 0 : key_ls->act_size +=
1046 : : sizeof(struct nfp_fl_act_set_ip4_addrs);
1047 : : ip_set_flag = true;
1048 : : }
1049 : : break;
1050 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
1051 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_IPV4_DST detected");
1052 [ # # ]: 0 : if (!ip_set_flag) {
1053 : 0 : key_ls->act_size +=
1054 : : sizeof(struct nfp_fl_act_set_ip4_addrs);
1055 : : ip_set_flag = true;
1056 : : }
1057 : : break;
1058 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
1059 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC detected");
1060 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_ipv6_addr);
1061 : 0 : break;
1062 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
1063 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_IPV6_DST detected");
1064 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_ipv6_addr);
1065 : 0 : break;
1066 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
1067 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_TP_SRC detected");
1068 [ # # ]: 0 : if (!tp_set_flag) {
1069 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_tport);
1070 : : tp_set_flag = true;
1071 : : }
1072 : : break;
1073 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
1074 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_TP_DST detected");
1075 [ # # ]: 0 : if (!tp_set_flag) {
1076 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_tport);
1077 : : tp_set_flag = true;
1078 : : }
1079 : : break;
1080 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TTL:
1081 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_TTL detected");
1082 [ # # ]: 0 : if ((key_ls->key_layer & NFP_FLOWER_LAYER_IPV4) != 0) {
1083 [ # # ]: 0 : if (!ttl_tos_flag) {
1084 : 0 : key_ls->act_size +=
1085 : : sizeof(struct nfp_fl_act_set_ip4_ttl_tos);
1086 : : ttl_tos_flag = true;
1087 : : }
1088 : : } else {
1089 [ # # ]: 0 : if (!tc_hl_flag) {
1090 : 0 : key_ls->act_size +=
1091 : : sizeof(struct nfp_fl_act_set_ipv6_tc_hl_fl);
1092 : : tc_hl_flag = true;
1093 : : }
1094 : : }
1095 : : break;
1096 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
1097 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP detected");
1098 [ # # ]: 0 : if (!ttl_tos_flag) {
1099 : 0 : key_ls->act_size +=
1100 : : sizeof(struct nfp_fl_act_set_ip4_ttl_tos);
1101 : : ttl_tos_flag = true;
1102 : : }
1103 : : break;
1104 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
1105 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP detected");
1106 [ # # ]: 0 : if (!tc_hl_flag) {
1107 : 0 : key_ls->act_size +=
1108 : : sizeof(struct nfp_fl_act_set_ipv6_tc_hl_fl);
1109 : : tc_hl_flag = true;
1110 : : }
1111 : : break;
1112 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
1113 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP detected");
1114 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
1115 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
1116 : 0 : break;
1117 : 0 : case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
1118 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_ENCAP detected");
1119 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
1120 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
1121 : 0 : break;
1122 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
1123 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
1124 : 0 : break;
1125 : 0 : case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
1126 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_DECAP detected");
1127 : 0 : break;
1128 : 0 : case RTE_FLOW_ACTION_TYPE_METER:
1129 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_METER detected");
1130 [ # # ]: 0 : if (!meter_flag) {
1131 : 0 : key_ls->act_size += sizeof(struct nfp_fl_act_meter);
1132 : : meter_flag = true;
1133 : : } else {
1134 : 0 : PMD_DRV_LOG(ERR, "Only support one meter action.");
1135 : 0 : return -ENOTSUP;
1136 : : }
1137 : 0 : break;
1138 : 0 : case RTE_FLOW_ACTION_TYPE_CONNTRACK:
1139 : 0 : PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_CONNTRACK detected");
1140 : 0 : break;
1141 : 0 : default:
1142 : 0 : PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
1143 : 0 : return -ENOTSUP;
1144 : : }
1145 : : }
1146 : :
1147 : : return ret;
1148 : : }
1149 : :
1150 : : static int
1151 : 0 : nfp_flow_key_layers_calculate(const struct rte_flow_item items[],
1152 : : const struct rte_flow_action actions[],
1153 : : struct nfp_fl_key_ls *key_ls)
1154 : : {
1155 : : int ret = 0;
1156 : :
1157 : 0 : key_ls->key_layer_two = 0;
1158 : 0 : key_ls->key_layer = NFP_FLOWER_LAYER_PORT;
1159 : 0 : key_ls->key_size = sizeof(struct nfp_flower_meta_tci) +
1160 : : sizeof(struct nfp_flower_in_port);
1161 : 0 : key_ls->act_size = 0;
1162 : 0 : key_ls->port = ~0;
1163 : 0 : key_ls->vlan = 0;
1164 : 0 : key_ls->tun_type = NFP_FL_TUN_NONE;
1165 : :
1166 : 0 : ret |= nfp_flow_key_layers_calculate_items(items, key_ls);
1167 : 0 : ret |= nfp_flow_key_layers_calculate_actions(actions, key_ls);
1168 : :
1169 : 0 : return ret;
1170 : : }
1171 : :
1172 : : static bool
1173 : 0 : nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
1174 : : {
1175 : : uint32_t key_layer2;
1176 : : struct nfp_flower_ext_meta *ext_meta;
1177 : : struct nfp_flower_meta_tci *meta_tci;
1178 : :
1179 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1180 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN) != 0)
1181 : : return true;
1182 : :
1183 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) == 0)
1184 : : return false;
1185 : :
1186 : : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1187 [ # # ]: 0 : key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
1188 [ # # ]: 0 : if ((key_layer2 & (NFP_FLOWER_LAYER2_GENEVE | NFP_FLOWER_LAYER2_GRE)) != 0)
1189 : 0 : return true;
1190 : :
1191 : : return false;
1192 : : }
1193 : :
1194 : : static int
1195 : 0 : nfp_flow_merge_eth(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1196 : : __rte_unused struct rte_flow *nfp_flow,
1197 : : char **mbuf_off,
1198 : : const struct rte_flow_item *item,
1199 : : const struct nfp_flow_item_proc *proc,
1200 : : bool is_mask,
1201 : : __rte_unused bool is_outer_layer)
1202 : : {
1203 : : struct nfp_flower_mac_mpls *eth;
1204 : : const struct rte_flow_item_eth *spec;
1205 : : const struct rte_flow_item_eth *mask;
1206 : :
1207 : 0 : spec = item->spec;
1208 [ # # ]: 0 : if (spec == NULL) {
1209 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge eth: no item->spec!");
1210 : 0 : goto eth_end;
1211 : : }
1212 : :
1213 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1214 : 0 : eth = (void *)*mbuf_off;
1215 : :
1216 [ # # ]: 0 : if (is_mask) {
1217 : 0 : memcpy(eth->mac_src, mask->hdr.src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
1218 : 0 : memcpy(eth->mac_dst, mask->hdr.dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
1219 : : } else {
1220 : 0 : memcpy(eth->mac_src, spec->hdr.src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
1221 : 0 : memcpy(eth->mac_dst, spec->hdr.dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
1222 : : }
1223 : :
1224 : 0 : eth->mpls_lse = 0;
1225 : :
1226 : 0 : eth_end:
1227 : 0 : *mbuf_off += sizeof(struct nfp_flower_mac_mpls);
1228 : :
1229 : 0 : return 0;
1230 : : }
1231 : :
1232 : : static int
1233 : 0 : nfp_flow_merge_vlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1234 : : struct rte_flow *nfp_flow,
1235 : : __rte_unused char **mbuf_off,
1236 : : const struct rte_flow_item *item,
1237 : : const struct nfp_flow_item_proc *proc,
1238 : : bool is_mask,
1239 : : __rte_unused bool is_outer_layer)
1240 : : {
1241 : : struct nfp_flower_meta_tci *meta_tci;
1242 : : const struct rte_flow_item_vlan *spec;
1243 : : const struct rte_flow_item_vlan *mask;
1244 : :
1245 : 0 : spec = item->spec;
1246 [ # # ]: 0 : if (spec == NULL) {
1247 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge vlan: no item->spec!");
1248 : 0 : return 0;
1249 : : }
1250 : :
1251 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1252 [ # # ]: 0 : if (is_mask) {
1253 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.mask_data;
1254 : 0 : meta_tci->tci |= mask->hdr.vlan_tci;
1255 : : } else {
1256 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1257 : 0 : meta_tci->tci |= spec->hdr.vlan_tci;
1258 : : }
1259 : :
1260 : : return 0;
1261 : : }
1262 : :
1263 : : static int
1264 : 0 : nfp_flow_merge_ipv4(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1265 : : struct rte_flow *nfp_flow,
1266 : : char **mbuf_off,
1267 : : const struct rte_flow_item *item,
1268 : : const struct nfp_flow_item_proc *proc,
1269 : : bool is_mask,
1270 : : bool is_outer_layer)
1271 : : {
1272 : : struct nfp_flower_ipv4 *ipv4;
1273 : : const struct rte_ipv4_hdr *hdr;
1274 : : struct nfp_flower_meta_tci *meta_tci;
1275 : : const struct rte_flow_item_ipv4 *spec;
1276 : : const struct rte_flow_item_ipv4 *mask;
1277 : : struct nfp_flower_ext_meta *ext_meta = NULL;
1278 : : struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
1279 : : struct nfp_flower_ipv4_gre_tun *ipv4_gre_tun;
1280 : :
1281 : 0 : spec = item->spec;
1282 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1283 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1284 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) != 0)
1285 : 0 : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1286 : :
1287 [ # # # # ]: 0 : if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
1288 [ # # ]: 0 : if (spec == NULL) {
1289 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
1290 : 0 : return 0;
1291 : : }
1292 : :
1293 [ # # ]: 0 : hdr = is_mask ? &mask->hdr : &spec->hdr;
1294 : :
1295 [ # # # # : 0 : if (ext_meta != NULL && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
# # ]
1296 [ # # ]: 0 : NFP_FLOWER_LAYER2_GRE) != 0) {
1297 : 0 : ipv4_gre_tun = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
1298 : :
1299 : 0 : ipv4_gre_tun->ip_ext.tos = hdr->type_of_service;
1300 : 0 : ipv4_gre_tun->ip_ext.ttl = hdr->time_to_live;
1301 : 0 : ipv4_gre_tun->ipv4.src = hdr->src_addr;
1302 : 0 : ipv4_gre_tun->ipv4.dst = hdr->dst_addr;
1303 : : } else {
1304 : 0 : ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
1305 : :
1306 : 0 : ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
1307 : 0 : ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
1308 : 0 : ipv4_udp_tun->ipv4.src = hdr->src_addr;
1309 : 0 : ipv4_udp_tun->ipv4.dst = hdr->dst_addr;
1310 : : }
1311 : : } else {
1312 [ # # ]: 0 : if (spec == NULL) {
1313 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
1314 : 0 : goto ipv4_end;
1315 : : }
1316 : :
1317 : : /*
1318 : : * Reserve space for L4 info.
1319 : : * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4.
1320 : : */
1321 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP) != 0)
1322 : 0 : *mbuf_off += sizeof(struct nfp_flower_tp_ports);
1323 : :
1324 [ # # ]: 0 : hdr = is_mask ? &mask->hdr : &spec->hdr;
1325 : 0 : ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
1326 : :
1327 : 0 : ipv4->ip_ext.tos = hdr->type_of_service;
1328 : 0 : ipv4->ip_ext.proto = hdr->next_proto_id;
1329 : 0 : ipv4->ip_ext.ttl = hdr->time_to_live;
1330 : 0 : ipv4->ipv4_src = hdr->src_addr;
1331 : 0 : ipv4->ipv4_dst = hdr->dst_addr;
1332 : :
1333 : 0 : ipv4_end:
1334 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv4);
1335 : : }
1336 : :
1337 : : return 0;
1338 : : }
1339 : :
1340 : : static int
1341 : 0 : nfp_flow_merge_ipv6(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1342 : : struct rte_flow *nfp_flow,
1343 : : char **mbuf_off,
1344 : : const struct rte_flow_item *item,
1345 : : const struct nfp_flow_item_proc *proc,
1346 : : bool is_mask,
1347 : : bool is_outer_layer)
1348 : : {
1349 : : uint32_t vtc_flow;
1350 : : struct nfp_flower_ipv6 *ipv6;
1351 : : const struct rte_ipv6_hdr *hdr;
1352 : : struct nfp_flower_meta_tci *meta_tci;
1353 : : const struct rte_flow_item_ipv6 *spec;
1354 : : const struct rte_flow_item_ipv6 *mask;
1355 : : struct nfp_flower_ext_meta *ext_meta = NULL;
1356 : : struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
1357 : : struct nfp_flower_ipv6_gre_tun *ipv6_gre_tun;
1358 : :
1359 : 0 : spec = item->spec;
1360 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1361 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1362 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) != 0)
1363 : 0 : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1364 : :
1365 [ # # # # ]: 0 : if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
1366 [ # # ]: 0 : if (spec == NULL) {
1367 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
1368 : 0 : return 0;
1369 : : }
1370 : :
1371 [ # # ]: 0 : hdr = is_mask ? &mask->hdr : &spec->hdr;
1372 : :
1373 [ # # ]: 0 : vtc_flow = rte_be_to_cpu_32(hdr->vtc_flow);
1374 [ # # # # : 0 : if (ext_meta != NULL && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
# # ]
1375 [ # # ]: 0 : NFP_FLOWER_LAYER2_GRE) != 0) {
1376 : 0 : ipv6_gre_tun = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
1377 : :
1378 : 0 : ipv6_gre_tun->ip_ext.tos = vtc_flow >> RTE_IPV6_HDR_TC_SHIFT;
1379 : 0 : ipv6_gre_tun->ip_ext.ttl = hdr->hop_limits;
1380 : 0 : memcpy(ipv6_gre_tun->ipv6.ipv6_src, hdr->src_addr,
1381 : : sizeof(ipv6_gre_tun->ipv6.ipv6_src));
1382 : 0 : memcpy(ipv6_gre_tun->ipv6.ipv6_dst, hdr->dst_addr,
1383 : : sizeof(ipv6_gre_tun->ipv6.ipv6_dst));
1384 : : } else {
1385 : 0 : ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
1386 : :
1387 : 0 : ipv6_udp_tun->ip_ext.tos = vtc_flow >> RTE_IPV6_HDR_TC_SHIFT;
1388 : 0 : ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
1389 : 0 : memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
1390 : : sizeof(ipv6_udp_tun->ipv6.ipv6_src));
1391 : 0 : memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
1392 : : sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
1393 : : }
1394 : : } else {
1395 [ # # ]: 0 : if (spec == NULL) {
1396 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
1397 : 0 : goto ipv6_end;
1398 : : }
1399 : :
1400 : : /*
1401 : : * Reserve space for L4 info.
1402 : : * rte_flow has ipv6 before L4 but NFP flower fw requires L4 before ipv6.
1403 : : */
1404 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP) != 0)
1405 : 0 : *mbuf_off += sizeof(struct nfp_flower_tp_ports);
1406 : :
1407 [ # # ]: 0 : hdr = is_mask ? &mask->hdr : &spec->hdr;
1408 [ # # ]: 0 : vtc_flow = rte_be_to_cpu_32(hdr->vtc_flow);
1409 : 0 : ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
1410 : :
1411 : 0 : ipv6->ip_ext.tos = vtc_flow >> RTE_IPV6_HDR_TC_SHIFT;
1412 : 0 : ipv6->ip_ext.proto = hdr->proto;
1413 : 0 : ipv6->ip_ext.ttl = hdr->hop_limits;
1414 : 0 : memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
1415 : 0 : memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
1416 : :
1417 : 0 : ipv6_end:
1418 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv6);
1419 : : }
1420 : :
1421 : : return 0;
1422 : : }
1423 : :
1424 : : static int
1425 : 0 : nfp_flow_merge_tcp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1426 : : struct rte_flow *nfp_flow,
1427 : : char **mbuf_off,
1428 : : const struct rte_flow_item *item,
1429 : : const struct nfp_flow_item_proc *proc,
1430 : : bool is_mask,
1431 : : __rte_unused bool is_outer_layer)
1432 : : {
1433 : : uint8_t tcp_flags;
1434 : : struct nfp_flower_tp_ports *ports;
1435 : : struct nfp_flower_ipv4 *ipv4 = NULL;
1436 : : struct nfp_flower_ipv6 *ipv6 = NULL;
1437 : : const struct rte_flow_item_tcp *spec;
1438 : : const struct rte_flow_item_tcp *mask;
1439 : : struct nfp_flower_meta_tci *meta_tci;
1440 : :
1441 : 0 : spec = item->spec;
1442 [ # # ]: 0 : if (spec == NULL) {
1443 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge tcp: no item->spec!");
1444 : 0 : return 0;
1445 : : }
1446 : :
1447 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1448 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) != 0) {
1449 : 0 : ipv4 = (struct nfp_flower_ipv4 *)
1450 : 0 : (*mbuf_off - sizeof(struct nfp_flower_ipv4));
1451 : 0 : ports = (struct nfp_flower_tp_ports *)
1452 : : ((char *)ipv4 - sizeof(struct nfp_flower_tp_ports));
1453 : : } else { /* IPv6 */
1454 : 0 : ipv6 = (struct nfp_flower_ipv6 *)
1455 : 0 : (*mbuf_off - sizeof(struct nfp_flower_ipv6));
1456 : 0 : ports = (struct nfp_flower_tp_ports *)
1457 : : ((char *)ipv6 - sizeof(struct nfp_flower_tp_ports));
1458 : : }
1459 : :
1460 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1461 [ # # ]: 0 : if (is_mask) {
1462 : 0 : ports->port_src = mask->hdr.src_port;
1463 : 0 : ports->port_dst = mask->hdr.dst_port;
1464 : 0 : tcp_flags = mask->hdr.tcp_flags;
1465 : : } else {
1466 : 0 : ports->port_src = spec->hdr.src_port;
1467 : 0 : ports->port_dst = spec->hdr.dst_port;
1468 : 0 : tcp_flags = spec->hdr.tcp_flags;
1469 : : }
1470 : :
1471 [ # # ]: 0 : if (ipv4 != NULL) {
1472 [ # # ]: 0 : if (tcp_flags & RTE_TCP_FIN_FLAG)
1473 : 0 : ipv4->ip_ext.flags |= NFP_FL_TCP_FLAG_FIN;
1474 [ # # ]: 0 : if (tcp_flags & RTE_TCP_SYN_FLAG)
1475 : 0 : ipv4->ip_ext.flags |= NFP_FL_TCP_FLAG_SYN;
1476 [ # # ]: 0 : if (tcp_flags & RTE_TCP_RST_FLAG)
1477 : 0 : ipv4->ip_ext.flags |= NFP_FL_TCP_FLAG_RST;
1478 [ # # ]: 0 : if (tcp_flags & RTE_TCP_PSH_FLAG)
1479 : 0 : ipv4->ip_ext.flags |= NFP_FL_TCP_FLAG_PSH;
1480 [ # # ]: 0 : if (tcp_flags & RTE_TCP_URG_FLAG)
1481 : 0 : ipv4->ip_ext.flags |= NFP_FL_TCP_FLAG_URG;
1482 : : } else { /* IPv6 */
1483 [ # # ]: 0 : if (tcp_flags & RTE_TCP_FIN_FLAG)
1484 : 0 : ipv6->ip_ext.flags |= NFP_FL_TCP_FLAG_FIN;
1485 [ # # ]: 0 : if (tcp_flags & RTE_TCP_SYN_FLAG)
1486 : 0 : ipv6->ip_ext.flags |= NFP_FL_TCP_FLAG_SYN;
1487 [ # # ]: 0 : if (tcp_flags & RTE_TCP_RST_FLAG)
1488 : 0 : ipv6->ip_ext.flags |= NFP_FL_TCP_FLAG_RST;
1489 [ # # ]: 0 : if (tcp_flags & RTE_TCP_PSH_FLAG)
1490 : 0 : ipv6->ip_ext.flags |= NFP_FL_TCP_FLAG_PSH;
1491 [ # # ]: 0 : if (tcp_flags & RTE_TCP_URG_FLAG)
1492 : 0 : ipv6->ip_ext.flags |= NFP_FL_TCP_FLAG_URG;
1493 : : }
1494 : :
1495 : : return 0;
1496 : : }
1497 : :
1498 : : static int
1499 : 0 : nfp_flow_merge_udp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1500 : : struct rte_flow *nfp_flow,
1501 : : char **mbuf_off,
1502 : : const struct rte_flow_item *item,
1503 : : const struct nfp_flow_item_proc *proc,
1504 : : bool is_mask,
1505 : : bool is_outer_layer)
1506 : : {
1507 : : char *ports_off;
1508 : : struct nfp_flower_tp_ports *ports;
1509 : : const struct rte_flow_item_udp *spec;
1510 : : const struct rte_flow_item_udp *mask;
1511 : : struct nfp_flower_meta_tci *meta_tci;
1512 : :
1513 : 0 : spec = item->spec;
1514 [ # # ]: 0 : if (spec == NULL) {
1515 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge udp: no item->spec!");
1516 : 0 : return 0;
1517 : : }
1518 : :
1519 : : /* Don't add L4 info if working on a inner layer pattern */
1520 [ # # ]: 0 : if (!is_outer_layer) {
1521 : 0 : PMD_DRV_LOG(INFO, "Detected inner layer UDP, skipping.");
1522 : 0 : return 0;
1523 : : }
1524 : :
1525 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1526 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) != 0) {
1527 : 0 : ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv4) -
1528 : : sizeof(struct nfp_flower_tp_ports);
1529 : : } else {/* IPv6 */
1530 : 0 : ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv6) -
1531 : : sizeof(struct nfp_flower_tp_ports);
1532 : : }
1533 : : ports = (struct nfp_flower_tp_ports *)ports_off;
1534 : :
1535 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1536 [ # # ]: 0 : if (is_mask) {
1537 : 0 : ports->port_src = mask->hdr.src_port;
1538 : 0 : ports->port_dst = mask->hdr.dst_port;
1539 : : } else {
1540 : 0 : ports->port_src = spec->hdr.src_port;
1541 : 0 : ports->port_dst = spec->hdr.dst_port;
1542 : : }
1543 : :
1544 : : return 0;
1545 : : }
1546 : :
1547 : : static int
1548 : 0 : nfp_flow_merge_sctp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1549 : : struct rte_flow *nfp_flow,
1550 : : char **mbuf_off,
1551 : : const struct rte_flow_item *item,
1552 : : const struct nfp_flow_item_proc *proc,
1553 : : bool is_mask,
1554 : : __rte_unused bool is_outer_layer)
1555 : : {
1556 : : char *ports_off;
1557 : : struct nfp_flower_tp_ports *ports;
1558 : : struct nfp_flower_meta_tci *meta_tci;
1559 : : const struct rte_flow_item_sctp *spec;
1560 : : const struct rte_flow_item_sctp *mask;
1561 : :
1562 : 0 : spec = item->spec;
1563 [ # # ]: 0 : if (spec == NULL) {
1564 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge sctp: no item->spec!");
1565 : 0 : return 0;
1566 : : }
1567 : :
1568 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1569 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) != 0) {
1570 : 0 : ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv4) -
1571 : : sizeof(struct nfp_flower_tp_ports);
1572 : : } else { /* IPv6 */
1573 : 0 : ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv6) -
1574 : : sizeof(struct nfp_flower_tp_ports);
1575 : : }
1576 : : ports = (struct nfp_flower_tp_ports *)ports_off;
1577 : :
1578 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1579 [ # # ]: 0 : if (is_mask) {
1580 : 0 : ports->port_src = mask->hdr.src_port;
1581 : 0 : ports->port_dst = mask->hdr.dst_port;
1582 : : } else {
1583 : 0 : ports->port_src = spec->hdr.src_port;
1584 : 0 : ports->port_dst = spec->hdr.dst_port;
1585 : : }
1586 : :
1587 : : return 0;
1588 : : }
1589 : :
1590 : : static int
1591 : 0 : nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
1592 : : struct rte_flow *nfp_flow,
1593 : : char **mbuf_off,
1594 : : const struct rte_flow_item *item,
1595 : : const struct nfp_flow_item_proc *proc,
1596 : : bool is_mask,
1597 : : __rte_unused bool is_outer_layer)
1598 : : {
1599 : : int ret = 0;
1600 : : const struct rte_vxlan_hdr *hdr;
1601 : : struct nfp_flower_ipv4_udp_tun *tun4;
1602 : : struct nfp_flower_ipv6_udp_tun *tun6;
1603 : : struct nfp_flower_meta_tci *meta_tci;
1604 : : const struct rte_flow_item_vxlan *spec;
1605 : : const struct rte_flow_item_vxlan *mask;
1606 : : struct nfp_flower_ext_meta *ext_meta = NULL;
1607 : :
1608 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1609 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) != 0)
1610 : 0 : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1611 : :
1612 : 0 : spec = item->spec;
1613 [ # # ]: 0 : if (spec == NULL) {
1614 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge vxlan: no item->spec!");
1615 : 0 : goto vxlan_end;
1616 : : }
1617 : :
1618 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1619 [ # # ]: 0 : hdr = is_mask ? &mask->hdr : &spec->hdr;
1620 : :
1621 [ # # # # : 0 : if (ext_meta != NULL && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
# # ]
1622 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0) {
1623 : 0 : tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
1624 : 0 : tun6->tun_id = hdr->vx_vni;
1625 [ # # ]: 0 : if (!is_mask)
1626 : 0 : ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
1627 : : } else {
1628 : 0 : tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
1629 : 0 : tun4->tun_id = hdr->vx_vni;
1630 [ # # ]: 0 : if (!is_mask)
1631 : 0 : ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
1632 : : }
1633 : :
1634 : 0 : vxlan_end:
1635 [ # # # # : 0 : if (ext_meta != NULL && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
# # ]
1636 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0)
1637 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
1638 : : else
1639 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
1640 : :
1641 : 0 : return ret;
1642 : : }
1643 : :
1644 : : static int
1645 : 0 : nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
1646 : : struct rte_flow *nfp_flow,
1647 : : char **mbuf_off,
1648 : : const struct rte_flow_item *item,
1649 : : const struct nfp_flow_item_proc *proc,
1650 : : bool is_mask,
1651 : : __rte_unused bool is_outer_layer)
1652 : : {
1653 : : int ret = 0;
1654 : : struct nfp_flower_ipv4_udp_tun *tun4;
1655 : : struct nfp_flower_ipv6_udp_tun *tun6;
1656 : : struct nfp_flower_meta_tci *meta_tci;
1657 : : const struct rte_flow_item_geneve *spec;
1658 : : const struct rte_flow_item_geneve *mask;
1659 : : const struct rte_flow_item_geneve *geneve;
1660 : : struct nfp_flower_ext_meta *ext_meta = NULL;
1661 : :
1662 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1663 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) != 0)
1664 : 0 : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1665 : :
1666 : 0 : spec = item->spec;
1667 [ # # ]: 0 : if (spec == NULL) {
1668 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge geneve: no item->spec!");
1669 : 0 : goto geneve_end;
1670 : : }
1671 : :
1672 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1673 [ # # ]: 0 : geneve = is_mask ? mask : spec;
1674 : :
1675 [ # # # # : 0 : if (ext_meta != NULL && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
# # ]
1676 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0) {
1677 : 0 : tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
1678 [ # # ]: 0 : tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
1679 : : (geneve->vni[1] << 8) | (geneve->vni[2]));
1680 [ # # ]: 0 : if (!is_mask)
1681 : 0 : ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
1682 : : } else {
1683 : 0 : tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
1684 [ # # ]: 0 : tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
1685 : : (geneve->vni[1] << 8) | (geneve->vni[2]));
1686 [ # # ]: 0 : if (!is_mask)
1687 : 0 : ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
1688 : : }
1689 : :
1690 : 0 : geneve_end:
1691 [ # # # # : 0 : if (ext_meta != NULL && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
# # ]
1692 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0) {
1693 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
1694 : : } else {
1695 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
1696 : : }
1697 : :
1698 : 0 : return ret;
1699 : : }
1700 : :
1701 : : static int
1702 : 0 : nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
1703 : : struct rte_flow *nfp_flow,
1704 : : char **mbuf_off,
1705 : : __rte_unused const struct rte_flow_item *item,
1706 : : __rte_unused const struct nfp_flow_item_proc *proc,
1707 : : bool is_mask,
1708 : : __rte_unused bool is_outer_layer)
1709 : : {
1710 : : struct nfp_flower_meta_tci *meta_tci;
1711 : : struct nfp_flower_ext_meta *ext_meta;
1712 : : struct nfp_flower_ipv4_gre_tun *tun4;
1713 : : struct nfp_flower_ipv6_gre_tun *tun6;
1714 : :
1715 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1716 : : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1717 : :
1718 : : /* NVGRE is the only supported GRE tunnel type */
1719 [ # # ]: 0 : if ((rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
1720 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0) {
1721 : 0 : tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
1722 [ # # ]: 0 : if (is_mask)
1723 : 0 : tun6->ethertype = rte_cpu_to_be_16(~0);
1724 : : else
1725 : 0 : tun6->ethertype = rte_cpu_to_be_16(0x6558);
1726 : : } else {
1727 : 0 : tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
1728 [ # # ]: 0 : if (is_mask)
1729 : 0 : tun4->ethertype = rte_cpu_to_be_16(~0);
1730 : : else
1731 : 0 : tun4->ethertype = rte_cpu_to_be_16(0x6558);
1732 : : }
1733 : :
1734 : 0 : return 0;
1735 : : }
1736 : :
1737 : : static int
1738 : 0 : nfp_flow_merge_gre_key(struct nfp_app_fw_flower *app_fw_flower,
1739 : : struct rte_flow *nfp_flow,
1740 : : char **mbuf_off,
1741 : : const struct rte_flow_item *item,
1742 : : const struct nfp_flow_item_proc *proc,
1743 : : bool is_mask,
1744 : : __rte_unused bool is_outer_layer)
1745 : : {
1746 : : int ret = 0;
1747 : : rte_be32_t tun_key;
1748 : : const rte_be32_t *spec;
1749 : : const rte_be32_t *mask;
1750 : : struct nfp_flower_meta_tci *meta_tci;
1751 : : struct nfp_flower_ext_meta *ext_meta;
1752 : : struct nfp_flower_ipv4_gre_tun *tun4;
1753 : : struct nfp_flower_ipv6_gre_tun *tun6;
1754 : :
1755 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
1756 : : ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
1757 : :
1758 : 0 : spec = item->spec;
1759 [ # # ]: 0 : if (spec == NULL) {
1760 : 0 : PMD_DRV_LOG(DEBUG, "nfp flow merge gre key: no item->spec!");
1761 : 0 : goto gre_key_end;
1762 : : }
1763 : :
1764 [ # # ]: 0 : mask = item->mask ? item->mask : proc->mask_default;
1765 [ # # ]: 0 : tun_key = is_mask ? *mask : *spec;
1766 : :
1767 [ # # ]: 0 : if ((rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
1768 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0) {
1769 : 0 : tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
1770 : 0 : tun6->tun_key = tun_key;
1771 : 0 : tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
1772 [ # # ]: 0 : if (!is_mask)
1773 : 0 : ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
1774 : : } else {
1775 : 0 : tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
1776 : 0 : tun4->tun_key = tun_key;
1777 : 0 : tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
1778 [ # # ]: 0 : if (!is_mask)
1779 : 0 : ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
1780 : : }
1781 : :
1782 : 0 : gre_key_end:
1783 [ # # ]: 0 : if ((rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
1784 [ # # ]: 0 : NFP_FLOWER_LAYER2_TUN_IPV6) != 0)
1785 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv6_gre_tun);
1786 : : else
1787 : 0 : *mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
1788 : :
1789 : 0 : return ret;
1790 : : }
1791 : :
1792 : : const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
1793 : :
1794 : : /* Graph of supported items and associated process function */
1795 : : static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
1796 : : [RTE_FLOW_ITEM_TYPE_END] = {
1797 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
1798 : : RTE_FLOW_ITEM_TYPE_IPV4,
1799 : : RTE_FLOW_ITEM_TYPE_IPV6),
1800 : : },
1801 : : [RTE_FLOW_ITEM_TYPE_ETH] = {
1802 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
1803 : : RTE_FLOW_ITEM_TYPE_IPV4,
1804 : : RTE_FLOW_ITEM_TYPE_IPV6),
1805 : : .mask_support = &(const struct rte_flow_item_eth) {
1806 : : .hdr = {
1807 : : .dst_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
1808 : : .src_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
1809 : : .ether_type = RTE_BE16(0xffff),
1810 : : },
1811 : : .has_vlan = 1,
1812 : : },
1813 : : .mask_default = &rte_flow_item_eth_mask,
1814 : : .mask_sz = sizeof(struct rte_flow_item_eth),
1815 : : .merge = nfp_flow_merge_eth,
1816 : : },
1817 : : [RTE_FLOW_ITEM_TYPE_VLAN] = {
1818 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_IPV4,
1819 : : RTE_FLOW_ITEM_TYPE_IPV6),
1820 : : .mask_support = &(const struct rte_flow_item_vlan) {
1821 : : .hdr = {
1822 : : .vlan_tci = RTE_BE16(0xefff),
1823 : : .eth_proto = RTE_BE16(0xffff),
1824 : : },
1825 : : .has_more_vlan = 1,
1826 : : },
1827 : : .mask_default = &rte_flow_item_vlan_mask,
1828 : : .mask_sz = sizeof(struct rte_flow_item_vlan),
1829 : : .merge = nfp_flow_merge_vlan,
1830 : : },
1831 : : [RTE_FLOW_ITEM_TYPE_IPV4] = {
1832 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
1833 : : RTE_FLOW_ITEM_TYPE_UDP,
1834 : : RTE_FLOW_ITEM_TYPE_SCTP,
1835 : : RTE_FLOW_ITEM_TYPE_GRE),
1836 : : .mask_support = &(const struct rte_flow_item_ipv4) {
1837 : : .hdr = {
1838 : : .type_of_service = 0xff,
1839 : : .fragment_offset = RTE_BE16(0xffff),
1840 : : .time_to_live = 0xff,
1841 : : .next_proto_id = 0xff,
1842 : : .src_addr = RTE_BE32(0xffffffff),
1843 : : .dst_addr = RTE_BE32(0xffffffff),
1844 : : },
1845 : : },
1846 : : .mask_default = &rte_flow_item_ipv4_mask,
1847 : : .mask_sz = sizeof(struct rte_flow_item_ipv4),
1848 : : .merge = nfp_flow_merge_ipv4,
1849 : : },
1850 : : [RTE_FLOW_ITEM_TYPE_IPV6] = {
1851 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
1852 : : RTE_FLOW_ITEM_TYPE_UDP,
1853 : : RTE_FLOW_ITEM_TYPE_SCTP,
1854 : : RTE_FLOW_ITEM_TYPE_GRE),
1855 : : .mask_support = &(const struct rte_flow_item_ipv6) {
1856 : : .hdr = {
1857 : : .vtc_flow = RTE_BE32(0x0ff00000),
1858 : : .proto = 0xff,
1859 : : .hop_limits = 0xff,
1860 : : .src_addr = "\xff\xff\xff\xff\xff\xff\xff\xff"
1861 : : "\xff\xff\xff\xff\xff\xff\xff\xff",
1862 : : .dst_addr = "\xff\xff\xff\xff\xff\xff\xff\xff"
1863 : : "\xff\xff\xff\xff\xff\xff\xff\xff",
1864 : : },
1865 : : .has_frag_ext = 1,
1866 : : },
1867 : : .mask_default = &rte_flow_item_ipv6_mask,
1868 : : .mask_sz = sizeof(struct rte_flow_item_ipv6),
1869 : : .merge = nfp_flow_merge_ipv6,
1870 : : },
1871 : : [RTE_FLOW_ITEM_TYPE_TCP] = {
1872 : : .mask_support = &(const struct rte_flow_item_tcp) {
1873 : : .hdr = {
1874 : : .tcp_flags = 0xff,
1875 : : .src_port = RTE_BE16(0xffff),
1876 : : .dst_port = RTE_BE16(0xffff),
1877 : : },
1878 : : },
1879 : : .mask_default = &rte_flow_item_tcp_mask,
1880 : : .mask_sz = sizeof(struct rte_flow_item_tcp),
1881 : : .merge = nfp_flow_merge_tcp,
1882 : : },
1883 : : [RTE_FLOW_ITEM_TYPE_UDP] = {
1884 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN,
1885 : : RTE_FLOW_ITEM_TYPE_GENEVE),
1886 : : .mask_support = &(const struct rte_flow_item_udp) {
1887 : : .hdr = {
1888 : : .src_port = RTE_BE16(0xffff),
1889 : : .dst_port = RTE_BE16(0xffff),
1890 : : },
1891 : : },
1892 : : .mask_default = &rte_flow_item_udp_mask,
1893 : : .mask_sz = sizeof(struct rte_flow_item_udp),
1894 : : .merge = nfp_flow_merge_udp,
1895 : : },
1896 : : [RTE_FLOW_ITEM_TYPE_SCTP] = {
1897 : : .mask_support = &(const struct rte_flow_item_sctp) {
1898 : : .hdr = {
1899 : : .src_port = RTE_BE16(0xffff),
1900 : : .dst_port = RTE_BE16(0xffff),
1901 : : },
1902 : : },
1903 : : .mask_default = &rte_flow_item_sctp_mask,
1904 : : .mask_sz = sizeof(struct rte_flow_item_sctp),
1905 : : .merge = nfp_flow_merge_sctp,
1906 : : },
1907 : : [RTE_FLOW_ITEM_TYPE_VXLAN] = {
1908 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
1909 : : .mask_support = &(const struct rte_flow_item_vxlan) {
1910 : : .hdr = {
1911 : : .vx_vni = RTE_BE32(0xffffff00),
1912 : : },
1913 : : },
1914 : : .mask_default = &rte_flow_item_vxlan_mask,
1915 : : .mask_sz = sizeof(struct rte_flow_item_vxlan),
1916 : : .merge = nfp_flow_merge_vxlan,
1917 : : },
1918 : : [RTE_FLOW_ITEM_TYPE_GENEVE] = {
1919 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
1920 : : .mask_support = &(const struct rte_flow_item_geneve) {
1921 : : .vni = "\xff\xff\xff",
1922 : : },
1923 : : .mask_default = &rte_flow_item_geneve_mask,
1924 : : .mask_sz = sizeof(struct rte_flow_item_geneve),
1925 : : .merge = nfp_flow_merge_geneve,
1926 : : },
1927 : : [RTE_FLOW_ITEM_TYPE_GRE] = {
1928 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_GRE_KEY),
1929 : : .mask_support = &(const struct rte_flow_item_gre) {
1930 : : .c_rsvd0_ver = RTE_BE16(0xa000),
1931 : : .protocol = RTE_BE16(0xffff),
1932 : : },
1933 : : .mask_default = &rte_flow_item_gre_mask,
1934 : : .mask_sz = sizeof(struct rte_flow_item_gre),
1935 : : .merge = nfp_flow_merge_gre,
1936 : : },
1937 : : [RTE_FLOW_ITEM_TYPE_GRE_KEY] = {
1938 : : .next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
1939 : : .mask_support = &nfp_flow_item_gre_key,
1940 : : .mask_default = &nfp_flow_item_gre_key,
1941 : : .mask_sz = sizeof(rte_be32_t),
1942 : : .merge = nfp_flow_merge_gre_key,
1943 : : },
1944 : : };
1945 : :
1946 : : static int
1947 : 0 : nfp_flow_item_check(const struct rte_flow_item *item,
1948 : : const struct nfp_flow_item_proc *proc)
1949 : : {
1950 : : size_t i;
1951 : : int ret = 0;
1952 : : const uint8_t *mask;
1953 : :
1954 : : /* item->last and item->mask cannot exist without item->spec. */
1955 [ # # ]: 0 : if (item->spec == NULL) {
1956 [ # # # # ]: 0 : if (item->mask || item->last) {
1957 : 0 : PMD_DRV_LOG(ERR, "'mask' or 'last' field provided"
1958 : : " without a corresponding 'spec'.");
1959 : 0 : return -EINVAL;
1960 : : }
1961 : :
1962 : : /* No spec, no mask, no problem. */
1963 : : return 0;
1964 : : }
1965 : :
1966 [ # # ]: 0 : mask = item->mask ? (const uint8_t *)item->mask :
1967 : : (const uint8_t *)proc->mask_default;
1968 : :
1969 : : /*
1970 : : * Single-pass check to make sure that:
1971 : : * - Mask is supported, no bits are set outside proc->mask_support.
1972 : : * - Both item->spec and item->last are included in mask.
1973 : : */
1974 [ # # ]: 0 : for (i = 0; i != proc->mask_sz; ++i) {
1975 [ # # ]: 0 : if (mask[i] == 0)
1976 : 0 : continue;
1977 : :
1978 [ # # ]: 0 : if ((mask[i] | ((const uint8_t *)proc->mask_support)[i]) !=
1979 : : ((const uint8_t *)proc->mask_support)[i]) {
1980 : 0 : PMD_DRV_LOG(ERR, "Unsupported field found in 'mask'.");
1981 : : ret = -EINVAL;
1982 : 0 : break;
1983 : : }
1984 : :
1985 [ # # ]: 0 : if (item->last && (((const uint8_t *)item->spec)[i] & mask[i]) !=
1986 [ # # ]: 0 : (((const uint8_t *)item->last)[i] & mask[i])) {
1987 : 0 : PMD_DRV_LOG(ERR, "Range between 'spec' and 'last'"
1988 : : " is larger than 'mask'.");
1989 : : ret = -ERANGE;
1990 : 0 : break;
1991 : : }
1992 : : }
1993 : :
1994 : : return ret;
1995 : : }
1996 : :
1997 : : static bool
1998 : : nfp_flow_is_tun_item(const struct rte_flow_item *item)
1999 : : {
2000 [ # # # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
2001 : : item->type == RTE_FLOW_ITEM_TYPE_GENEVE ||
2002 : : item->type == RTE_FLOW_ITEM_TYPE_GRE_KEY)
2003 : : return true;
2004 : :
2005 : : return false;
2006 : : }
2007 : :
2008 : : bool
2009 : 0 : nfp_flow_inner_item_get(const struct rte_flow_item items[],
2010 : : const struct rte_flow_item **inner_item)
2011 : : {
2012 : : const struct rte_flow_item *item;
2013 : :
2014 : 0 : *inner_item = items;
2015 : :
2016 [ # # ]: 0 : for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
2017 : : if (nfp_flow_is_tun_item(item)) {
2018 : 0 : *inner_item = ++item;
2019 : 0 : return true;
2020 : : }
2021 : : }
2022 : :
2023 : : return false;
2024 : : }
2025 : :
2026 : : static bool
2027 : : nfp_flow_tcp_flag_check(const struct rte_flow_item items[])
2028 : : {
2029 : : const struct rte_flow_item *item;
2030 : :
2031 [ # # ]: 0 : for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
2032 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_TCP)
2033 : : return true;
2034 : : }
2035 : :
2036 : : return false;
2037 : : }
2038 : :
2039 : : static int
2040 : 0 : nfp_flow_compile_item_proc(struct nfp_flower_representor *repr,
2041 : : const struct rte_flow_item items[],
2042 : : struct rte_flow *nfp_flow,
2043 : : char **mbuf_off_exact,
2044 : : char **mbuf_off_mask,
2045 : : bool is_outer_layer)
2046 : : {
2047 : : uint32_t i;
2048 : : int ret = 0;
2049 : : bool continue_flag = true;
2050 : : const struct rte_flow_item *item;
2051 : : const struct nfp_flow_item_proc *proc_list;
2052 : 0 : struct nfp_app_fw_flower *app_fw_flower = repr->app_fw_flower;
2053 : :
2054 : : proc_list = nfp_flow_item_proc_list;
2055 [ # # # # ]: 0 : for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
2056 : : const struct nfp_flow_item_proc *proc = NULL;
2057 : :
2058 : : if (nfp_flow_is_tun_item(item))
2059 : : continue_flag = false;
2060 : :
2061 [ # # # # ]: 0 : for (i = 0; proc_list->next_item && proc_list->next_item[i]; ++i) {
2062 [ # # ]: 0 : if (proc_list->next_item[i] == item->type) {
2063 : 0 : proc = &nfp_flow_item_proc_list[item->type];
2064 : 0 : break;
2065 : : }
2066 : : }
2067 : :
2068 [ # # ]: 0 : if (proc == NULL) {
2069 : 0 : PMD_DRV_LOG(ERR, "No next item provided for %d", item->type);
2070 : : ret = -ENOTSUP;
2071 : 0 : break;
2072 : : }
2073 : :
2074 : : /* Perform basic sanity checks */
2075 : 0 : ret = nfp_flow_item_check(item, proc);
2076 [ # # ]: 0 : if (ret != 0) {
2077 : 0 : PMD_DRV_LOG(ERR, "nfp flow item %d check failed", item->type);
2078 : : ret = -EINVAL;
2079 : 0 : break;
2080 : : }
2081 : :
2082 [ # # ]: 0 : if (proc->merge == NULL) {
2083 : 0 : PMD_DRV_LOG(ERR, "nfp flow item %d no proc function", item->type);
2084 : : ret = -ENOTSUP;
2085 : 0 : break;
2086 : : }
2087 : :
2088 : 0 : ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_exact, item,
2089 : : proc, false, is_outer_layer);
2090 [ # # ]: 0 : if (ret != 0) {
2091 : 0 : PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
2092 : 0 : break;
2093 : : }
2094 : :
2095 : 0 : ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_mask, item,
2096 : : proc, true, is_outer_layer);
2097 [ # # ]: 0 : if (ret != 0) {
2098 : 0 : PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
2099 : 0 : break;
2100 : : }
2101 : :
2102 : : proc_list = proc;
2103 : : }
2104 : :
2105 : 0 : return ret;
2106 : : }
2107 : :
2108 : : static int
2109 : 0 : nfp_flow_compile_items(struct nfp_flower_representor *representor,
2110 : : const struct rte_flow_item items[],
2111 : : struct rte_flow *nfp_flow)
2112 : : {
2113 : : int ret;
2114 : : char *mbuf_off_mask;
2115 : : char *mbuf_off_exact;
2116 : : bool is_tun_flow = false;
2117 : : bool is_outer_layer = true;
2118 : : struct nfp_flower_meta_tci *meta_tci;
2119 : : const struct rte_flow_item *loop_item;
2120 : :
2121 : 0 : mbuf_off_exact = nfp_flow->payload.unmasked_data +
2122 : 0 : sizeof(struct nfp_flower_meta_tci) +
2123 : : sizeof(struct nfp_flower_in_port);
2124 : 0 : mbuf_off_mask = nfp_flow->payload.mask_data +
2125 : 0 : sizeof(struct nfp_flower_meta_tci) +
2126 : : sizeof(struct nfp_flower_in_port);
2127 : :
2128 : : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
2129 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) != 0) {
2130 : 0 : mbuf_off_exact += sizeof(struct nfp_flower_ext_meta);
2131 : 0 : mbuf_off_mask += sizeof(struct nfp_flower_ext_meta);
2132 : : }
2133 : :
2134 [ # # ]: 0 : if (nfp_flow_tcp_flag_check(items))
2135 : 0 : nfp_flow->tcp_flag = true;
2136 : :
2137 : : /* Check if this is a tunnel flow and get the inner item */
2138 : 0 : is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
2139 [ # # ]: 0 : if (is_tun_flow)
2140 : : is_outer_layer = false;
2141 : :
2142 : : /* Go over items */
2143 : 0 : ret = nfp_flow_compile_item_proc(representor, loop_item, nfp_flow,
2144 : : &mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
2145 [ # # ]: 0 : if (ret != 0) {
2146 : 0 : PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
2147 : 0 : return -EINVAL;
2148 : : }
2149 : :
2150 : : /* Go over inner items */
2151 [ # # ]: 0 : if (is_tun_flow) {
2152 : 0 : ret = nfp_flow_compile_item_proc(representor, items, nfp_flow,
2153 : : &mbuf_off_exact, &mbuf_off_mask, true);
2154 [ # # ]: 0 : if (ret != 0) {
2155 : 0 : PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
2156 : 0 : return -EINVAL;
2157 : : }
2158 : : }
2159 : :
2160 : : return 0;
2161 : : }
2162 : :
2163 : : static int
2164 : 0 : nfp_flow_action_output(char *act_data,
2165 : : const struct rte_flow_action *action,
2166 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2167 : : uint32_t output_cnt)
2168 : : {
2169 : : size_t act_size;
2170 : : struct rte_eth_dev *ethdev;
2171 : : struct nfp_fl_act_output *output;
2172 : : struct nfp_flower_representor *representor;
2173 : : const struct rte_flow_action_port_id *port_id;
2174 : :
2175 : 0 : port_id = action->conf;
2176 [ # # # # ]: 0 : if (port_id == NULL || port_id->id >= RTE_MAX_ETHPORTS)
2177 : : return -ERANGE;
2178 : :
2179 : : ethdev = &rte_eth_devices[port_id->id];
2180 : 0 : representor = ethdev->data->dev_private;
2181 : : act_size = sizeof(struct nfp_fl_act_output);
2182 : :
2183 : : output = (struct nfp_fl_act_output *)act_data;
2184 : 0 : output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT;
2185 : 0 : output->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2186 [ # # ]: 0 : output->port = rte_cpu_to_be_32(representor->port_id);
2187 [ # # ]: 0 : if (output_cnt == 0)
2188 : 0 : output->flags = rte_cpu_to_be_16(NFP_FL_OUT_FLAGS_LAST);
2189 : :
2190 [ # # ]: 0 : nfp_flow_meta->shortcut = rte_cpu_to_be_32(representor->port_id);
2191 : :
2192 : 0 : return 0;
2193 : : }
2194 : :
2195 : : static int
2196 : 0 : nfp_flow_action_output_stage(char *act_data,
2197 : : const struct rte_flow_action *action,
2198 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2199 : : uint32_t output_cnt)
2200 : : {
2201 : : size_t act_size;
2202 : : struct rte_eth_dev *ethdev;
2203 : : struct nfp_fl_act_output *output;
2204 : : struct nfp_flower_representor *representor;
2205 : : const struct rte_flow_action_ethdev *action_ethdev;
2206 : :
2207 : 0 : action_ethdev = action->conf;
2208 [ # # # # ]: 0 : if (action_ethdev == NULL || action_ethdev->port_id >= RTE_MAX_ETHPORTS)
2209 : : return -ERANGE;
2210 : :
2211 : 0 : ethdev = &rte_eth_devices[action_ethdev->port_id];
2212 : 0 : representor = ethdev->data->dev_private;
2213 : : act_size = sizeof(struct nfp_fl_act_output);
2214 : :
2215 : : output = (struct nfp_fl_act_output *)act_data;
2216 : 0 : output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT;
2217 : 0 : output->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2218 [ # # ]: 0 : output->port = rte_cpu_to_be_32(representor->port_id);
2219 [ # # ]: 0 : if (output_cnt == 0)
2220 : 0 : output->flags = rte_cpu_to_be_16(NFP_FL_OUT_FLAGS_LAST);
2221 : :
2222 [ # # ]: 0 : nfp_flow_meta->shortcut = rte_cpu_to_be_32(representor->port_id);
2223 : :
2224 : 0 : return 0;
2225 : : }
2226 : :
2227 : : static void
2228 : 0 : nfp_flow_action_set_mac(char *act_data,
2229 : : const struct rte_flow_action *action,
2230 : : bool mac_src_flag,
2231 : : bool mac_set_flag)
2232 : : {
2233 : : uint8_t i;
2234 : : size_t act_size;
2235 : : struct nfp_fl_act_set_eth *set_eth;
2236 : : const struct rte_flow_action_set_mac *set_mac;
2237 : :
2238 [ # # ]: 0 : if (mac_set_flag)
2239 : 0 : set_eth = (struct nfp_fl_act_set_eth *)act_data - 1;
2240 : : else
2241 : : set_eth = (struct nfp_fl_act_set_eth *)act_data;
2242 : :
2243 : : act_size = sizeof(struct nfp_fl_act_set_eth);
2244 : 0 : set_eth->head.jump_id = NFP_FL_ACTION_OPCODE_SET_ETHERNET;
2245 : 0 : set_eth->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2246 : 0 : set_eth->reserved = 0;
2247 : :
2248 : 0 : set_mac = action->conf;
2249 [ # # ]: 0 : if (mac_src_flag) {
2250 : 0 : rte_memcpy(&set_eth->eth_addr[RTE_ETHER_ADDR_LEN],
2251 [ # # ]: 0 : set_mac->mac_addr, RTE_ETHER_ADDR_LEN);
2252 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
2253 : 0 : set_eth->eth_addr_mask[RTE_ETHER_ADDR_LEN + i] = 0xff;
2254 : : } else {
2255 : 0 : rte_memcpy(&set_eth->eth_addr[0],
2256 [ # # ]: 0 : set_mac->mac_addr, RTE_ETHER_ADDR_LEN);
2257 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
2258 : 0 : set_eth->eth_addr_mask[i] = 0xff;
2259 : : }
2260 : 0 : }
2261 : :
2262 : : static void
2263 : : nfp_flow_action_pop_vlan(char *act_data,
2264 : : struct nfp_fl_rule_metadata *nfp_flow_meta)
2265 : : {
2266 : : size_t act_size;
2267 : : struct nfp_fl_act_pop_vlan *pop_vlan;
2268 : :
2269 : : act_size = sizeof(struct nfp_fl_act_pop_vlan);
2270 : : pop_vlan = (struct nfp_fl_act_pop_vlan *)act_data;
2271 : 0 : pop_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_POP_VLAN;
2272 : 0 : pop_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2273 : 0 : pop_vlan->reserved = 0;
2274 : :
2275 : 0 : nfp_flow_meta->shortcut = rte_cpu_to_be_32(NFP_FL_SC_ACT_POPV);
2276 : : }
2277 : :
2278 : : static void
2279 : : nfp_flow_action_set_ip(char *act_data,
2280 : : const struct rte_flow_action *action,
2281 : : bool ip_src_flag,
2282 : : bool ip_set_flag)
2283 : : {
2284 : : size_t act_size;
2285 : : struct nfp_fl_act_set_ip4_addrs *set_ip;
2286 : : const struct rte_flow_action_set_ipv4 *set_ipv4;
2287 : :
2288 [ # # # # ]: 0 : if (ip_set_flag)
2289 : 0 : set_ip = (struct nfp_fl_act_set_ip4_addrs *)act_data - 1;
2290 : : else
2291 : : set_ip = (struct nfp_fl_act_set_ip4_addrs *)act_data;
2292 : :
2293 : : act_size = sizeof(struct nfp_fl_act_set_ip4_addrs);
2294 : 0 : set_ip->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
2295 : 0 : set_ip->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2296 : 0 : set_ip->reserved = 0;
2297 : :
2298 : 0 : set_ipv4 = action->conf;
2299 : : if (ip_src_flag) {
2300 : 0 : set_ip->ipv4_src = set_ipv4->ipv4_addr;
2301 : 0 : set_ip->ipv4_src_mask = RTE_BE32(0xffffffff);
2302 : : } else {
2303 : 0 : set_ip->ipv4_dst = set_ipv4->ipv4_addr;
2304 : 0 : set_ip->ipv4_dst_mask = RTE_BE32(0xffffffff);
2305 : : }
2306 : : }
2307 : :
2308 : : static void
2309 : 0 : nfp_flow_action_set_ipv6(char *act_data,
2310 : : const struct rte_flow_action *action,
2311 : : bool ip_src_flag)
2312 : : {
2313 : : uint32_t i;
2314 : : rte_be32_t tmp;
2315 : : size_t act_size;
2316 : : struct nfp_fl_act_set_ipv6_addr *set_ip;
2317 : : const struct rte_flow_action_set_ipv6 *set_ipv6;
2318 : :
2319 : : set_ip = (struct nfp_fl_act_set_ipv6_addr *)act_data;
2320 : 0 : set_ipv6 = action->conf;
2321 : :
2322 [ # # ]: 0 : if (ip_src_flag)
2323 : 0 : set_ip->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_SRC;
2324 : : else
2325 : 0 : set_ip->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_DST;
2326 : :
2327 : : act_size = sizeof(struct nfp_fl_act_set_ipv6_addr);
2328 : 0 : set_ip->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2329 : 0 : set_ip->reserved = 0;
2330 : :
2331 [ # # ]: 0 : for (i = 0; i < 4; i++) {
2332 [ # # ]: 0 : rte_memcpy(&tmp, &set_ipv6->ipv6_addr[i * 4], 4);
2333 : 0 : set_ip->ipv6[i].exact = tmp;
2334 : 0 : set_ip->ipv6[i].mask = RTE_BE32(0xffffffff);
2335 : : }
2336 : 0 : }
2337 : :
2338 : : static void
2339 : : nfp_flow_action_set_tp(char *act_data,
2340 : : const struct rte_flow_action *action,
2341 : : bool tp_src_flag,
2342 : : bool tp_set_flag,
2343 : : bool tcp_flag)
2344 : : {
2345 : : size_t act_size;
2346 : : struct nfp_fl_act_set_tport *set_tp;
2347 : : const struct rte_flow_action_set_tp *set_tp_conf;
2348 : :
2349 : 0 : if (tp_set_flag)
2350 : 0 : set_tp = (struct nfp_fl_act_set_tport *)act_data - 1;
2351 : : else
2352 : : set_tp = (struct nfp_fl_act_set_tport *)act_data;
2353 : :
2354 : : act_size = sizeof(struct nfp_fl_act_set_tport);
2355 [ # # # # ]: 0 : if (tcp_flag)
2356 : 0 : set_tp->head.jump_id = NFP_FL_ACTION_OPCODE_SET_TCP;
2357 : : else
2358 : 0 : set_tp->head.jump_id = NFP_FL_ACTION_OPCODE_SET_UDP;
2359 : 0 : set_tp->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2360 : 0 : set_tp->reserved = 0;
2361 : :
2362 : 0 : set_tp_conf = action->conf;
2363 : : if (tp_src_flag) {
2364 : 0 : set_tp->src_port = set_tp_conf->port;
2365 : 0 : set_tp->src_port_mask = RTE_BE16(0xffff);
2366 : : } else {
2367 : 0 : set_tp->dst_port = set_tp_conf->port;
2368 : 0 : set_tp->dst_port_mask = RTE_BE16(0xffff);
2369 : : }
2370 : : }
2371 : :
2372 : : static int
2373 : 0 : nfp_flow_action_push_vlan(char *act_data,
2374 : : const struct rte_flow_action *action)
2375 : : {
2376 : : uint8_t pcp;
2377 : : uint16_t vid;
2378 : : size_t act_size;
2379 : : struct nfp_fl_act_push_vlan *push_vlan;
2380 : : const struct rte_flow_action_of_push_vlan *push_vlan_conf;
2381 : : const struct rte_flow_action_of_set_vlan_pcp *vlan_pcp_conf;
2382 : : const struct rte_flow_action_of_set_vlan_vid *vlan_vid_conf;
2383 : :
2384 [ # # ]: 0 : if (((action + 1)->type != RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) ||
2385 [ # # ]: 0 : ((action + 2)->type != RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID))
2386 : : return -EINVAL;
2387 : :
2388 : : act_size = sizeof(struct nfp_fl_act_push_vlan);
2389 : : push_vlan = (struct nfp_fl_act_push_vlan *)act_data;
2390 : 0 : push_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_VLAN;
2391 : 0 : push_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2392 : 0 : push_vlan->reserved = 0;
2393 : :
2394 : 0 : push_vlan_conf = action->conf;
2395 : 0 : vlan_pcp_conf = (action + 1)->conf;
2396 : 0 : vlan_vid_conf = (action + 2)->conf;
2397 : :
2398 [ # # ]: 0 : vid = rte_be_to_cpu_16(vlan_vid_conf->vlan_vid) & 0x0fff;
2399 : 0 : pcp = vlan_pcp_conf->vlan_pcp & 0x07;
2400 : 0 : push_vlan->vlan_tpid = push_vlan_conf->ethertype;
2401 [ # # ]: 0 : push_vlan->vlan_tci = rte_cpu_to_be_16(vid | (pcp << 13));
2402 : :
2403 : 0 : return 0;
2404 : : }
2405 : :
2406 : : static void
2407 : : nfp_flow_action_set_ttl(char *act_data,
2408 : : const struct rte_flow_action *action,
2409 : : bool ttl_tos_flag)
2410 : : {
2411 : : size_t act_size;
2412 : : struct nfp_fl_act_set_ip4_ttl_tos *ttl_tos;
2413 : : const struct rte_flow_action_set_ttl *ttl_conf;
2414 : :
2415 [ # # ]: 0 : if (ttl_tos_flag)
2416 : 0 : ttl_tos = (struct nfp_fl_act_set_ip4_ttl_tos *)act_data - 1;
2417 : : else
2418 : : ttl_tos = (struct nfp_fl_act_set_ip4_ttl_tos *)act_data;
2419 : :
2420 : : act_size = sizeof(struct nfp_fl_act_set_ip4_ttl_tos);
2421 : 0 : ttl_tos->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
2422 : 0 : ttl_tos->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2423 : :
2424 : 0 : ttl_conf = action->conf;
2425 : 0 : ttl_tos->ipv4_ttl = ttl_conf->ttl_value;
2426 : 0 : ttl_tos->ipv4_ttl_mask = 0xff;
2427 : 0 : ttl_tos->reserved = 0;
2428 : : }
2429 : :
2430 : : static void
2431 : : nfp_flow_action_set_hl(char *act_data,
2432 : : const struct rte_flow_action *action,
2433 : : bool tc_hl_flag)
2434 : : {
2435 : : size_t act_size;
2436 : : struct nfp_fl_act_set_ipv6_tc_hl_fl *tc_hl;
2437 : : const struct rte_flow_action_set_ttl *ttl_conf;
2438 : :
2439 [ # # ]: 0 : if (tc_hl_flag)
2440 : 0 : tc_hl = (struct nfp_fl_act_set_ipv6_tc_hl_fl *)act_data - 1;
2441 : : else
2442 : : tc_hl = (struct nfp_fl_act_set_ipv6_tc_hl_fl *)act_data;
2443 : :
2444 : : act_size = sizeof(struct nfp_fl_act_set_ipv6_tc_hl_fl);
2445 : 0 : tc_hl->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL;
2446 : 0 : tc_hl->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2447 : :
2448 : 0 : ttl_conf = action->conf;
2449 : 0 : tc_hl->ipv6_hop_limit = ttl_conf->ttl_value;
2450 : 0 : tc_hl->ipv6_hop_limit_mask = 0xff;
2451 : 0 : tc_hl->reserved = 0;
2452 : : }
2453 : :
2454 : : static void
2455 : : nfp_flow_action_set_tos(char *act_data,
2456 : : const struct rte_flow_action *action,
2457 : : bool ttl_tos_flag)
2458 : : {
2459 : : size_t act_size;
2460 : : struct nfp_fl_act_set_ip4_ttl_tos *ttl_tos;
2461 : : const struct rte_flow_action_set_dscp *tos_conf;
2462 : :
2463 [ # # ]: 0 : if (ttl_tos_flag)
2464 : 0 : ttl_tos = (struct nfp_fl_act_set_ip4_ttl_tos *)act_data - 1;
2465 : : else
2466 : : ttl_tos = (struct nfp_fl_act_set_ip4_ttl_tos *)act_data;
2467 : :
2468 : : act_size = sizeof(struct nfp_fl_act_set_ip4_ttl_tos);
2469 : 0 : ttl_tos->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
2470 : 0 : ttl_tos->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2471 : :
2472 : 0 : tos_conf = action->conf;
2473 : 0 : ttl_tos->ipv4_tos = tos_conf->dscp;
2474 : 0 : ttl_tos->ipv4_tos_mask = 0xff;
2475 : 0 : ttl_tos->reserved = 0;
2476 : : }
2477 : :
2478 : : static void
2479 : : nfp_flow_action_set_tc(char *act_data,
2480 : : const struct rte_flow_action *action,
2481 : : bool tc_hl_flag)
2482 : : {
2483 : : size_t act_size;
2484 : : struct nfp_fl_act_set_ipv6_tc_hl_fl *tc_hl;
2485 : : const struct rte_flow_action_set_dscp *tos_conf;
2486 : :
2487 [ # # ]: 0 : if (tc_hl_flag)
2488 : 0 : tc_hl = (struct nfp_fl_act_set_ipv6_tc_hl_fl *)act_data - 1;
2489 : : else
2490 : : tc_hl = (struct nfp_fl_act_set_ipv6_tc_hl_fl *)act_data;
2491 : :
2492 : : act_size = sizeof(struct nfp_fl_act_set_ipv6_tc_hl_fl);
2493 : 0 : tc_hl->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV6_TC_HL_FL;
2494 : 0 : tc_hl->head.len_lw = act_size >> NFP_FL_LW_SIZ;
2495 : :
2496 : 0 : tos_conf = action->conf;
2497 : 0 : tc_hl->ipv6_tc = tos_conf->dscp;
2498 : 0 : tc_hl->ipv6_tc_mask = 0xff;
2499 : 0 : tc_hl->reserved = 0;
2500 : : }
2501 : :
2502 : : static void
2503 : : nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
2504 : : rte_be32_t ipv4_dst)
2505 : : {
2506 : 0 : pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
2507 : 0 : pre_tun->head.len_lw = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
2508 : 0 : pre_tun->ipv4_dst = ipv4_dst;
2509 : : }
2510 : :
2511 : : static void
2512 : : nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
2513 : : const uint8_t ipv6_dst[])
2514 : : {
2515 : 0 : pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
2516 : 0 : pre_tun->head.len_lw = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
2517 : 0 : pre_tun->flags = rte_cpu_to_be_16(NFP_FL_PRE_TUN_IPV6);
2518 : 0 : memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
2519 : : }
2520 : :
2521 : : static void
2522 : : nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
2523 : : enum nfp_flower_tun_type tun_type,
2524 : : uint64_t tun_id,
2525 : : uint8_t ttl,
2526 : : uint8_t tos)
2527 : : {
2528 : : /* Currently only support one pre-tunnel, so index is always 0. */
2529 : : uint8_t pretun_idx = 0;
2530 : : uint32_t tun_type_index;
2531 : :
2532 : : tun_type_index = ((tun_type << 4) & 0xf0) | (pretun_idx & 0x07);
2533 : :
2534 : 0 : set_tun->head.jump_id = NFP_FL_ACTION_OPCODE_SET_TUNNEL;
2535 : 0 : set_tun->head.len_lw = sizeof(struct nfp_fl_act_set_tun) >> NFP_FL_LW_SIZ;
2536 : 0 : set_tun->tun_type_index = rte_cpu_to_be_32(tun_type_index);
2537 : 0 : set_tun->tun_id = rte_cpu_to_be_64(tun_id);
2538 : 0 : set_tun->ttl = ttl;
2539 : 0 : set_tun->tos = tos;
2540 : : }
2541 : :
2542 : : static int
2543 : 0 : nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
2544 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2545 : : struct nfp_fl_tun *tun,
2546 : : const struct rte_ether_hdr *eth,
2547 : : const struct rte_flow_item_ipv4 *ipv4)
2548 : : {
2549 : : struct nfp_fl_tun *tmp;
2550 : : struct nfp_flow_priv *priv;
2551 : : struct nfp_flower_in_port *port;
2552 : : struct nfp_flower_cmsg_tun_neigh_v4 payload;
2553 : :
2554 : 0 : tun->payload.v6_flag = 0;
2555 : 0 : tun->payload.dst.dst_ipv4 = ipv4->hdr.dst_addr;
2556 : 0 : tun->payload.src.src_ipv4 = ipv4->hdr.src_addr;
2557 : 0 : memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2558 : 0 : memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2559 : :
2560 : 0 : tun->ref_cnt = 1;
2561 : 0 : priv = app_fw_flower->flow_priv;
2562 [ # # ]: 0 : LIST_FOREACH(tmp, &priv->nn_list, next) {
2563 [ # # ]: 0 : if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
2564 : 0 : tmp->ref_cnt++;
2565 : 0 : return 0;
2566 : : }
2567 : : }
2568 : :
2569 [ # # ]: 0 : LIST_INSERT_HEAD(&priv->nn_list, tun, next);
2570 : :
2571 : : port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
2572 : : sizeof(struct nfp_fl_rule_metadata) +
2573 : : sizeof(struct nfp_flower_meta_tci));
2574 : :
2575 : : memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
2576 : 0 : payload.dst_ipv4 = ipv4->hdr.dst_addr;
2577 : 0 : payload.src_ipv4 = ipv4->hdr.src_addr;
2578 : : memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2579 : : memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2580 : 0 : payload.common.port_id = port->in_port;
2581 : :
2582 : 0 : return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
2583 : : }
2584 : :
2585 : : static int
2586 : 0 : nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
2587 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2588 : : struct rte_flow *nfp_flow)
2589 : : {
2590 : : bool exists = false;
2591 : : struct nfp_fl_tun *tmp;
2592 : : struct nfp_fl_tun *tun;
2593 : : struct nfp_flow_priv *priv;
2594 : : struct nfp_flower_ipv4 *ipv4;
2595 : : struct nfp_flower_mac_mpls *eth;
2596 : : struct nfp_flower_in_port *port;
2597 : : struct nfp_flower_meta_tci *meta_tci;
2598 : : struct nfp_flower_cmsg_tun_neigh_v4 payload;
2599 : :
2600 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
2601 : : port = (struct nfp_flower_in_port *)(meta_tci + 1);
2602 : : eth = (struct nfp_flower_mac_mpls *)(port + 1);
2603 : :
2604 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP) != 0)
2605 : 0 : ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
2606 : : sizeof(struct nfp_flower_mac_mpls) +
2607 : : sizeof(struct nfp_flower_tp_ports));
2608 : : else
2609 : 0 : ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
2610 : : sizeof(struct nfp_flower_mac_mpls));
2611 : :
2612 : 0 : tun = &nfp_flow->tun;
2613 : 0 : tun->payload.v6_flag = 0;
2614 : 0 : tun->payload.dst.dst_ipv4 = ipv4->ipv4_src;
2615 : 0 : tun->payload.src.src_ipv4 = ipv4->ipv4_dst;
2616 : 0 : memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
2617 : 0 : memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
2618 : :
2619 : 0 : tun->ref_cnt = 1;
2620 : 0 : priv = app_fw_flower->flow_priv;
2621 [ # # ]: 0 : LIST_FOREACH(tmp, &priv->nn_list, next) {
2622 [ # # ]: 0 : if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
2623 [ # # ]: 0 : tmp->ref_cnt++;
2624 : : exists = true;
2625 : : break;
2626 : : }
2627 : : }
2628 : :
2629 : : if (exists) {
2630 [ # # ]: 0 : if (!nfp_flower_support_decap_v2(app_fw_flower))
2631 : : return 0;
2632 : : } else {
2633 [ # # ]: 0 : LIST_INSERT_HEAD(&priv->nn_list, tun, next);
2634 : : }
2635 : :
2636 : : memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
2637 : 0 : payload.dst_ipv4 = ipv4->ipv4_src;
2638 : 0 : payload.src_ipv4 = ipv4->ipv4_dst;
2639 : : memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
2640 : : memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
2641 [ # # ]: 0 : payload.common.port_id = port->in_port;
2642 : :
2643 [ # # ]: 0 : if (nfp_flower_support_decap_v2(app_fw_flower)) {
2644 [ # # ]: 0 : if (meta_tci->tci != 0) {
2645 : 0 : payload.ext.vlan_tci = meta_tci->tci;
2646 : 0 : payload.ext.vlan_tpid = RTE_BE16(0x88a8);
2647 : : } else {
2648 : 0 : payload.ext.vlan_tci = RTE_BE16(0xffff);
2649 : 0 : payload.ext.vlan_tpid = RTE_BE16(0xffff);
2650 : : }
2651 : 0 : payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
2652 : : }
2653 : :
2654 : 0 : return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
2655 : : }
2656 : :
2657 : : static int
2658 : 0 : nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
2659 : : rte_be32_t ipv4)
2660 : : {
2661 : : struct nfp_flower_cmsg_tun_neigh_v4 payload;
2662 : :
2663 : : memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
2664 : 0 : payload.dst_ipv4 = ipv4;
2665 : :
2666 : 0 : return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
2667 : : }
2668 : :
2669 : : static int
2670 : 0 : nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
2671 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2672 : : struct nfp_fl_tun *tun,
2673 : : const struct rte_ether_hdr *eth,
2674 : : const struct rte_flow_item_ipv6 *ipv6)
2675 : : {
2676 : : struct nfp_fl_tun *tmp;
2677 : : struct nfp_flow_priv *priv;
2678 : : struct nfp_flower_in_port *port;
2679 : : struct nfp_flower_cmsg_tun_neigh_v6 payload;
2680 : :
2681 : 0 : tun->payload.v6_flag = 1;
2682 : 0 : memcpy(tun->payload.dst.dst_ipv6, ipv6->hdr.dst_addr, sizeof(tun->payload.dst.dst_ipv6));
2683 : 0 : memcpy(tun->payload.src.src_ipv6, ipv6->hdr.src_addr, sizeof(tun->payload.src.src_ipv6));
2684 : 0 : memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2685 : 0 : memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2686 : :
2687 : 0 : tun->ref_cnt = 1;
2688 : 0 : priv = app_fw_flower->flow_priv;
2689 [ # # ]: 0 : LIST_FOREACH(tmp, &priv->nn_list, next) {
2690 [ # # ]: 0 : if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
2691 : 0 : tmp->ref_cnt++;
2692 : 0 : return 0;
2693 : : }
2694 : : }
2695 : :
2696 [ # # ]: 0 : LIST_INSERT_HEAD(&priv->nn_list, tun, next);
2697 : :
2698 : : port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
2699 : : sizeof(struct nfp_fl_rule_metadata) +
2700 : : sizeof(struct nfp_flower_meta_tci));
2701 : :
2702 : : memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
2703 : : memcpy(payload.dst_ipv6, ipv6->hdr.dst_addr, sizeof(payload.dst_ipv6));
2704 : : memcpy(payload.src_ipv6, ipv6->hdr.src_addr, sizeof(payload.src_ipv6));
2705 : : memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2706 : : memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
2707 : 0 : payload.common.port_id = port->in_port;
2708 : :
2709 : 0 : return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
2710 : : }
2711 : :
2712 : : static int
2713 : 0 : nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
2714 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2715 : : struct rte_flow *nfp_flow)
2716 : : {
2717 : : bool exists = false;
2718 : : struct nfp_fl_tun *tmp;
2719 : : struct nfp_fl_tun *tun;
2720 : : struct nfp_flow_priv *priv;
2721 : : struct nfp_flower_ipv6 *ipv6;
2722 : : struct nfp_flower_mac_mpls *eth;
2723 : : struct nfp_flower_in_port *port;
2724 : : struct nfp_flower_meta_tci *meta_tci;
2725 : : struct nfp_flower_cmsg_tun_neigh_v6 payload;
2726 : :
2727 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
2728 : : port = (struct nfp_flower_in_port *)(meta_tci + 1);
2729 : : eth = (struct nfp_flower_mac_mpls *)(port + 1);
2730 : :
2731 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP) != 0)
2732 : 0 : ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
2733 : : sizeof(struct nfp_flower_mac_mpls) +
2734 : : sizeof(struct nfp_flower_tp_ports));
2735 : : else
2736 : 0 : ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
2737 : : sizeof(struct nfp_flower_mac_mpls));
2738 : :
2739 : 0 : tun = &nfp_flow->tun;
2740 : 0 : tun->payload.v6_flag = 1;
2741 : 0 : memcpy(tun->payload.dst.dst_ipv6, ipv6->ipv6_src, sizeof(tun->payload.dst.dst_ipv6));
2742 : 0 : memcpy(tun->payload.src.src_ipv6, ipv6->ipv6_dst, sizeof(tun->payload.src.src_ipv6));
2743 : 0 : memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
2744 : 0 : memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
2745 : :
2746 : 0 : tun->ref_cnt = 1;
2747 : 0 : priv = app_fw_flower->flow_priv;
2748 [ # # ]: 0 : LIST_FOREACH(tmp, &priv->nn_list, next) {
2749 [ # # ]: 0 : if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
2750 [ # # ]: 0 : tmp->ref_cnt++;
2751 : : exists = true;
2752 : : break;
2753 : : }
2754 : : }
2755 : :
2756 : : if (exists) {
2757 [ # # ]: 0 : if (!nfp_flower_support_decap_v2(app_fw_flower))
2758 : : return 0;
2759 : : } else {
2760 [ # # ]: 0 : LIST_INSERT_HEAD(&priv->nn_list, tun, next);
2761 : : }
2762 : :
2763 : : memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
2764 : : memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
2765 : : memcpy(payload.src_ipv6, ipv6->ipv6_dst, sizeof(payload.src_ipv6));
2766 : : memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
2767 : : memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
2768 [ # # ]: 0 : payload.common.port_id = port->in_port;
2769 : :
2770 [ # # ]: 0 : if (nfp_flower_support_decap_v2(app_fw_flower)) {
2771 [ # # ]: 0 : if (meta_tci->tci != 0) {
2772 : 0 : payload.ext.vlan_tci = meta_tci->tci;
2773 : 0 : payload.ext.vlan_tpid = RTE_BE16(0x88a8);
2774 : : } else {
2775 : 0 : payload.ext.vlan_tci = RTE_BE16(0xffff);
2776 : 0 : payload.ext.vlan_tpid = RTE_BE16(0xffff);
2777 : : }
2778 : 0 : payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
2779 : : }
2780 : :
2781 : 0 : return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
2782 : : }
2783 : :
2784 : : static int
2785 : 0 : nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
2786 : : uint8_t *ipv6)
2787 : : {
2788 : : struct nfp_flower_cmsg_tun_neigh_v6 payload;
2789 : :
2790 : : memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
2791 : : memcpy(payload.dst_ipv6, ipv6, sizeof(payload.dst_ipv6));
2792 : :
2793 : 0 : return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
2794 : : }
2795 : :
2796 : : static int
2797 : 0 : nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
2798 : : struct rte_flow *nfp_flow,
2799 : : bool decap_flag)
2800 : : {
2801 : : int ret;
2802 : : bool flag = false;
2803 : : struct nfp_fl_tun *tmp;
2804 : : struct nfp_fl_tun *tun;
2805 : : struct nfp_flower_in_port *port;
2806 : :
2807 : : tun = &nfp_flow->tun;
2808 [ # # ]: 0 : LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
2809 : 0 : ret = memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry));
2810 [ # # ]: 0 : if (ret == 0) {
2811 : 0 : tmp->ref_cnt--;
2812 : : flag = true;
2813 : : break;
2814 : : }
2815 : : }
2816 : :
2817 : : if (!flag) {
2818 : 0 : PMD_DRV_LOG(DEBUG, "Can't find nn entry in the nn list");
2819 : 0 : return -EINVAL;
2820 : : }
2821 : :
2822 [ # # ]: 0 : if (tmp->ref_cnt == 0) {
2823 [ # # ]: 0 : LIST_REMOVE(tmp, next);
2824 [ # # ]: 0 : if (tmp->payload.v6_flag != 0) {
2825 : 0 : return nfp_flower_del_tun_neigh_v6(app_fw_flower,
2826 : 0 : tmp->payload.dst.dst_ipv6);
2827 : : } else {
2828 : 0 : return nfp_flower_del_tun_neigh_v4(app_fw_flower,
2829 : : tmp->payload.dst.dst_ipv4);
2830 : : }
2831 : : }
2832 : :
2833 [ # # ]: 0 : if (!decap_flag)
2834 : : return 0;
2835 : :
2836 : 0 : port = (struct nfp_flower_in_port *)(nfp_flow->payload.unmasked_data +
2837 : : sizeof(struct nfp_fl_rule_metadata) +
2838 : : sizeof(struct nfp_flower_meta_tci));
2839 : :
2840 [ # # ]: 0 : if (tmp->payload.v6_flag != 0) {
2841 : : struct nfp_flower_cmsg_tun_neigh_v6 nn_v6;
2842 : : memset(&nn_v6, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
2843 : : memcpy(nn_v6.dst_ipv6, tmp->payload.dst.dst_ipv6, sizeof(nn_v6.dst_ipv6));
2844 : : memcpy(nn_v6.src_ipv6, tmp->payload.src.src_ipv6, sizeof(nn_v6.src_ipv6));
2845 : : memcpy(nn_v6.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
2846 : : memcpy(nn_v6.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
2847 : 0 : nn_v6.common.port_id = port->in_port;
2848 : :
2849 : 0 : ret = nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &nn_v6);
2850 : : } else {
2851 : : struct nfp_flower_cmsg_tun_neigh_v4 nn_v4;
2852 : : memset(&nn_v4, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
2853 : 0 : nn_v4.dst_ipv4 = tmp->payload.dst.dst_ipv4;
2854 : 0 : nn_v4.src_ipv4 = tmp->payload.src.src_ipv4;
2855 : : memcpy(nn_v4.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
2856 : : memcpy(nn_v4.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
2857 : 0 : nn_v4.common.port_id = port->in_port;
2858 : :
2859 : 0 : ret = nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &nn_v4);
2860 : : }
2861 : :
2862 [ # # ]: 0 : if (ret != 0) {
2863 : 0 : PMD_DRV_LOG(DEBUG, "Failed to send the nn entry");
2864 : 0 : return -EINVAL;
2865 : : }
2866 : :
2867 : : return 0;
2868 : : }
2869 : :
2870 : : static int
2871 : 0 : nfp_flow_action_vxlan_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
2872 : : char *act_data,
2873 : : char *actions,
2874 : : const struct vxlan_data *vxlan_data,
2875 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2876 : : struct nfp_fl_tun *tun)
2877 : : {
2878 : : uint64_t tun_id;
2879 : : struct nfp_fl_act_pre_tun *pre_tun;
2880 : : struct nfp_fl_act_set_tun *set_tun;
2881 : : const struct rte_flow_item_eth *eth;
2882 : : const struct rte_flow_item_ipv4 *ipv4;
2883 : : const struct rte_flow_item_vxlan *vxlan;
2884 : : size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
2885 : : size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
2886 : :
2887 : 0 : eth = vxlan_data->items[0].spec;
2888 : 0 : ipv4 = vxlan_data->items[1].spec;
2889 [ # # ]: 0 : vxlan = vxlan_data->items[3].spec;
2890 : :
2891 : : pre_tun = (struct nfp_fl_act_pre_tun *)actions;
2892 : : memset(pre_tun, 0, act_pre_size);
2893 : 0 : nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
2894 : :
2895 : 0 : set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
2896 : : memset(set_tun, 0, act_set_size);
2897 [ # # ]: 0 : tun_id = rte_be_to_cpu_32(vxlan->hdr.vx_vni) >> 8;
2898 : : nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, tun_id,
2899 [ # # ]: 0 : ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
2900 : 0 : set_tun->tun_flags = vxlan->hdr.vx_flags;
2901 : :
2902 : : /* Send the tunnel neighbor cmsg to fw */
2903 : 0 : return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
2904 : : tun, ð->hdr, ipv4);
2905 : : }
2906 : :
2907 : : static int
2908 : 0 : nfp_flow_action_vxlan_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
2909 : : char *act_data,
2910 : : char *actions,
2911 : : const struct vxlan_data *vxlan_data,
2912 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2913 : : struct nfp_fl_tun *tun)
2914 : : {
2915 : : uint8_t tos;
2916 : : uint64_t tun_id;
2917 : : struct nfp_fl_act_pre_tun *pre_tun;
2918 : : struct nfp_fl_act_set_tun *set_tun;
2919 : : const struct rte_flow_item_eth *eth;
2920 : : const struct rte_flow_item_ipv6 *ipv6;
2921 : : const struct rte_flow_item_vxlan *vxlan;
2922 : : size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
2923 : : size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
2924 : :
2925 : 0 : eth = vxlan_data->items[0].spec;
2926 : 0 : ipv6 = vxlan_data->items[1].spec;
2927 [ # # ]: 0 : vxlan = vxlan_data->items[3].spec;
2928 : :
2929 : : pre_tun = (struct nfp_fl_act_pre_tun *)actions;
2930 : : memset(pre_tun, 0, act_pre_size);
2931 [ # # ]: 0 : nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
2932 : :
2933 : 0 : set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
2934 : : memset(set_tun, 0, act_set_size);
2935 [ # # ]: 0 : tun_id = rte_be_to_cpu_32(vxlan->hdr.vx_vni) >> 8;
2936 [ # # ]: 0 : tos = rte_be_to_cpu_32(ipv6->hdr.vtc_flow) >> RTE_IPV6_HDR_TC_SHIFT;
2937 : : nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, tun_id,
2938 [ # # ]: 0 : ipv6->hdr.hop_limits, tos);
2939 : 0 : set_tun->tun_flags = vxlan->hdr.vx_flags;
2940 : :
2941 : : /* Send the tunnel neighbor cmsg to fw */
2942 : 0 : return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
2943 : : tun, ð->hdr, ipv6);
2944 : : }
2945 : :
2946 : : static int
2947 : 0 : nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
2948 : : char *act_data,
2949 : : char *actions,
2950 : : const struct rte_flow_action *action,
2951 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
2952 : : struct nfp_fl_tun *tun)
2953 : : {
2954 : : size_t act_len;
2955 : : size_t act_pre_size;
2956 : : const struct vxlan_data *vxlan_data;
2957 : :
2958 : 0 : vxlan_data = action->conf;
2959 [ # # ]: 0 : if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
2960 [ # # ]: 0 : (vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 &&
2961 : 0 : vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV6) ||
2962 [ # # ]: 0 : vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
2963 [ # # ]: 0 : vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
2964 [ # # ]: 0 : vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
2965 : 0 : PMD_DRV_LOG(ERR, "Not an valid vxlan action conf.");
2966 : 0 : return -EINVAL;
2967 : : }
2968 : :
2969 : : /*
2970 : : * Pre_tunnel action must be the first on the action list.
2971 : : * If other actions already exist, they need to be pushed forward.
2972 : : */
2973 : 0 : act_len = act_data - actions;
2974 [ # # ]: 0 : if (act_len != 0) {
2975 : : act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
2976 : 0 : memmove(actions + act_pre_size, actions, act_len);
2977 : : }
2978 : :
2979 [ # # ]: 0 : if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
2980 : 0 : return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
2981 : : actions, vxlan_data, nfp_flow_meta, tun);
2982 : : else
2983 : 0 : return nfp_flow_action_vxlan_encap_v6(app_fw_flower, act_data,
2984 : : actions, vxlan_data, nfp_flow_meta, tun);
2985 : : }
2986 : :
2987 : : static struct nfp_pre_tun_entry *
2988 : 0 : nfp_pre_tun_table_search(struct nfp_flow_priv *priv,
2989 : : char *hash_data,
2990 : : uint32_t hash_len)
2991 : : {
2992 : : int index;
2993 : : uint32_t hash_key;
2994 : : struct nfp_pre_tun_entry *mac_index;
2995 : :
2996 : 0 : hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
2997 : 0 : index = rte_hash_lookup_data(priv->pre_tun_table, &hash_key, (void **)&mac_index);
2998 [ # # ]: 0 : if (index < 0) {
2999 : 0 : PMD_DRV_LOG(DEBUG, "Data NOT found in the hash table");
3000 : 0 : return NULL;
3001 : : }
3002 : :
3003 : 0 : return mac_index;
3004 : : }
3005 : :
3006 : : static bool
3007 : 0 : nfp_pre_tun_table_add(struct nfp_flow_priv *priv,
3008 : : char *hash_data,
3009 : : uint32_t hash_len)
3010 : : {
3011 : : int ret;
3012 : : uint32_t hash_key;
3013 : :
3014 : 0 : hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
3015 : 0 : ret = rte_hash_add_key_data(priv->pre_tun_table, &hash_key, hash_data);
3016 [ # # ]: 0 : if (ret != 0) {
3017 : 0 : PMD_DRV_LOG(ERR, "Add to pre tunnel table failed");
3018 : 0 : return false;
3019 : : }
3020 : :
3021 : : return true;
3022 : : }
3023 : :
3024 : : static bool
3025 : 0 : nfp_pre_tun_table_delete(struct nfp_flow_priv *priv,
3026 : : char *hash_data,
3027 : : uint32_t hash_len)
3028 : : {
3029 : : int ret;
3030 : : uint32_t hash_key;
3031 : :
3032 : 0 : hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
3033 : 0 : ret = rte_hash_del_key(priv->pre_tun_table, &hash_key);
3034 [ # # ]: 0 : if (ret < 0) {
3035 : 0 : PMD_DRV_LOG(ERR, "Delete from pre tunnel table failed");
3036 : 0 : return false;
3037 : : }
3038 : :
3039 : : return true;
3040 : : }
3041 : :
3042 : : static int
3043 : 0 : nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
3044 : : uint16_t *index)
3045 : : {
3046 : : uint16_t i;
3047 : : uint32_t entry_size;
3048 : : uint16_t mac_index = 1;
3049 : : struct nfp_flow_priv *priv;
3050 : : struct nfp_pre_tun_entry *entry;
3051 : : struct nfp_pre_tun_entry *find_entry;
3052 : :
3053 : 0 : priv = repr->app_fw_flower->flow_priv;
3054 [ # # ]: 0 : if (priv->pre_tun_cnt >= NFP_TUN_PRE_TUN_RULE_LIMIT) {
3055 : 0 : PMD_DRV_LOG(ERR, "Pre tunnel table has full");
3056 : 0 : return -EINVAL;
3057 : : }
3058 : :
3059 : : entry_size = sizeof(struct nfp_pre_tun_entry);
3060 : 0 : entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
3061 [ # # ]: 0 : if (entry == NULL) {
3062 : 0 : PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
3063 : 0 : return -ENOMEM;
3064 : : }
3065 : :
3066 : 0 : entry->ref_cnt = 1U;
3067 : : rte_ether_addr_copy(&repr->mac_addr, &entry->mac_addr);
3068 : :
3069 : : /* 0 is considered a failed match */
3070 [ # # ]: 0 : for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
3071 [ # # ]: 0 : if (priv->pre_tun_bitmap[i] == 0)
3072 : 0 : continue;
3073 : :
3074 : 0 : entry->mac_index = i;
3075 : 0 : find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
3076 [ # # ]: 0 : if (find_entry != NULL) {
3077 : 0 : find_entry->ref_cnt++;
3078 : 0 : *index = find_entry->mac_index;
3079 : 0 : rte_free(entry);
3080 : 0 : return 0;
3081 : : }
3082 : : }
3083 : :
3084 [ # # ]: 0 : for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
3085 [ # # ]: 0 : if (priv->pre_tun_bitmap[i] == 0) {
3086 : 0 : priv->pre_tun_bitmap[i] = 1U;
3087 : : mac_index = i;
3088 : 0 : break;
3089 : : }
3090 : : }
3091 : :
3092 : 0 : entry->mac_index = mac_index;
3093 [ # # ]: 0 : if (!nfp_pre_tun_table_add(priv, (char *)entry, entry_size)) {
3094 : 0 : rte_free(entry);
3095 : 0 : return -EINVAL;
3096 : : }
3097 : :
3098 : 0 : *index = entry->mac_index;
3099 : 0 : priv->pre_tun_cnt++;
3100 : :
3101 : 0 : return 0;
3102 : : }
3103 : :
3104 : : static int
3105 : 0 : nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
3106 : : struct rte_flow *nfp_flow)
3107 : : {
3108 : : uint16_t i;
3109 : : int ret = 0;
3110 : : uint32_t entry_size;
3111 : : uint16_t nfp_mac_idx;
3112 : : struct nfp_flow_priv *priv;
3113 : : struct nfp_pre_tun_entry *entry;
3114 : : struct nfp_pre_tun_entry *find_entry;
3115 : : struct nfp_fl_rule_metadata *nfp_flow_meta;
3116 : :
3117 : 0 : priv = repr->app_fw_flower->flow_priv;
3118 [ # # ]: 0 : if (priv->pre_tun_cnt == 1)
3119 : : return 0;
3120 : :
3121 : : entry_size = sizeof(struct nfp_pre_tun_entry);
3122 : 0 : entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
3123 [ # # ]: 0 : if (entry == NULL) {
3124 : 0 : PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
3125 : 0 : return -ENOMEM;
3126 : : }
3127 : :
3128 : 0 : entry->ref_cnt = 1U;
3129 : : rte_ether_addr_copy(&repr->mac_addr, &entry->mac_addr);
3130 : :
3131 : : /* 0 is considered a failed match */
3132 [ # # ]: 0 : for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
3133 [ # # ]: 0 : if (priv->pre_tun_bitmap[i] == 0)
3134 : 0 : continue;
3135 : :
3136 : 0 : entry->mac_index = i;
3137 : 0 : find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
3138 [ # # ]: 0 : if (find_entry != NULL) {
3139 : 0 : find_entry->ref_cnt--;
3140 [ # # ]: 0 : if (find_entry->ref_cnt != 0)
3141 : 0 : goto free_entry;
3142 : :
3143 : 0 : priv->pre_tun_bitmap[i] = 0;
3144 : 0 : break;
3145 : : }
3146 : : }
3147 : :
3148 : 0 : nfp_flow_meta = nfp_flow->payload.meta;
3149 : 0 : nfp_mac_idx = (find_entry->mac_index << 8) |
3150 : 0 : NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
3151 : : NFP_TUN_PRE_TUN_IDX_BIT;
3152 [ # # ]: 0 : if (nfp_flow->tun.payload.v6_flag != 0)
3153 : 0 : nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
3154 : :
3155 : 0 : ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
3156 : : nfp_mac_idx, true);
3157 [ # # ]: 0 : if (ret != 0) {
3158 : 0 : PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
3159 : : ret = -EINVAL;
3160 : 0 : goto free_entry;
3161 : : }
3162 : :
3163 [ # # ]: 0 : if (!nfp_flower_support_decap_v2(repr->app_fw_flower)) {
3164 : 0 : ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
3165 : : nfp_mac_idx, true);
3166 [ # # ]: 0 : if (ret != 0) {
3167 : 0 : PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
3168 : : ret = -EINVAL;
3169 : 0 : goto free_entry;
3170 : : }
3171 : : }
3172 : :
3173 : 0 : find_entry->ref_cnt = 1U;
3174 [ # # ]: 0 : if (!nfp_pre_tun_table_delete(priv, (char *)find_entry, entry_size)) {
3175 : 0 : PMD_DRV_LOG(ERR, "Delete entry from pre tunnel table failed");
3176 : : ret = -EINVAL;
3177 : 0 : goto free_entry;
3178 : : }
3179 : :
3180 : 0 : rte_free(entry);
3181 : 0 : rte_free(find_entry);
3182 : 0 : priv->pre_tun_cnt--;
3183 : :
3184 : 0 : free_entry:
3185 : 0 : rte_free(entry);
3186 : :
3187 : 0 : return ret;
3188 : : }
3189 : :
3190 : : static int
3191 : 0 : nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
3192 : : const struct rte_flow_action *action,
3193 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
3194 : : struct rte_flow *nfp_flow)
3195 : : {
3196 : : int ret;
3197 : 0 : uint16_t nfp_mac_idx = 0;
3198 : : struct nfp_flower_meta_tci *meta_tci;
3199 : : struct nfp_app_fw_flower *app_fw_flower;
3200 : :
3201 : 0 : ret = nfp_pre_tun_table_check_add(repr, &nfp_mac_idx);
3202 [ # # ]: 0 : if (ret != 0) {
3203 : 0 : PMD_DRV_LOG(ERR, "Pre tunnel table add failed");
3204 : 0 : return -EINVAL;
3205 : : }
3206 : :
3207 : 0 : nfp_mac_idx = (nfp_mac_idx << 8) |
3208 : 0 : NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
3209 : : NFP_TUN_PRE_TUN_IDX_BIT;
3210 [ # # ]: 0 : if (action->conf != NULL)
3211 : 0 : nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
3212 : :
3213 : 0 : app_fw_flower = repr->app_fw_flower;
3214 : 0 : ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
3215 : : nfp_mac_idx, false);
3216 [ # # ]: 0 : if (ret != 0) {
3217 : 0 : PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
3218 : 0 : return -EINVAL;
3219 : : }
3220 : :
3221 [ # # ]: 0 : if (!nfp_flower_support_decap_v2(app_fw_flower)) {
3222 : 0 : ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
3223 : : nfp_mac_idx, false);
3224 [ # # ]: 0 : if (ret != 0) {
3225 : 0 : PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
3226 : 0 : return -EINVAL;
3227 : : }
3228 : : }
3229 : :
3230 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
3231 [ # # ]: 0 : if ((meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) != 0)
3232 : 0 : return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
3233 : : else
3234 : 0 : return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
3235 : : }
3236 : :
3237 : : static int
3238 : 0 : nfp_flow_action_geneve_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
3239 : : char *act_data,
3240 : : char *actions,
3241 : : const struct rte_flow_action_raw_encap *raw_encap,
3242 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
3243 : : struct nfp_fl_tun *tun)
3244 : : {
3245 : : uint64_t tun_id;
3246 : : const struct rte_ether_hdr *eth;
3247 : : struct nfp_fl_act_pre_tun *pre_tun;
3248 : : struct nfp_fl_act_set_tun *set_tun;
3249 : : const struct rte_flow_item_udp *udp;
3250 : : const struct rte_flow_item_ipv4 *ipv4;
3251 : : const struct rte_flow_item_geneve *geneve;
3252 : : size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
3253 : : size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
3254 : :
3255 : 0 : eth = (const struct rte_ether_hdr *)raw_encap->data;
3256 [ # # ]: 0 : ipv4 = (const struct rte_flow_item_ipv4 *)(eth + 1);
3257 : : udp = (const struct rte_flow_item_udp *)(ipv4 + 1);
3258 : : geneve = (const struct rte_flow_item_geneve *)(udp + 1);
3259 : :
3260 : : pre_tun = (struct nfp_fl_act_pre_tun *)actions;
3261 : : memset(pre_tun, 0, act_pre_size);
3262 : 0 : nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
3263 : :
3264 : 0 : set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
3265 : : memset(set_tun, 0, act_set_size);
3266 : 0 : tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
3267 : : nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
3268 [ # # ]: 0 : ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
3269 : 0 : set_tun->tun_proto = geneve->protocol;
3270 : :
3271 : : /* Send the tunnel neighbor cmsg to fw */
3272 : 0 : return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
3273 : : tun, eth, ipv4);
3274 : : }
3275 : :
3276 : : static int
3277 : 0 : nfp_flow_action_geneve_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
3278 : : char *act_data,
3279 : : char *actions,
3280 : : const struct rte_flow_action_raw_encap *raw_encap,
3281 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
3282 : : struct nfp_fl_tun *tun)
3283 : : {
3284 : : uint8_t tos;
3285 : : uint64_t tun_id;
3286 : : const struct rte_ether_hdr *eth;
3287 : : struct nfp_fl_act_pre_tun *pre_tun;
3288 : : struct nfp_fl_act_set_tun *set_tun;
3289 : : const struct rte_flow_item_udp *udp;
3290 : : const struct rte_flow_item_ipv6 *ipv6;
3291 : : const struct rte_flow_item_geneve *geneve;
3292 : : size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
3293 : : size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
3294 : :
3295 : 0 : eth = (const struct rte_ether_hdr *)raw_encap->data;
3296 [ # # ]: 0 : ipv6 = (const struct rte_flow_item_ipv6 *)(eth + 1);
3297 : : udp = (const struct rte_flow_item_udp *)(ipv6 + 1);
3298 : : geneve = (const struct rte_flow_item_geneve *)(udp + 1);
3299 : :
3300 : : pre_tun = (struct nfp_fl_act_pre_tun *)actions;
3301 : : memset(pre_tun, 0, act_pre_size);
3302 [ # # ]: 0 : nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
3303 : :
3304 : 0 : set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
3305 : : memset(set_tun, 0, act_set_size);
3306 [ # # ]: 0 : tos = rte_be_to_cpu_32(ipv6->hdr.vtc_flow) >> RTE_IPV6_HDR_TC_SHIFT;
3307 : 0 : tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
3308 : : nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
3309 [ # # ]: 0 : ipv6->hdr.hop_limits, tos);
3310 : 0 : set_tun->tun_proto = geneve->protocol;
3311 : :
3312 : : /* Send the tunnel neighbor cmsg to fw */
3313 : 0 : return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
3314 : : tun, eth, ipv6);
3315 : : }
3316 : :
3317 : : static int
3318 : 0 : nfp_flow_action_nvgre_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
3319 : : char *act_data,
3320 : : char *actions,
3321 : : const struct rte_flow_action_raw_encap *raw_encap,
3322 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
3323 : : struct nfp_fl_tun *tun)
3324 : : {
3325 : : uint64_t tun_id;
3326 : : const struct rte_ether_hdr *eth;
3327 : : struct nfp_fl_act_pre_tun *pre_tun;
3328 : : struct nfp_fl_act_set_tun *set_tun;
3329 : : const struct rte_flow_item_gre *gre;
3330 : : const struct rte_flow_item_ipv4 *ipv4;
3331 : : size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
3332 : : size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
3333 : :
3334 : 0 : eth = (const struct rte_ether_hdr *)raw_encap->data;
3335 : 0 : ipv4 = (const struct rte_flow_item_ipv4 *)(eth + 1);
3336 : : gre = (const struct rte_flow_item_gre *)(ipv4 + 1);
3337 [ # # ]: 0 : tun_id = rte_be_to_cpu_32(*(const rte_be32_t *)(gre + 1));
3338 : :
3339 : : pre_tun = (struct nfp_fl_act_pre_tun *)actions;
3340 : : memset(pre_tun, 0, act_pre_size);
3341 : 0 : nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
3342 : :
3343 : 0 : set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
3344 : : memset(set_tun, 0, act_set_size);
3345 : : nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, tun_id,
3346 [ # # ]: 0 : ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
3347 : 0 : set_tun->tun_proto = gre->protocol;
3348 : :
3349 : : /* Send the tunnel neighbor cmsg to fw */
3350 : 0 : return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
3351 : : tun, eth, ipv4);
3352 : : }
3353 : :
3354 : : static int
3355 : 0 : nfp_flow_action_nvgre_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
3356 : : char *act_data,
3357 : : char *actions,
3358 : : const struct rte_flow_action_raw_encap *raw_encap,
3359 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
3360 : : struct nfp_fl_tun *tun)
3361 : : {
3362 : : uint8_t tos;
3363 : : uint64_t tun_id;
3364 : : const struct rte_ether_hdr *eth;
3365 : : struct nfp_fl_act_pre_tun *pre_tun;
3366 : : struct nfp_fl_act_set_tun *set_tun;
3367 : : const struct rte_flow_item_gre *gre;
3368 : : const struct rte_flow_item_ipv6 *ipv6;
3369 : : size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
3370 : : size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
3371 : :
3372 : 0 : eth = (const struct rte_ether_hdr *)raw_encap->data;
3373 : 0 : ipv6 = (const struct rte_flow_item_ipv6 *)(eth + 1);
3374 : : gre = (const struct rte_flow_item_gre *)(ipv6 + 1);
3375 [ # # ]: 0 : tun_id = rte_be_to_cpu_32(*(const rte_be32_t *)(gre + 1));
3376 : :
3377 : : pre_tun = (struct nfp_fl_act_pre_tun *)actions;
3378 : : memset(pre_tun, 0, act_pre_size);
3379 [ # # ]: 0 : nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
3380 : :
3381 : 0 : set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
3382 : : memset(set_tun, 0, act_set_size);
3383 [ # # ]: 0 : tos = rte_be_to_cpu_32(ipv6->hdr.vtc_flow) >> RTE_IPV6_HDR_TC_SHIFT;
3384 : : nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, tun_id,
3385 [ # # ]: 0 : ipv6->hdr.hop_limits, tos);
3386 : 0 : set_tun->tun_proto = gre->protocol;
3387 : :
3388 : : /* Send the tunnel neighbor cmsg to fw */
3389 : 0 : return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
3390 : : tun, eth, ipv6);
3391 : : }
3392 : :
3393 : : static int
3394 : 0 : nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
3395 : : char *act_data,
3396 : : char *actions,
3397 : : const struct rte_flow_action *action,
3398 : : struct nfp_fl_rule_metadata *nfp_flow_meta,
3399 : : struct nfp_fl_tun *tun)
3400 : : {
3401 : : int ret;
3402 : : size_t act_len;
3403 : : size_t act_pre_size;
3404 : : const struct rte_flow_action_raw_encap *raw_encap;
3405 : :
3406 : 0 : raw_encap = action->conf;
3407 [ # # ]: 0 : if (raw_encap->data == NULL) {
3408 : 0 : PMD_DRV_LOG(ERR, "The raw encap action conf is NULL.");
3409 : 0 : return -EINVAL;
3410 : : }
3411 : :
3412 : : /*
3413 : : * Pre_tunnel action must be the first on action list.
3414 : : * If other actions already exist, they need to be pushed forward.
3415 : : */
3416 : 0 : act_len = act_data - actions;
3417 [ # # ]: 0 : if (act_len != 0) {
3418 : : act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
3419 : 0 : memmove(actions + act_pre_size, actions, act_len);
3420 : : }
3421 : :
3422 [ # # # # : 0 : switch (raw_encap->size) {
# ]
3423 : 0 : case GENEVE_V4_LEN:
3424 : 0 : ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
3425 : : actions, raw_encap, nfp_flow_meta, tun);
3426 : 0 : break;
3427 : 0 : case GENEVE_V6_LEN:
3428 : 0 : ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
3429 : : actions, raw_encap, nfp_flow_meta, tun);
3430 : 0 : break;
3431 : 0 : case NVGRE_V4_LEN:
3432 : 0 : ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
3433 : : actions, raw_encap, nfp_flow_meta, tun);
3434 : 0 : break;
3435 : 0 : case NVGRE_V6_LEN:
3436 : 0 : ret = nfp_flow_action_nvgre_encap_v6(app_fw_flower, act_data,
3437 : : actions, raw_encap, nfp_flow_meta, tun);
3438 : 0 : break;
3439 : 0 : default:
3440 : 0 : PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
3441 : : ret = -EINVAL;
3442 : 0 : break;
3443 : : }
3444 : :
3445 : : return ret;
3446 : : }
3447 : :
3448 : : static int
3449 : 0 : nfp_flow_action_meter(struct nfp_flower_representor *representor,
3450 : : const struct rte_flow_action *action,
3451 : : char *act_data,
3452 : : uint32_t *mtr_id)
3453 : : {
3454 : : struct nfp_mtr *mtr;
3455 : : struct nfp_fl_act_meter *fl_meter;
3456 : : struct nfp_app_fw_flower *app_fw_flower;
3457 : : const struct rte_flow_action_meter *meter;
3458 : : size_t act_size = sizeof(struct nfp_fl_act_meter);
3459 : :
3460 : 0 : meter = action->conf;
3461 : : fl_meter = (struct nfp_fl_act_meter *)act_data;
3462 : 0 : app_fw_flower = representor->app_fw_flower;
3463 : :
3464 : 0 : mtr = nfp_mtr_find_by_mtr_id(app_fw_flower->mtr_priv, meter->mtr_id);
3465 [ # # ]: 0 : if (mtr == NULL) {
3466 : 0 : PMD_DRV_LOG(ERR, "Meter id not exist");
3467 : 0 : return -EINVAL;
3468 : : }
3469 : :
3470 [ # # ]: 0 : if (!mtr->enable) {
3471 : 0 : PMD_DRV_LOG(ERR, "Requested meter disable");
3472 : 0 : return -EINVAL;
3473 : : }
3474 : :
3475 [ # # # # ]: 0 : if (!mtr->shared && mtr->ref_cnt > 0) {
3476 : 0 : PMD_DRV_LOG(ERR, "Can't use a used unshared meter");
3477 : 0 : return -EINVAL;
3478 : : }
3479 : :
3480 : 0 : *mtr_id = meter->mtr_id;
3481 : :
3482 : 0 : fl_meter->head.jump_id = NFP_FL_ACTION_OPCODE_METER;
3483 : 0 : fl_meter->head.len_lw = act_size >> NFP_FL_LW_SIZ;
3484 : 0 : fl_meter->reserved = 0;
3485 [ # # ]: 0 : fl_meter->profile_id = rte_cpu_to_be_32(mtr->mtr_profile->profile_id);
3486 : :
3487 : 0 : return 0;
3488 : : }
3489 : :
3490 : : static uint32_t
3491 : : nfp_flow_count_output(const struct rte_flow_action actions[])
3492 : : {
3493 : : uint32_t count = 0;
3494 : : const struct rte_flow_action *action;
3495 : :
3496 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
3497 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_PORT_ID ||
3498 : : action->type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT)
3499 : 0 : count++;
3500 : : }
3501 : :
3502 : : return count;
3503 : : }
3504 : :
3505 : : static int
3506 : 0 : nfp_flow_compile_action(struct nfp_flower_representor *representor,
3507 : : const struct rte_flow_action actions[],
3508 : : struct rte_flow *nfp_flow)
3509 : : {
3510 : : int ret = 0;
3511 : : uint32_t count;
3512 : : char *position;
3513 : : char *action_data;
3514 : : bool drop_flag = false;
3515 : : bool tc_hl_flag = false;
3516 : : bool ip_set_flag = false;
3517 : : bool tp_set_flag = false;
3518 : : bool mac_set_flag = false;
3519 : : bool ttl_tos_flag = false;
3520 : : uint32_t total_actions = 0;
3521 : : const struct rte_flow_action *action;
3522 : : struct nfp_flower_meta_tci *meta_tci;
3523 : : struct nfp_fl_rule_metadata *nfp_flow_meta;
3524 : :
3525 : 0 : nfp_flow_meta = nfp_flow->payload.meta;
3526 : 0 : action_data = nfp_flow->payload.action_data;
3527 : : position = action_data;
3528 : 0 : meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
3529 : :
3530 : : count = nfp_flow_count_output(actions);
3531 : :
3532 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
3533 [ # # # # : 0 : switch (action->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# ]
3534 : : case RTE_FLOW_ACTION_TYPE_VOID:
3535 : : break;
3536 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
3537 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_DROP");
3538 : : drop_flag = true;
3539 : 0 : break;
3540 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
3541 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_COUNT");
3542 : 0 : break;
3543 : 0 : case RTE_FLOW_ACTION_TYPE_JUMP:
3544 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_JUMP");
3545 : 0 : break;
3546 : 0 : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
3547 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT");
3548 : 0 : count--;
3549 : 0 : ret = nfp_flow_action_output_stage(position, action, nfp_flow_meta, count);
3550 [ # # ]: 0 : if (ret != 0) {
3551 : 0 : PMD_DRV_LOG(ERR, "Failed when process"
3552 : : " RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT");
3553 : 0 : return ret;
3554 : : }
3555 : :
3556 : 0 : position += sizeof(struct nfp_fl_act_output);
3557 : 0 : break;
3558 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
3559 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_PORT_ID");
3560 : 0 : count--;
3561 : 0 : ret = nfp_flow_action_output(position, action, nfp_flow_meta, count);
3562 [ # # ]: 0 : if (ret != 0) {
3563 : 0 : PMD_DRV_LOG(ERR, "Failed when process"
3564 : : " RTE_FLOW_ACTION_TYPE_PORT_ID");
3565 : 0 : return ret;
3566 : : }
3567 : :
3568 : 0 : position += sizeof(struct nfp_fl_act_output);
3569 : 0 : break;
3570 : 0 : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
3571 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_MAC_SRC");
3572 : 0 : nfp_flow_action_set_mac(position, action, true, mac_set_flag);
3573 [ # # ]: 0 : if (!mac_set_flag) {
3574 : 0 : position += sizeof(struct nfp_fl_act_set_eth);
3575 : : mac_set_flag = true;
3576 : : }
3577 : : break;
3578 : 0 : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
3579 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_MAC_DST");
3580 : 0 : nfp_flow_action_set_mac(position, action, false, mac_set_flag);
3581 [ # # ]: 0 : if (!mac_set_flag) {
3582 : 0 : position += sizeof(struct nfp_fl_act_set_eth);
3583 : : mac_set_flag = true;
3584 : : }
3585 : : break;
3586 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
3587 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_OF_POP_VLAN");
3588 : : nfp_flow_action_pop_vlan(position, nfp_flow_meta);
3589 : 0 : position += sizeof(struct nfp_fl_act_pop_vlan);
3590 : 0 : break;
3591 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
3592 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN");
3593 : 0 : ret = nfp_flow_action_push_vlan(position, action);
3594 [ # # ]: 0 : if (ret != 0) {
3595 : 0 : PMD_DRV_LOG(ERR, "Failed when process"
3596 : : " RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN");
3597 : 0 : return ret;
3598 : : }
3599 : :
3600 : : /*
3601 : : * RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP and
3602 : : * RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID
3603 : : * have also been processed.
3604 : : */
3605 : 0 : action += 2;
3606 : 0 : position += sizeof(struct nfp_fl_act_push_vlan);
3607 : 0 : break;
3608 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
3609 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC");
3610 : : nfp_flow_action_set_ip(position, action, true, ip_set_flag);
3611 [ # # ]: 0 : if (!ip_set_flag) {
3612 : 0 : position += sizeof(struct nfp_fl_act_set_ip4_addrs);
3613 : : ip_set_flag = true;
3614 : : }
3615 : : break;
3616 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
3617 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_IPV4_DST");
3618 : : nfp_flow_action_set_ip(position, action, false, ip_set_flag);
3619 [ # # ]: 0 : if (!ip_set_flag) {
3620 : 0 : position += sizeof(struct nfp_fl_act_set_ip4_addrs);
3621 : : ip_set_flag = true;
3622 : : }
3623 : : break;
3624 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
3625 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC");
3626 : 0 : nfp_flow_action_set_ipv6(position, action, true);
3627 : 0 : position += sizeof(struct nfp_fl_act_set_ipv6_addr);
3628 : 0 : break;
3629 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
3630 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_IPV6_DST");
3631 : 0 : nfp_flow_action_set_ipv6(position, action, false);
3632 : 0 : position += sizeof(struct nfp_fl_act_set_ipv6_addr);
3633 : 0 : break;
3634 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
3635 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_TP_SRC");
3636 : : nfp_flow_action_set_tp(position, action, true,
3637 [ # # ]: 0 : tp_set_flag, nfp_flow->tcp_flag);
3638 [ # # ]: 0 : if (!tp_set_flag) {
3639 : 0 : position += sizeof(struct nfp_fl_act_set_tport);
3640 : : tp_set_flag = true;
3641 : : }
3642 : : break;
3643 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
3644 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_TP_DST");
3645 : : nfp_flow_action_set_tp(position, action, false,
3646 [ # # ]: 0 : tp_set_flag, nfp_flow->tcp_flag);
3647 [ # # ]: 0 : if (!tp_set_flag) {
3648 : 0 : position += sizeof(struct nfp_fl_act_set_tport);
3649 : : tp_set_flag = true;
3650 : : }
3651 : : break;
3652 : 0 : case RTE_FLOW_ACTION_TYPE_SET_TTL:
3653 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_TTL");
3654 [ # # ]: 0 : if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) {
3655 : : nfp_flow_action_set_ttl(position, action, ttl_tos_flag);
3656 [ # # ]: 0 : if (!ttl_tos_flag) {
3657 : 0 : position += sizeof(struct nfp_fl_act_set_ip4_ttl_tos);
3658 : : ttl_tos_flag = true;
3659 : : }
3660 : : } else {
3661 : : nfp_flow_action_set_hl(position, action, ttl_tos_flag);
3662 [ # # ]: 0 : if (!tc_hl_flag) {
3663 : 0 : position += sizeof(struct nfp_fl_act_set_ipv6_tc_hl_fl);
3664 : : tc_hl_flag = true;
3665 : : }
3666 : : }
3667 : : break;
3668 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
3669 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP");
3670 : : nfp_flow_action_set_tos(position, action, ttl_tos_flag);
3671 [ # # ]: 0 : if (!ttl_tos_flag) {
3672 : 0 : position += sizeof(struct nfp_fl_act_set_ip4_ttl_tos);
3673 : : ttl_tos_flag = true;
3674 : : }
3675 : : break;
3676 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
3677 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP");
3678 : : nfp_flow_action_set_tc(position, action, ttl_tos_flag);
3679 [ # # ]: 0 : if (!tc_hl_flag) {
3680 : 0 : position += sizeof(struct nfp_fl_act_set_ipv6_tc_hl_fl);
3681 : : tc_hl_flag = true;
3682 : : }
3683 : : break;
3684 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
3685 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
3686 : 0 : ret = nfp_flow_action_vxlan_encap(representor->app_fw_flower,
3687 : : position, action_data, action, nfp_flow_meta,
3688 : : &nfp_flow->tun);
3689 [ # # ]: 0 : if (ret != 0) {
3690 : 0 : PMD_DRV_LOG(ERR, "Failed when process"
3691 : : " RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
3692 : 0 : return ret;
3693 : : }
3694 : : position += sizeof(struct nfp_fl_act_pre_tun);
3695 : 0 : position += sizeof(struct nfp_fl_act_set_tun);
3696 : 0 : nfp_flow->type = NFP_FLOW_ENCAP;
3697 : 0 : break;
3698 : 0 : case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
3699 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
3700 : 0 : ret = nfp_flow_action_raw_encap(representor->app_fw_flower,
3701 : : position, action_data, action, nfp_flow_meta,
3702 : : &nfp_flow->tun);
3703 [ # # ]: 0 : if (ret != 0) {
3704 : 0 : PMD_DRV_LOG(ERR, "Failed when process"
3705 : : " RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
3706 : 0 : return ret;
3707 : : }
3708 : : position += sizeof(struct nfp_fl_act_pre_tun);
3709 : 0 : position += sizeof(struct nfp_fl_act_set_tun);
3710 : 0 : nfp_flow->type = NFP_FLOW_ENCAP;
3711 : 0 : break;
3712 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
3713 : : case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
3714 : 0 : PMD_DRV_LOG(DEBUG, "process action tunnel decap");
3715 : 0 : ret = nfp_flow_action_tunnel_decap(representor, action,
3716 : : nfp_flow_meta, nfp_flow);
3717 [ # # ]: 0 : if (ret != 0) {
3718 : 0 : PMD_DRV_LOG(ERR, "Failed when process tunnel decap");
3719 : 0 : return ret;
3720 : : }
3721 : 0 : nfp_flow->type = NFP_FLOW_DECAP;
3722 : 0 : nfp_flow->install_flag = false;
3723 [ # # ]: 0 : if (action->conf != NULL)
3724 : 0 : nfp_flow->tun.payload.v6_flag = 1;
3725 : : break;
3726 : 0 : case RTE_FLOW_ACTION_TYPE_METER:
3727 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_METER");
3728 : 0 : ret = nfp_flow_action_meter(representor, action,
3729 : : position, &nfp_flow->mtr_id);
3730 [ # # ]: 0 : if (ret != 0)
3731 : : return -EINVAL;
3732 : 0 : position += sizeof(struct nfp_fl_act_meter);
3733 : 0 : break;
3734 : 0 : case RTE_FLOW_ACTION_TYPE_CONNTRACK:
3735 : 0 : PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_CONNTRACK");
3736 : 0 : break;
3737 : 0 : default:
3738 : 0 : PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
3739 : 0 : return -ENOTSUP;
3740 : : }
3741 : 0 : total_actions++;
3742 : : }
3743 : :
3744 [ # # ]: 0 : if (drop_flag)
3745 : 0 : nfp_flow_meta->shortcut = rte_cpu_to_be_32(NFP_FL_SC_ACT_DROP);
3746 [ # # ]: 0 : else if (total_actions > 1)
3747 : 0 : nfp_flow_meta->shortcut = rte_cpu_to_be_32(NFP_FL_SC_ACT_NULL);
3748 : :
3749 : : return 0;
3750 : : }
3751 : :
3752 : : struct rte_flow *
3753 : 0 : nfp_flow_process(struct nfp_flower_representor *representor,
3754 : : const struct rte_flow_item items[],
3755 : : const struct rte_flow_action actions[],
3756 : : bool validate_flag,
3757 : : uint64_t cookie,
3758 : : bool install_flag,
3759 : : bool merge_flag)
3760 : : {
3761 : : int ret;
3762 : : char *hash_data;
3763 : : char *mask_data;
3764 : : uint32_t mask_len;
3765 : 0 : uint32_t stats_ctx = 0;
3766 : 0 : uint8_t new_mask_id = 0;
3767 : : struct rte_flow *nfp_flow;
3768 : : struct rte_flow *flow_find;
3769 : : struct nfp_flow_priv *priv;
3770 : : struct nfp_fl_key_ls key_layer;
3771 : : struct nfp_fl_rule_metadata *nfp_flow_meta;
3772 : :
3773 : 0 : ret = nfp_flow_key_layers_calculate(items, actions, &key_layer);
3774 [ # # ]: 0 : if (ret != 0) {
3775 : 0 : PMD_DRV_LOG(ERR, "Key layers calculate failed.");
3776 : 0 : return NULL;
3777 : : }
3778 : :
3779 [ # # ]: 0 : if (key_layer.port == (uint32_t)~0)
3780 : 0 : key_layer.port = representor->port_id;
3781 : :
3782 : 0 : priv = representor->app_fw_flower->flow_priv;
3783 : 0 : ret = nfp_stats_id_alloc(priv, &stats_ctx);
3784 [ # # ]: 0 : if (ret != 0) {
3785 : 0 : PMD_DRV_LOG(ERR, "nfp stats id alloc failed.");
3786 : 0 : return NULL;
3787 : : }
3788 : :
3789 : 0 : nfp_flow = nfp_flow_alloc(&key_layer, representor->port_id);
3790 [ # # ]: 0 : if (nfp_flow == NULL) {
3791 : 0 : PMD_DRV_LOG(ERR, "Alloc nfp flow failed.");
3792 : 0 : goto free_stats;
3793 : : }
3794 : :
3795 : 0 : nfp_flow->install_flag = install_flag;
3796 : 0 : nfp_flow->merge_flag = merge_flag;
3797 : :
3798 : 0 : nfp_flow_compile_metadata(priv, nfp_flow, &key_layer, stats_ctx, cookie);
3799 : :
3800 : 0 : ret = nfp_flow_compile_items(representor, items, nfp_flow);
3801 [ # # ]: 0 : if (ret != 0) {
3802 : 0 : PMD_DRV_LOG(ERR, "nfp flow item process failed.");
3803 : 0 : goto free_flow;
3804 : : }
3805 : :
3806 : 0 : ret = nfp_flow_compile_action(representor, actions, nfp_flow);
3807 [ # # ]: 0 : if (ret != 0) {
3808 : 0 : PMD_DRV_LOG(ERR, "nfp flow action process failed.");
3809 : 0 : goto free_flow;
3810 : : }
3811 : :
3812 : 0 : nfp_flow_meta = nfp_flow->payload.meta;
3813 : 0 : mask_data = nfp_flow->payload.mask_data;
3814 : 0 : mask_len = key_layer.key_size;
3815 [ # # ]: 0 : if (!nfp_check_mask_add(priv, mask_data, mask_len,
3816 : : &nfp_flow_meta->flags, &new_mask_id)) {
3817 : 0 : PMD_DRV_LOG(ERR, "nfp mask add check failed.");
3818 : 0 : goto free_flow;
3819 : : }
3820 : :
3821 : : /* Once we have a mask_id, update the meta tci */
3822 : 0 : nfp_flower_update_meta_tci(nfp_flow->payload.unmasked_data, new_mask_id);
3823 : :
3824 : : /* Calculate and store the hash_key for later use */
3825 : : hash_data = nfp_flow->payload.unmasked_data;
3826 : 0 : nfp_flow->hash_key = rte_jhash(hash_data, nfp_flow->length, priv->hash_seed);
3827 : :
3828 : : /* Find the flow in hash table */
3829 : 0 : flow_find = nfp_flow_table_search(priv, nfp_flow);
3830 [ # # # # : 0 : if (flow_find != NULL && !nfp_flow->merge_flag && !flow_find->merge_flag) {
# # ]
3831 : 0 : PMD_DRV_LOG(ERR, "This flow is already exist.");
3832 [ # # ]: 0 : if (!nfp_check_mask_remove(priv, mask_data, mask_len,
3833 : : &nfp_flow_meta->flags)) {
3834 : 0 : PMD_DRV_LOG(ERR, "nfp mask del check failed.");
3835 : : }
3836 : 0 : goto free_flow;
3837 : : }
3838 : :
3839 : : /* Flow validate should not update the flower version */
3840 [ # # ]: 0 : if (!validate_flag)
3841 : 0 : priv->flower_version++;
3842 : :
3843 : : return nfp_flow;
3844 : :
3845 : 0 : free_flow:
3846 : 0 : nfp_flow_free(nfp_flow);
3847 : 0 : free_stats:
3848 : 0 : nfp_stats_id_free(priv, stats_ctx);
3849 : :
3850 : 0 : return NULL;
3851 : : }
3852 : :
3853 : : static struct rte_flow *
3854 : 0 : nfp_flow_setup(struct nfp_flower_representor *representor,
3855 : : const struct rte_flow_attr *attr,
3856 : : const struct rte_flow_item items[],
3857 : : const struct rte_flow_action actions[],
3858 : : __rte_unused struct rte_flow_error *error,
3859 : : bool validate_flag)
3860 : : {
3861 : : uint64_t cookie;
3862 : : const struct rte_flow_item *item;
3863 : : const struct rte_flow_item *ct_item = NULL;
3864 : :
3865 [ # # ]: 0 : if (attr->group != 0)
3866 : 0 : PMD_DRV_LOG(INFO, "Pretend we support group attribute.");
3867 : :
3868 [ # # ]: 0 : if (attr->priority != 0)
3869 : 0 : PMD_DRV_LOG(INFO, "Pretend we support priority attribute.");
3870 : :
3871 [ # # ]: 0 : if (attr->transfer != 0)
3872 : 0 : PMD_DRV_LOG(INFO, "Pretend we support transfer attribute.");
3873 : :
3874 [ # # ]: 0 : for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
3875 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_CONNTRACK) {
3876 : : ct_item = item;
3877 : : break;
3878 : : }
3879 : : }
3880 : :
3881 : 0 : cookie = rte_rand();
3882 : :
3883 [ # # ]: 0 : if (ct_item != NULL)
3884 : 0 : return nfp_ct_flow_setup(representor, items, actions,
3885 : : ct_item, validate_flag, cookie);
3886 : :
3887 : 0 : return nfp_flow_process(representor, items, actions, validate_flag, cookie, true, false);
3888 : : }
3889 : :
3890 : : int
3891 : 0 : nfp_flow_teardown(struct nfp_flow_priv *priv,
3892 : : struct rte_flow *nfp_flow,
3893 : : bool validate_flag)
3894 : : {
3895 : : char *mask_data;
3896 : : uint32_t mask_len;
3897 : : uint32_t stats_ctx;
3898 : : struct nfp_fl_rule_metadata *nfp_flow_meta;
3899 : :
3900 : 0 : nfp_flow_meta = nfp_flow->payload.meta;
3901 : 0 : mask_data = nfp_flow->payload.mask_data;
3902 : 0 : mask_len = nfp_flow_meta->mask_len << NFP_FL_LW_SIZ;
3903 : 0 : nfp_flow_meta->flags &= ~NFP_FL_META_FLAG_MANAGE_MASK;
3904 [ # # ]: 0 : if (!nfp_check_mask_remove(priv, mask_data, mask_len,
3905 : : &nfp_flow_meta->flags)) {
3906 : 0 : PMD_DRV_LOG(ERR, "nfp mask del check failed.");
3907 : 0 : return -EINVAL;
3908 : : }
3909 : :
3910 [ # # ]: 0 : nfp_flow_meta->flow_version = rte_cpu_to_be_64(priv->flower_version);
3911 : :
3912 : : /* Flow validate should not update the flower version */
3913 [ # # ]: 0 : if (!validate_flag)
3914 : 0 : priv->flower_version++;
3915 : :
3916 [ # # ]: 0 : stats_ctx = rte_be_to_cpu_32(nfp_flow_meta->host_ctx_id);
3917 : 0 : return nfp_stats_id_free(priv, stats_ctx);
3918 : : }
3919 : :
3920 : : static int
3921 : 0 : nfp_flow_validate(struct rte_eth_dev *dev,
3922 : : const struct rte_flow_attr *attr,
3923 : : const struct rte_flow_item items[],
3924 : : const struct rte_flow_action actions[],
3925 : : struct rte_flow_error *error)
3926 : : {
3927 : : int ret;
3928 : : struct rte_flow *nfp_flow;
3929 : : struct nfp_flow_priv *priv;
3930 : : struct nfp_flower_representor *representor;
3931 : :
3932 : 0 : representor = dev->data->dev_private;
3933 : 0 : priv = representor->app_fw_flower->flow_priv;
3934 : :
3935 : 0 : nfp_flow = nfp_flow_setup(representor, attr, items, actions, error, true);
3936 [ # # ]: 0 : if (nfp_flow == NULL) {
3937 : 0 : return rte_flow_error_set(error, ENOTSUP,
3938 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3939 : : NULL, "This flow can not be offloaded.");
3940 : : }
3941 : :
3942 : 0 : ret = nfp_flow_teardown(priv, nfp_flow, true);
3943 [ # # ]: 0 : if (ret != 0) {
3944 : 0 : return rte_flow_error_set(error, EINVAL,
3945 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3946 : : NULL, "Flow resource free failed.");
3947 : : }
3948 : :
3949 : 0 : nfp_flow_free(nfp_flow);
3950 : :
3951 : 0 : return 0;
3952 : : }
3953 : :
3954 : : static struct rte_flow *
3955 : 0 : nfp_flow_create(struct rte_eth_dev *dev,
3956 : : const struct rte_flow_attr *attr,
3957 : : const struct rte_flow_item items[],
3958 : : const struct rte_flow_action actions[],
3959 : : struct rte_flow_error *error)
3960 : : {
3961 : : int ret;
3962 : : struct rte_flow *nfp_flow;
3963 : : struct nfp_flow_priv *priv;
3964 : : struct nfp_app_fw_flower *app_fw_flower;
3965 : : struct nfp_flower_representor *representor;
3966 : :
3967 : 0 : representor = dev->data->dev_private;
3968 : 0 : app_fw_flower = representor->app_fw_flower;
3969 : 0 : priv = app_fw_flower->flow_priv;
3970 : :
3971 : 0 : nfp_flow = nfp_flow_setup(representor, attr, items, actions, error, false);
3972 [ # # ]: 0 : if (nfp_flow == NULL) {
3973 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3974 : : NULL, "This flow can not be offloaded.");
3975 : 0 : return NULL;
3976 : : }
3977 : :
3978 : : /* Add the flow to hardware */
3979 [ # # ]: 0 : if (nfp_flow->install_flag) {
3980 : 0 : ret = nfp_flower_cmsg_flow_add(app_fw_flower, nfp_flow);
3981 [ # # ]: 0 : if (ret != 0) {
3982 : 0 : rte_flow_error_set(error, EINVAL,
3983 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3984 : : NULL, "Add flow to firmware failed.");
3985 : 0 : goto flow_teardown;
3986 : : }
3987 : : }
3988 : :
3989 : : /* Add the flow to flow hash table */
3990 : 0 : ret = nfp_flow_table_add_merge(priv, nfp_flow);
3991 [ # # ]: 0 : if (ret != 0) {
3992 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3993 : : NULL, "Add flow to the flow table failed.");
3994 : 0 : goto flow_teardown;
3995 : : }
3996 : :
3997 : : /* Update meter object ref count */
3998 [ # # ]: 0 : if (nfp_flow->mtr_id != NFP_MAX_MTR_CNT) {
3999 : 0 : ret = nfp_mtr_update_ref_cnt(app_fw_flower->mtr_priv,
4000 : : nfp_flow->mtr_id, true);
4001 [ # # ]: 0 : if (ret != 0) {
4002 : 0 : rte_flow_error_set(error, EINVAL,
4003 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4004 : : NULL, "Update meter ref_cnt failed.");
4005 : 0 : goto flow_teardown;
4006 : : }
4007 : : }
4008 : :
4009 : : return nfp_flow;
4010 : :
4011 : 0 : flow_teardown:
4012 : 0 : nfp_flow_teardown(priv, nfp_flow, false);
4013 : 0 : nfp_flow_free(nfp_flow);
4014 : :
4015 : 0 : return NULL;
4016 : : }
4017 : :
4018 : : int
4019 : 0 : nfp_flow_destroy(struct rte_eth_dev *dev,
4020 : : struct rte_flow *nfp_flow,
4021 : : struct rte_flow_error *error)
4022 : : {
4023 : : int ret;
4024 : : uint64_t cookie;
4025 : : struct rte_flow *flow_find;
4026 : : struct nfp_flow_priv *priv;
4027 : : struct nfp_ct_map_entry *me;
4028 : : struct nfp_app_fw_flower *app_fw_flower;
4029 : : struct nfp_flower_representor *representor;
4030 : :
4031 : 0 : representor = dev->data->dev_private;
4032 : 0 : app_fw_flower = representor->app_fw_flower;
4033 : 0 : priv = app_fw_flower->flow_priv;
4034 : :
4035 : : /* Find the flow in ct_map_table */
4036 [ # # ]: 0 : cookie = rte_be_to_cpu_64(nfp_flow->payload.meta->host_cookie);
4037 : 0 : me = nfp_ct_map_table_search(priv, (char *)&cookie, sizeof(uint64_t));
4038 [ # # ]: 0 : if (me != NULL)
4039 : 0 : return nfp_ct_offload_del(dev, me, error);
4040 : :
4041 : : /* Find the flow in flow hash table */
4042 : 0 : flow_find = nfp_flow_table_search(priv, nfp_flow);
4043 [ # # ]: 0 : if (flow_find == NULL) {
4044 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4045 : : NULL, "Flow does not exist.");
4046 : : ret = -EINVAL;
4047 : 0 : goto exit;
4048 : : }
4049 : :
4050 : : /* Update flow */
4051 : 0 : ret = nfp_flow_teardown(priv, nfp_flow, false);
4052 [ # # ]: 0 : if (ret != 0) {
4053 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4054 : : NULL, "Flow teardown failed.");
4055 : : ret = -EINVAL;
4056 : 0 : goto exit;
4057 : : }
4058 : :
4059 [ # # # # ]: 0 : switch (nfp_flow->type) {
4060 : : case NFP_FLOW_COMMON:
4061 : : break;
4062 : 0 : case NFP_FLOW_ENCAP:
4063 : : /* Delete the entry from nn table */
4064 : 0 : ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, false);
4065 : 0 : break;
4066 : 0 : case NFP_FLOW_DECAP:
4067 : : /* Delete the entry from nn table */
4068 : 0 : ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, true);
4069 [ # # ]: 0 : if (ret != 0)
4070 : 0 : goto exit;
4071 : :
4072 : : /* Delete the entry in pre tunnel table */
4073 : 0 : ret = nfp_pre_tun_table_check_del(representor, nfp_flow);
4074 : 0 : break;
4075 : 0 : default:
4076 : 0 : PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
4077 : : ret = -EINVAL;
4078 : : break;
4079 : : }
4080 : :
4081 [ # # ]: 0 : if (ret != 0)
4082 : 0 : goto exit;
4083 : :
4084 : : /* Delete the ip off */
4085 [ # # ]: 0 : if (nfp_flow_is_tunnel(nfp_flow))
4086 : 0 : nfp_tun_check_ip_off_del(representor, nfp_flow);
4087 : :
4088 : : /* Delete the flow from hardware */
4089 [ # # ]: 0 : if (nfp_flow->install_flag) {
4090 : 0 : ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
4091 [ # # ]: 0 : if (ret != 0) {
4092 : 0 : rte_flow_error_set(error, EINVAL,
4093 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4094 : : NULL, "Delete flow from firmware failed.");
4095 : : ret = -EINVAL;
4096 : 0 : goto exit;
4097 : : }
4098 : : }
4099 : :
4100 : : /* Delete the flow from flow hash table */
4101 : 0 : ret = nfp_flow_table_delete_merge(priv, nfp_flow);
4102 [ # # ]: 0 : if (ret != 0) {
4103 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4104 : : NULL, "Delete flow from the flow table failed.");
4105 : : ret = -EINVAL;
4106 : 0 : goto exit;
4107 : : }
4108 : :
4109 : : /* Update meter object ref count */
4110 [ # # ]: 0 : if (nfp_flow->mtr_id != NFP_MAX_MTR_CNT) {
4111 : 0 : ret = nfp_mtr_update_ref_cnt(app_fw_flower->mtr_priv,
4112 : : nfp_flow->mtr_id, false);
4113 [ # # ]: 0 : if (ret != 0) {
4114 : 0 : rte_flow_error_set(error, EINVAL,
4115 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4116 : : NULL, "Update meter ref_cnt failed.");
4117 : : }
4118 : : }
4119 : :
4120 : 0 : exit:
4121 : 0 : nfp_flow_free(nfp_flow);
4122 : :
4123 : 0 : return ret;
4124 : : }
4125 : :
4126 : : static int
4127 : 0 : nfp_flow_flush(struct rte_eth_dev *dev,
4128 : : struct rte_flow_error *error)
4129 : : {
4130 : : int ret = 0;
4131 : : void *next_data;
4132 : 0 : uint32_t iter = 0;
4133 : : const void *next_key;
4134 : : struct rte_flow *nfp_flow;
4135 : : struct nfp_flow_priv *priv;
4136 : : struct nfp_flower_representor *representor;
4137 : :
4138 : 0 : representor = dev->data->dev_private;
4139 : :
4140 : : priv = nfp_flow_dev_to_priv(dev);
4141 : :
4142 [ # # ]: 0 : while (rte_hash_iterate(priv->flow_table, &next_key, &next_data, &iter) >= 0) {
4143 : 0 : nfp_flow = next_data;
4144 [ # # ]: 0 : if (nfp_flow->port_id == representor->port_id) {
4145 : 0 : ret = nfp_flow_destroy(dev, nfp_flow, error);
4146 [ # # ]: 0 : if (ret != 0)
4147 : : break;
4148 : : }
4149 : : }
4150 : :
4151 : 0 : return ret;
4152 : : }
4153 : :
4154 : : static void
4155 : 0 : nfp_flow_stats_get(struct rte_eth_dev *dev,
4156 : : struct rte_flow *nfp_flow,
4157 : : void *data)
4158 : : {
4159 : : bool reset;
4160 : : uint64_t cookie;
4161 : : uint32_t ctx_id;
4162 : : struct rte_flow *flow;
4163 : : struct nfp_flow_priv *priv;
4164 : : struct nfp_fl_stats *stats;
4165 : : struct nfp_ct_map_entry *me;
4166 : : struct rte_flow_query_count *query;
4167 : :
4168 : : priv = nfp_flow_dev_to_priv(dev);
4169 : 0 : flow = nfp_flow_table_search(priv, nfp_flow);
4170 [ # # ]: 0 : if (flow == NULL) {
4171 : 0 : PMD_DRV_LOG(ERR, "Can not find statistics for this flow.");
4172 : 0 : return;
4173 : : }
4174 : :
4175 : : query = data;
4176 [ # # ]: 0 : reset = query->reset;
4177 : : memset(query, 0, sizeof(*query));
4178 : :
4179 : : /* Find the flow in ct_map_table */
4180 [ # # ]: 0 : cookie = rte_be_to_cpu_64(nfp_flow->payload.meta->host_cookie);
4181 : 0 : me = nfp_ct_map_table_search(priv, (char *)&cookie, sizeof(uint64_t));
4182 [ # # ]: 0 : if (me != NULL) {
4183 : 0 : stats = nfp_ct_flow_stats_get(priv, me);
4184 : : } else {
4185 [ # # ]: 0 : ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id);
4186 : 0 : stats = &priv->stats[ctx_id];
4187 : : }
4188 : :
4189 : 0 : rte_spinlock_lock(&priv->stats_lock);
4190 [ # # # # ]: 0 : if (stats->pkts != 0 && stats->bytes != 0) {
4191 : 0 : query->hits = stats->pkts;
4192 : 0 : query->bytes = stats->bytes;
4193 : 0 : query->hits_set = 1;
4194 : 0 : query->bytes_set = 1;
4195 [ # # ]: 0 : if (reset) {
4196 : 0 : stats->pkts = 0;
4197 : 0 : stats->bytes = 0;
4198 : : }
4199 : : }
4200 : : rte_spinlock_unlock(&priv->stats_lock);
4201 : : }
4202 : :
4203 : : static int
4204 : 0 : nfp_flow_query(struct rte_eth_dev *dev,
4205 : : struct rte_flow *nfp_flow,
4206 : : const struct rte_flow_action *actions,
4207 : : void *data,
4208 : : struct rte_flow_error *error)
4209 : : {
4210 : : const struct rte_flow_action *action;
4211 : :
4212 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
4213 [ # # # ]: 0 : switch (action->type) {
4214 : : case RTE_FLOW_ACTION_TYPE_VOID:
4215 : : break;
4216 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
4217 : 0 : nfp_flow_stats_get(dev, nfp_flow, data);
4218 : 0 : break;
4219 : 0 : default:
4220 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4221 : : NULL, "Unsupported action type for flow query.");
4222 : 0 : return -ENOTSUP;
4223 : : }
4224 : : }
4225 : :
4226 : : return 0;
4227 : : }
4228 : :
4229 : : static int
4230 : 0 : nfp_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
4231 : : __rte_unused struct rte_flow_tunnel *tunnel,
4232 : : __rte_unused struct rte_flow_item **pmd_items,
4233 : : uint32_t *num_of_items,
4234 : : __rte_unused struct rte_flow_error *err)
4235 : : {
4236 : 0 : *num_of_items = 0;
4237 : :
4238 : 0 : return 0;
4239 : : }
4240 : :
4241 : : static int
4242 : 0 : nfp_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
4243 : : __rte_unused struct rte_flow_item *pmd_items,
4244 : : __rte_unused uint32_t num_of_items,
4245 : : __rte_unused struct rte_flow_error *err)
4246 : : {
4247 : 0 : return 0;
4248 : : }
4249 : :
4250 : : static int
4251 : 0 : nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
4252 : : struct rte_flow_tunnel *tunnel,
4253 : : struct rte_flow_action **pmd_actions,
4254 : : uint32_t *num_of_actions,
4255 : : __rte_unused struct rte_flow_error *err)
4256 : : {
4257 : : struct rte_flow_action *nfp_action;
4258 : :
4259 : 0 : nfp_action = rte_zmalloc("nfp_tun_action", sizeof(struct rte_flow_action), 0);
4260 [ # # ]: 0 : if (nfp_action == NULL) {
4261 : 0 : PMD_DRV_LOG(ERR, "Alloc memory for nfp tunnel action failed.");
4262 : 0 : return -ENOMEM;
4263 : : }
4264 : :
4265 [ # # ]: 0 : if (tunnel->is_ipv6)
4266 : 0 : nfp_action->conf = (void *)~0;
4267 : :
4268 [ # # # ]: 0 : switch (tunnel->type) {
4269 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
4270 : 0 : nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
4271 : 0 : *pmd_actions = nfp_action;
4272 : 0 : *num_of_actions = 1;
4273 : 0 : break;
4274 : 0 : case RTE_FLOW_ITEM_TYPE_GENEVE:
4275 : : case RTE_FLOW_ITEM_TYPE_GRE:
4276 : 0 : nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
4277 : 0 : *pmd_actions = nfp_action;
4278 : 0 : *num_of_actions = 1;
4279 : 0 : break;
4280 : 0 : default:
4281 : 0 : *pmd_actions = NULL;
4282 : 0 : *num_of_actions = 0;
4283 : 0 : rte_free(nfp_action);
4284 : 0 : break;
4285 : : }
4286 : :
4287 : : return 0;
4288 : : }
4289 : :
4290 : : static int
4291 : 0 : nfp_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
4292 : : struct rte_flow_action *pmd_actions,
4293 : : uint32_t num_of_actions,
4294 : : __rte_unused struct rte_flow_error *err)
4295 : : {
4296 : : uint32_t i;
4297 : : struct rte_flow_action *nfp_action;
4298 : :
4299 [ # # ]: 0 : for (i = 0; i < num_of_actions; i++) {
4300 : 0 : nfp_action = &pmd_actions[i];
4301 : 0 : nfp_action->conf = NULL;
4302 : 0 : rte_free(nfp_action);
4303 : : }
4304 : :
4305 : 0 : return 0;
4306 : : }
4307 : :
4308 : : static const struct rte_flow_ops nfp_flow_ops = {
4309 : : .validate = nfp_flow_validate,
4310 : : .create = nfp_flow_create,
4311 : : .destroy = nfp_flow_destroy,
4312 : : .flush = nfp_flow_flush,
4313 : : .query = nfp_flow_query,
4314 : : .tunnel_match = nfp_flow_tunnel_match,
4315 : : .tunnel_item_release = nfp_flow_tunnel_item_release,
4316 : : .tunnel_decap_set = nfp_flow_tunnel_decap_set,
4317 : : .tunnel_action_decap_release = nfp_flow_tunnel_action_decap_release,
4318 : : };
4319 : :
4320 : : int
4321 : 0 : nfp_net_flow_ops_get(struct rte_eth_dev *dev,
4322 : : const struct rte_flow_ops **ops)
4323 : : {
4324 [ # # ]: 0 : if ((dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) == 0) {
4325 : 0 : *ops = NULL;
4326 : 0 : PMD_DRV_LOG(ERR, "Port is not a representor.");
4327 : 0 : return -EINVAL;
4328 : : }
4329 : :
4330 : 0 : *ops = &nfp_flow_ops;
4331 : :
4332 : 0 : return 0;
4333 : : }
4334 : :
4335 : : int
4336 : 0 : nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)
4337 : : {
4338 : 0 : int ret = 0;
4339 : : size_t stats_size;
4340 : : uint64_t ctx_count;
4341 : : uint64_t ctx_split;
4342 : : struct nfp_flow_priv *priv;
4343 : : char mask_name[RTE_HASH_NAMESIZE];
4344 : : char flow_name[RTE_HASH_NAMESIZE];
4345 : : char pretun_name[RTE_HASH_NAMESIZE];
4346 : : struct nfp_app_fw_flower *app_fw_flower;
4347 : 0 : const char *pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
4348 : :
4349 : : snprintf(mask_name, sizeof(mask_name), "%s_mask", pci_name);
4350 : : snprintf(flow_name, sizeof(flow_name), "%s_flow", pci_name);
4351 : : snprintf(pretun_name, sizeof(pretun_name), "%s_pretun", pci_name);
4352 : :
4353 : 0 : struct rte_hash_parameters mask_hash_params = {
4354 : : .name = mask_name,
4355 : : .entries = NFP_MASK_TABLE_ENTRIES,
4356 : : .hash_func = rte_jhash,
4357 : 0 : .socket_id = rte_socket_id(),
4358 : : .key_len = sizeof(uint32_t),
4359 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
4360 : : };
4361 : :
4362 : 0 : struct rte_hash_parameters flow_hash_params = {
4363 : : .name = flow_name,
4364 : : .hash_func = rte_jhash,
4365 : 0 : .socket_id = rte_socket_id(),
4366 : : .key_len = sizeof(uint32_t),
4367 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
4368 : : };
4369 : :
4370 : 0 : struct rte_hash_parameters pre_tun_hash_params = {
4371 : : .name = pretun_name,
4372 : : .entries = 32,
4373 : : .hash_func = rte_jhash,
4374 : 0 : .socket_id = rte_socket_id(),
4375 : : .key_len = sizeof(uint32_t),
4376 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
4377 : : };
4378 : :
4379 : 0 : struct rte_hash_parameters ct_zone_hash_params = {
4380 : : .name = "ct_zone_table",
4381 : : .entries = 65536,
4382 : : .hash_func = rte_jhash,
4383 : 0 : .socket_id = rte_socket_id(),
4384 : : .key_len = sizeof(uint32_t),
4385 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
4386 : : };
4387 : :
4388 : 0 : struct rte_hash_parameters ct_map_hash_params = {
4389 : : .name = "ct_map_table",
4390 : : .hash_func = rte_jhash,
4391 : 0 : .socket_id = rte_socket_id(),
4392 : : .key_len = sizeof(uint32_t),
4393 : : .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
4394 : : };
4395 : :
4396 : 0 : ctx_count = nfp_rtsym_read_le(pf_dev->sym_tbl,
4397 : : "CONFIG_FC_HOST_CTX_COUNT", &ret);
4398 [ # # ]: 0 : if (ret < 0) {
4399 : 0 : PMD_INIT_LOG(ERR, "Read CTX_COUNT from symbol table failed");
4400 : 0 : goto exit;
4401 : : }
4402 : :
4403 : 0 : ctx_split = nfp_rtsym_read_le(pf_dev->sym_tbl,
4404 : : "CONFIG_FC_HOST_CTX_SPLIT", &ret);
4405 [ # # ]: 0 : if (ret < 0) {
4406 : 0 : PMD_INIT_LOG(ERR, "Read CTX_SPLIT from symbol table failed");
4407 : 0 : goto exit;
4408 : : }
4409 : :
4410 : 0 : priv = rte_zmalloc("nfp_app_flow_priv", sizeof(struct nfp_flow_priv), 0);
4411 [ # # ]: 0 : if (priv == NULL) {
4412 : 0 : PMD_INIT_LOG(ERR, "nfp app flow priv creation failed");
4413 : 0 : ret = -ENOMEM;
4414 : 0 : goto exit;
4415 : : }
4416 : :
4417 : 0 : app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
4418 : 0 : app_fw_flower->flow_priv = priv;
4419 : 0 : priv->hash_seed = (uint32_t)rte_rand();
4420 : 0 : priv->stats_ring_size = ctx_count;
4421 : 0 : priv->total_mem_units = ctx_split;
4422 : :
4423 : : /* Init ring buffer and unallocated mask_ids. */
4424 : 0 : priv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1;
4425 : 0 : priv->mask_ids.free_list.buf = rte_zmalloc("nfp_app_mask_ids",
4426 : : NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS, 0);
4427 [ # # ]: 0 : if (priv->mask_ids.free_list.buf == NULL) {
4428 : 0 : PMD_INIT_LOG(ERR, "mask id free list creation failed");
4429 : 0 : ret = -ENOMEM;
4430 : 0 : goto free_priv;
4431 : : }
4432 : :
4433 : : /* Init ring buffer and unallocated stats_ids. */
4434 : 0 : priv->stats_ids.init_unallocated = ctx_count / ctx_split;
4435 : 0 : priv->stats_ids.free_list.buf = rte_zmalloc("nfp_app_stats_ids",
4436 : 0 : priv->stats_ring_size * NFP_FL_STATS_ELEM_RS, 0);
4437 [ # # ]: 0 : if (priv->stats_ids.free_list.buf == NULL) {
4438 : 0 : PMD_INIT_LOG(ERR, "stats id free list creation failed");
4439 : 0 : ret = -ENOMEM;
4440 : 0 : goto free_mask_id;
4441 : : }
4442 : :
4443 : : /* Flow stats */
4444 : : rte_spinlock_init(&priv->stats_lock);
4445 : 0 : stats_size = (ctx_count & NFP_FL_STAT_ID_STAT) |
4446 : 0 : ((ctx_split - 1) & NFP_FL_STAT_ID_MU_NUM);
4447 : 0 : PMD_INIT_LOG(INFO, "ctx_count:%0lx, ctx_split:%0lx, stats_size:%0lx ",
4448 : : ctx_count, ctx_split, stats_size);
4449 : 0 : priv->stats = rte_zmalloc("nfp_flow_stats",
4450 : : stats_size * sizeof(struct nfp_fl_stats), 0);
4451 [ # # ]: 0 : if (priv->stats == NULL) {
4452 : 0 : PMD_INIT_LOG(ERR, "flow stats creation failed");
4453 : 0 : ret = -ENOMEM;
4454 : 0 : goto free_stats_id;
4455 : : }
4456 : :
4457 : : /* Mask table */
4458 : 0 : mask_hash_params.hash_func_init_val = priv->hash_seed;
4459 : 0 : priv->mask_table = rte_hash_create(&mask_hash_params);
4460 [ # # ]: 0 : if (priv->mask_table == NULL) {
4461 : 0 : PMD_INIT_LOG(ERR, "mask hash table creation failed");
4462 : 0 : ret = -ENOMEM;
4463 : 0 : goto free_stats;
4464 : : }
4465 : :
4466 : : /* Flow table */
4467 : 0 : flow_hash_params.hash_func_init_val = priv->hash_seed;
4468 : 0 : flow_hash_params.entries = ctx_count;
4469 : 0 : priv->flow_table = rte_hash_create(&flow_hash_params);
4470 [ # # ]: 0 : if (priv->flow_table == NULL) {
4471 : 0 : PMD_INIT_LOG(ERR, "flow hash table creation failed");
4472 : 0 : ret = -ENOMEM;
4473 : 0 : goto free_mask_table;
4474 : : }
4475 : :
4476 : : /* Pre tunnel table */
4477 : 0 : priv->pre_tun_cnt = 1;
4478 : 0 : pre_tun_hash_params.hash_func_init_val = priv->hash_seed;
4479 : 0 : priv->pre_tun_table = rte_hash_create(&pre_tun_hash_params);
4480 [ # # ]: 0 : if (priv->pre_tun_table == NULL) {
4481 : 0 : PMD_INIT_LOG(ERR, "Pre tunnel table creation failed");
4482 : 0 : ret = -ENOMEM;
4483 : 0 : goto free_flow_table;
4484 : : }
4485 : :
4486 : : /* ct zone table */
4487 : 0 : ct_zone_hash_params.hash_func_init_val = priv->hash_seed;
4488 : 0 : priv->ct_zone_table = rte_hash_create(&ct_zone_hash_params);
4489 [ # # ]: 0 : if (priv->ct_zone_table == NULL) {
4490 : 0 : PMD_INIT_LOG(ERR, "ct zone table creation failed");
4491 : 0 : ret = -ENOMEM;
4492 : 0 : goto free_pre_tnl_table;
4493 : : }
4494 : :
4495 : : /* ct map table */
4496 : 0 : ct_map_hash_params.hash_func_init_val = priv->hash_seed;
4497 : 0 : ct_map_hash_params.entries = ctx_count;
4498 : 0 : priv->ct_map_table = rte_hash_create(&ct_map_hash_params);
4499 [ # # ]: 0 : if (priv->ct_map_table == NULL) {
4500 : 0 : PMD_INIT_LOG(ERR, "ct map table creation failed");
4501 : 0 : ret = -ENOMEM;
4502 : 0 : goto free_ct_zone_table;
4503 : : }
4504 : :
4505 : : /* IPv4 off list */
4506 : : rte_spinlock_init(&priv->ipv4_off_lock);
4507 : 0 : LIST_INIT(&priv->ipv4_off_list);
4508 : :
4509 : : /* IPv6 off list */
4510 : : rte_spinlock_init(&priv->ipv6_off_lock);
4511 : 0 : LIST_INIT(&priv->ipv6_off_list);
4512 : :
4513 : : /* Neighbor next list */
4514 : 0 : LIST_INIT(&priv->nn_list);
4515 : :
4516 : 0 : return 0;
4517 : :
4518 : : free_ct_zone_table:
4519 : 0 : rte_hash_free(priv->ct_zone_table);
4520 : 0 : free_pre_tnl_table:
4521 : 0 : rte_hash_free(priv->pre_tun_table);
4522 : 0 : free_flow_table:
4523 : 0 : rte_hash_free(priv->flow_table);
4524 : 0 : free_mask_table:
4525 : 0 : rte_hash_free(priv->mask_table);
4526 : 0 : free_stats:
4527 : 0 : rte_free(priv->stats);
4528 : 0 : free_stats_id:
4529 : 0 : rte_free(priv->stats_ids.free_list.buf);
4530 : 0 : free_mask_id:
4531 : 0 : rte_free(priv->mask_ids.free_list.buf);
4532 : 0 : free_priv:
4533 : 0 : rte_free(priv);
4534 : 0 : exit:
4535 : 0 : return ret;
4536 : : }
4537 : :
4538 : : void
4539 : 0 : nfp_flow_priv_uninit(struct nfp_pf_dev *pf_dev)
4540 : : {
4541 : : struct nfp_flow_priv *priv;
4542 : : struct nfp_app_fw_flower *app_fw_flower;
4543 : :
4544 : 0 : app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
4545 : 0 : priv = app_fw_flower->flow_priv;
4546 : :
4547 : 0 : rte_hash_free(priv->ct_map_table);
4548 : 0 : rte_hash_free(priv->ct_zone_table);
4549 : 0 : rte_hash_free(priv->pre_tun_table);
4550 : 0 : rte_hash_free(priv->flow_table);
4551 : 0 : rte_hash_free(priv->mask_table);
4552 : 0 : rte_free(priv->stats);
4553 : 0 : rte_free(priv->stats_ids.free_list.buf);
4554 : 0 : rte_free(priv->mask_ids.free_list.buf);
4555 : 0 : rte_free(priv);
4556 : 0 : }
|