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