NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_ct_tcp_ipv4_ipv6_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <unistd.h>
27 
28 #include <rte_ethdev.h>
29 
30 #include <doca_log.h>
31 #include <doca_flow.h>
32 #include <doca_flow_ct.h>
33 
34 #include "flow_ct_common.h"
35 #include "flow_common.h"
36 
37 #define PACKET_BURST 128
38 
39 static uint16_t sessions = 0;
40 
41 DOCA_LOG_REGISTER(FLOW_CT_TCP_IPV4_IPV6);
42 
43 /*
44  * Create RSS pipe
45  *
46  * @port [in]: Pipe port
47  * @status [in]: user context for adding entry
48  * @pipe [out]: Created pipe pointer
49  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
50  */
51 static doca_error_t create_rss_pipe(struct doca_flow_port *port,
52  struct entries_status *status,
53  struct doca_flow_pipe **pipe)
54 {
55  struct doca_flow_match match;
56  struct doca_flow_pipe_cfg *cfg;
57  struct doca_flow_fwd fwd;
58  uint16_t rss_queues[1];
60 
61  memset(&match, 0, sizeof(match));
62  memset(&fwd, 0, sizeof(fwd));
63 
65  if (result != DOCA_SUCCESS) {
66  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
67  return result;
68  }
69 
70  result = set_flow_pipe_cfg(cfg, "RSS_PIPE", DOCA_FLOW_PIPE_BASIC, false);
71  if (result != DOCA_SUCCESS) {
72  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
73  goto destroy_pipe_cfg;
74  }
76  if (result != DOCA_SUCCESS) {
77  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
78  goto destroy_pipe_cfg;
79  }
80 
81  /* RSS queue - send matched traffic to queue 0 */
82  rss_queues[0] = 0;
86  fwd.rss.nr_queues = 1;
87 
89  if (result != DOCA_SUCCESS) {
90  DOCA_LOG_ERR("Failed to create RSS pipe: %s", doca_error_get_descr(result));
91  goto destroy_pipe_cfg;
92  }
94 
95  /* Match on any packet */
96  result = doca_flow_pipe_add_entry(0, *pipe, &match, NULL, NULL, &fwd, 0, status, NULL);
97  if (result != DOCA_SUCCESS) {
98  DOCA_LOG_ERR("Failed to add RSS pipe entry: %s", doca_error_get_descr(result));
99  return result;
100  }
101 
103  if (result != DOCA_SUCCESS)
104  DOCA_LOG_ERR("Failed to process RSS entry: %s", doca_error_get_descr(result));
105 
106  return result;
107 
110  return result;
111 }
112 
113 /*
114  * Create egress pipe
115  *
116  * @port [in]: Pipe port
117  * @port_id [in]: Next pipe port id
118  * @status [in]: user context for adding entry
119  * @pipe [out]: Created pipe pointer
120  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
121  */
122 static doca_error_t create_egress_pipe(struct doca_flow_port *port,
123  int port_id,
124  struct entries_status *status,
125  struct doca_flow_pipe **pipe)
126 {
127  struct doca_flow_match match;
128  struct doca_flow_pipe_cfg *cfg;
129  struct doca_flow_fwd fwd;
131 
132  memset(&match, 0, sizeof(match));
133  memset(&fwd, 0, sizeof(fwd));
134 
136  if (result != DOCA_SUCCESS) {
137  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
138  return result;
139  }
140 
141  result = set_flow_pipe_cfg(cfg, "EGRESS_PIPE", DOCA_FLOW_PIPE_BASIC, false);
142  if (result != DOCA_SUCCESS) {
143  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
144  goto destroy_pipe_cfg;
145  }
147  if (result != DOCA_SUCCESS) {
148  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
149  goto destroy_pipe_cfg;
150  }
151 
153  fwd.port_id = port_id;
154 
156  if (result != DOCA_SUCCESS) {
157  DOCA_LOG_ERR("Failed to create EGRESS pipe: %s", doca_error_get_descr(result));
158  return result;
159  }
161 
162  /* Match on any packet */
163  result = doca_flow_pipe_add_entry(0, *pipe, &match, NULL, NULL, &fwd, 0, status, NULL);
164  if (result != DOCA_SUCCESS) {
165  DOCA_LOG_ERR("Failed to add EGRESS pipe entry: %s", doca_error_get_descr(result));
166  return result;
167  }
168 
170  if (result != DOCA_SUCCESS)
171  DOCA_LOG_ERR("Failed to process EGRESS entry: %s", doca_error_get_descr(result));
172 
173  return result;
174 
177  return result;
178 }
179 
180 /*
181  * Create CT miss pipe
182  *
183  * @port [in]: Pipe port
184  * @fwd_pipe [in]: Forward pipe pointer
185  * @status [in]: user context for adding entry
186  * @pipe [out]: Created pipe pointer
187  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
188  */
189 static doca_error_t create_ct_miss_pipe(struct doca_flow_port *port,
190  struct doca_flow_pipe *fwd_pipe,
191  struct entries_status *status,
192  struct doca_flow_pipe **pipe)
193 {
194  struct doca_flow_match match;
195  struct doca_flow_pipe_cfg *cfg;
196  struct doca_flow_fwd fwd;
197  struct doca_flow_fwd fwd_miss;
199 
200  memset(&match, 0, sizeof(match));
201  memset(&fwd, 0, sizeof(fwd));
202  memset(&fwd_miss, 0, sizeof(fwd));
203 
205  if (result != DOCA_SUCCESS) {
206  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
207  return result;
208  }
209 
210  result = set_flow_pipe_cfg(cfg, "CT_MISS_PIPE", DOCA_FLOW_PIPE_BASIC, false);
211  if (result != DOCA_SUCCESS) {
212  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
213  goto destroy_pipe_cfg;
214  }
216  if (result != DOCA_SUCCESS) {
217  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
218  goto destroy_pipe_cfg;
219  }
220 
222  fwd.next_pipe = fwd_pipe;
223 
225  fwd_miss.next_pipe = fwd_pipe;
226 
228  if (result != DOCA_SUCCESS) {
229  DOCA_LOG_ERR("Failed to create CT miss pipe: %s", doca_error_get_descr(result));
230  return result;
231  }
233 
234  /* Match on any packet */
235  result = doca_flow_pipe_add_entry(0, *pipe, &match, NULL, NULL, &fwd, 0, status, NULL);
236  if (result != DOCA_SUCCESS) {
237  DOCA_LOG_ERR("Failed to add CT miss pipe entry: %s", doca_error_get_descr(result));
238  return result;
239  }
240 
242  if (result != DOCA_SUCCESS)
243  DOCA_LOG_ERR("Failed to process CT miss entry: %s", doca_error_get_descr(result));
244 
245  return result;
246 
249  return result;
250 }
251 
252 /*
253  * Create DOCA Flow TCP state pipe to filter state on known TCP session
254  *
255  * @port [in]: Pipe port
256  * @status [in]: User context for adding entry
257  * @fwd_pipe [in]: Forward pipe
258  * @fwd_miss_pipe [in]: Forward miss pipe
259  * @pipe [out]: Created pipe pointer
260  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
261  */
262 static doca_error_t create_tcp_flags_filter_pipe(struct doca_flow_port *port,
263  struct entries_status *status,
264  struct doca_flow_pipe *fwd_pipe,
265  struct doca_flow_pipe *fwd_miss_pipe,
266  struct doca_flow_pipe **pipe)
267 {
268  struct doca_flow_match match;
269  struct doca_flow_match mask;
270  struct doca_flow_fwd fwd;
271  struct doca_flow_fwd fwd_miss;
272  struct doca_flow_pipe_cfg *cfg;
274 
275  memset(&match, 0, sizeof(match));
276  memset(&mask, 0, sizeof(mask));
277  memset(&fwd, 0, sizeof(fwd));
278  memset(&fwd_miss, 0, sizeof(fwd_miss));
279 
280  /* Match on non SYN, FIN and RST packets */
281  match.outer.tcp.flags = 0xff;
283 
287 
289  if (result != DOCA_SUCCESS) {
290  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
291  return result;
292  }
293 
294  result = set_flow_pipe_cfg(cfg, "TCP_FLAGS_FILTER_PIPE", DOCA_FLOW_PIPE_BASIC, false);
295  if (result != DOCA_SUCCESS) {
296  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
297  goto destroy_pipe_cfg;
298  }
299  result = doca_flow_pipe_cfg_set_match(cfg, &match, &mask);
300  if (result != DOCA_SUCCESS) {
301  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
302  goto destroy_pipe_cfg;
303  }
304 
306  fwd.next_pipe = fwd_pipe;
307 
309  fwd_miss.next_pipe = fwd_miss_pipe;
310 
312  if (result != DOCA_SUCCESS) {
313  DOCA_LOG_ERR("Failed to create TCP_FLAGS_FILTER pipe: %s", doca_error_get_descr(result));
314  return result;
315  }
317 
318  match.outer.tcp.flags = 0;
319  result = doca_flow_pipe_add_entry(0, *pipe, &match, NULL, NULL, NULL, 0, status, NULL);
320  if (result != DOCA_SUCCESS) {
321  DOCA_LOG_ERR("Failed to create TCP flags filter pipe entry: %s", doca_error_get_descr(result));
322  return result;
323  }
324 
326  if (result != DOCA_SUCCESS)
327  DOCA_LOG_ERR("Failed to process TCP flags filter entry: %s", doca_error_get_descr(result));
328 
329  return result;
330 
333  return result;
334 }
335 
336 /*
337  * Create CT pipe
338  *
339  * @port [in]: Pipe port
340  * @fwd_pipe [in]: Forward pipe pointer
341  * @fwd_miss_pipe [in]: Forward miss pipe pointer
342  * @pipe [out]: Created pipe pointer
343  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
344  */
345 static doca_error_t create_ct_pipe(struct doca_flow_port *port,
346  struct doca_flow_pipe *fwd_pipe,
347  struct doca_flow_pipe *fwd_miss_pipe,
348  struct doca_flow_pipe **pipe)
349 {
350  struct doca_flow_match match;
351  struct doca_flow_pipe_cfg *cfg;
352  struct doca_flow_fwd fwd;
353  struct doca_flow_fwd fwd_miss;
355 
356  memset(&match, 0, sizeof(match));
357  memset(&fwd, 0, sizeof(fwd));
358  memset(&fwd_miss, 0, sizeof(fwd));
359 
361  if (result != DOCA_SUCCESS) {
362  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
363  return result;
364  }
365 
366  result = set_flow_pipe_cfg(cfg, "CT_PIPE", DOCA_FLOW_PIPE_CT, false);
367  if (result != DOCA_SUCCESS) {
368  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
369  goto destroy_pipe_cfg;
370  }
372  if (result != DOCA_SUCCESS) {
373  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
374  goto destroy_pipe_cfg;
375  }
376 
378  fwd.next_pipe = fwd_pipe;
379 
381  fwd_miss.next_pipe = fwd_miss_pipe;
382 
384  if (result != DOCA_SUCCESS)
385  DOCA_LOG_ERR("Failed to create CT pipe: %s", doca_error_get_descr(result));
388  return result;
389 }
390 
391 /*
392  * Parse TCP packet to update CT tables
393  *
394  * @packet [in]: Packet to parse
395  * @match_o [out]: Origin match struct to fill
396  * @match_r [out]: Reply match struct to fill
397  * @tcp_state [out]: Packet TCP state
398  */
399 static void parse_packet(struct rte_mbuf *packet,
400  struct doca_flow_ct_match *match_o,
401  struct doca_flow_ct_match *match_r,
402  uint8_t *tcp_state)
403 {
404  static bool expect_ipv4_pkt = true;
405  *tcp_state = 0;
406  uint8_t *ip_hdr = rte_pktmbuf_mtod_offset(packet, uint8_t *, sizeof(struct rte_ether_hdr));
407 
408  if (expect_ipv4_pkt) {
409  uint8_t *l4_hdr;
410  struct rte_ipv4_hdr *ipv4_hdr = (struct rte_ipv4_hdr *)ip_hdr;
411  const struct rte_tcp_hdr *tcp_hdr;
412  doca_be32_t src_ipv6[] = {0x11111111, 0x11111111, 0x11111111, 0x11111111};
413  doca_be32_t dst_ipv6[] = {0x22222222, 0x22222222, 0x22222222, 0x22222222};
414 
415  if ((ip_hdr[0] >> 4) != 4)
416  return;
417 
418  /* initialize match origin with the extracted data from the ipv4 packet */
419  match_o->ipv4.src_ip = ipv4_hdr->src_addr;
420  match_o->ipv4.src_ip = ipv4_hdr->src_addr;
421 
422  l4_hdr = (typeof(l4_hdr))ipv4_hdr + rte_ipv4_hdr_len(ipv4_hdr);
423  tcp_hdr = (typeof(tcp_hdr))l4_hdr;
424 
425  match_o->ipv4.l4_port.src_port = tcp_hdr->src_port;
426  match_o->ipv4.l4_port.dst_port = tcp_hdr->dst_port;
428 
429  /* initialize match reply with data from other source, currently hard coded */
430  memcpy(match_r->ipv6.src_ip, src_ipv6, sizeof(src_ipv6));
431  memcpy(match_r->ipv6.dst_ip, dst_ipv6, sizeof(dst_ipv6));
432  match_r->ipv6.l4_port.src_port = match_o->ipv4.l4_port.dst_port;
433  match_r->ipv6.l4_port.dst_port = match_o->ipv4.l4_port.src_port;
435 
436  *tcp_state = tcp_hdr->tcp_flags;
437  expect_ipv4_pkt = false;
438  } else {
439  uint8_t *l6_hdr;
440  struct rte_ipv6_hdr *ipv6_hdr = (struct rte_ipv6_hdr *)ip_hdr;
441  const struct rte_tcp_hdr *tcp_hdr;
442 
443  if ((ip_hdr[0] >> 4) != 6)
444  return;
445 
446  l6_hdr = (typeof(l6_hdr))ipv6_hdr + sizeof(struct rte_ipv6_hdr);
447  tcp_hdr = (typeof(tcp_hdr))l6_hdr;
448 
449  *tcp_state = tcp_hdr->tcp_flags;
450  }
451 }
452 
453 /*
454  * Dequeue packets from DPDK queues, parse and update CT tables with new connection 5 tuple
455  *
456  * @port [in]: Port id to which an entry should be inserted
457  * @ct_queue [in]: DOCA Flow CT queue number
458  * @ct_status [in]: User context for adding CT entry
459  * @entry [in/out]: CT entry
460  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
461  */
462 static doca_error_t process_packets(struct doca_flow_port *port,
463  uint16_t ct_queue,
464  struct entries_status *ct_status,
465  struct doca_flow_pipe_entry **entry)
466 {
467  struct rte_mbuf *packets[PACKET_BURST];
468  struct doca_flow_ct_match match_o;
469  struct doca_flow_ct_match match_r;
475  uint8_t tcp_state;
477  int i, rc, nb_packets, nb_process = 0;
478  bool conn_exist = false;
479 
480  memset(&match_o, 0, sizeof(match_o));
481  memset(&match_r, 0, sizeof(match_r));
482 
483  rc = rte_flow_dynf_metadata_register();
484  if (unlikely(rc)) {
485  DOCA_LOG_ERR("Enable metadata failed");
486  return DOCA_ERROR_BAD_STATE;
487  }
488 
489  nb_packets = rte_eth_rx_burst(0, 0, packets, PACKET_BURST);
490  if (nb_packets == 0) {
491  DOCA_LOG_INFO("Sample didn't receive packets to process");
492  return DOCA_ERROR_BAD_STATE;
493  }
494 
495  DOCA_LOG_INFO("%d packets received on rx_burst()", nb_packets);
496  for (i = 0; i < PACKET_BURST && i < nb_packets; i++) {
497  parse_packet(packets[i], &match_o, &match_r, &tcp_state);
498  if (tcp_state & DOCA_FLOW_MATCH_TCP_FLAG_FIN || tcp_state & DOCA_FLOW_MATCH_TCP_FLAG_RST) {
499  if (sessions == 0) {
500  DOCA_LOG_INFO("No alive session to destroy, skip destroy");
501  continue;
502  }
503  result = doca_flow_ct_rm_entry(ct_queue, NULL, flags_rm, *entry);
504  if (result != DOCA_SUCCESS) {
505  DOCA_LOG_ERR("Failed to remove CT pipe entry: %s", doca_error_get_descr(result));
506  return result;
507  }
508  sessions--;
509  DOCA_LOG_INFO("TCP session was ended");
510  } else if (DOCA_FLOW_MATCH_TCP_FLAG_SYN) {
511  if (!tcp_state)
512  continue;
513 
514  /* Allocate CT entry */
516  NULL,
518  &match_o,
519  0,
520  &match_r,
521  0,
522  entry,
523  &conn_exist);
524  if (result != DOCA_SUCCESS) {
525  DOCA_LOG_ERR("Failed to prepare CT entry\n");
526  return result;
527  }
528  result = doca_flow_ct_add_entry(ct_queue,
529  NULL,
530  flags_o,
531  &match_o,
532  &match_r,
533  NULL,
534  NULL,
535  0,
536  0,
537  0,
538  ct_status,
539  *entry);
540  if (result != DOCA_SUCCESS) {
541  DOCA_LOG_ERR("Failed to add CT pipe an entry with origin only: %s",
543  return result;
544  }
545 
546  /* add IPV6 reply direction using internal info */
547  result = doca_flow_ct_entry_add_dir(ct_queue, NULL, flags_r, &match_r, NULL, 0, *entry);
548  if (result != DOCA_SUCCESS) {
549  DOCA_LOG_ERR("Failed to add CT pipe an reply IPv6 direction: %s",
551  return result;
552  }
553  sessions++;
554  nb_process++;
555 
556  while (ct_status->nb_processed != nb_process) {
557  result = doca_flow_ct_entries_process(port, ct_queue, 0, 0, NULL);
558  if (result != DOCA_SUCCESS) {
559  DOCA_LOG_ERR("Failed to process Flow CT entries: %s",
561  return result;
562  }
563 
564  if (ct_status->failure) {
565  DOCA_LOG_ERR("Flow CT entries process returned with a failure");
566  return DOCA_ERROR_BAD_STATE;
567  }
568  }
570  "Origin IPv4 + Reply IPv6 entries created, waiting for IPv6 'FIN' packet before ending the session");
571  } else {
572  DOCA_LOG_WARN("Sample is only able to process IPv4 'SYN', IPv6 'FIN'");
574  }
575  rte_flow_dynf_metadata_set(packets[i], 1);
576  packets[i]->ol_flags |= RTE_MBUF_DYNFLAG_TX_METADATA;
577  rte_eth_tx_burst(0, 0, &packets[i], 1);
578  }
579  ct_status->nb_processed = 0;
580 
581  return DOCA_SUCCESS;
582 }
583 
584 /*
585  * Run flow_ct_tcp_ipv4_ipv6 sample
586  *
587  * @nb_queues [in]: number of queues the sample will use
588  * @ct_dev [in]: Flow CT device
589  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
590  */
591 doca_error_t flow_ct_tcp_ipv4_ipv6(uint16_t nb_queues, struct doca_dev *ct_dev)
592 {
593  const int nb_ports = 2, nb_entries = 9;
594  struct flow_resources resource;
595  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
596  struct doca_flow_pipe_entry *tcp_entry;
597  struct doca_flow_pipe *egress_pipe, *ct_miss_pipe, *tcp_flags_filter_pipe, *rss_pipe, *tcp_pipe;
598  struct doca_flow_pipe *ct_pipe = NULL;
599  struct doca_flow_port *ports[nb_ports];
600  struct doca_flow_meta o_zone_mask, o_modify_mask, r_zone_mask, r_modify_mask;
601  struct doca_dev *dev_arr[nb_ports];
602  uint32_t actions_mem_size[nb_ports];
603  struct entries_status ctrl_status, ct_status;
604  uint32_t ct_flags, nb_arm_queues = 1, nb_ctrl_queues = 1, nb_user_actions = 0, nb_ipv4_sessions = 1024,
605  nb_ipv6_sessions = 2048;
606  uint16_t ct_queue = nb_queues;
608 
609  memset(&ctrl_status, 0, sizeof(ctrl_status));
610  memset(&ct_status, 0, sizeof(ct_status));
611  memset(&resource, 0, sizeof(resource));
612 
613  resource.nr_counters = 1;
614 
615  result = init_doca_flow(nb_queues, "switch,hws", &resource, nr_shared_resources);
616  if (result != DOCA_SUCCESS) {
617  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
618  return result;
619  }
620 
621  /* Dont use zone masking */
622  memset(&o_zone_mask, 0, sizeof(o_zone_mask));
623  memset(&o_modify_mask, 0, sizeof(o_modify_mask));
624  memset(&r_zone_mask, 0, sizeof(r_zone_mask));
625  memset(&r_modify_mask, 0, sizeof(r_modify_mask));
626 
628  result = init_doca_flow_ct(ct_flags,
629  nb_arm_queues,
630  nb_ctrl_queues,
631  nb_user_actions,
632  NULL,
633  nb_ipv4_sessions,
634  nb_ipv6_sessions,
635  0,
636  false,
637  &o_zone_mask,
638  &o_modify_mask,
639  true,
640  &r_zone_mask,
641  &r_modify_mask);
642  if (result != DOCA_SUCCESS) {
644  return result;
645  }
646 
647  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
648  dev_arr[0] = ct_dev;
651  if (result != DOCA_SUCCESS) {
652  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
655  return result;
656  }
657 
658  result = create_rss_pipe(ports[0], &ctrl_status, &rss_pipe);
659  if (result != DOCA_SUCCESS)
660  goto cleanup;
661 
662  result = create_egress_pipe(ports[0], 1, &ctrl_status, &egress_pipe);
663  if (result != DOCA_SUCCESS)
664  goto cleanup;
665 
666  result = create_tcp_flags_filter_pipe(ports[0], &ctrl_status, egress_pipe, rss_pipe, &tcp_flags_filter_pipe);
667  if (result != DOCA_SUCCESS)
668  goto cleanup;
669 
670  result = create_ct_miss_pipe(ports[0], rss_pipe, &ctrl_status, &ct_miss_pipe);
671  if (result != DOCA_SUCCESS)
672  goto cleanup;
673 
674  result = create_ct_pipe(ports[0], tcp_flags_filter_pipe, ct_miss_pipe, &ct_pipe);
675  if (result != DOCA_SUCCESS)
676  goto cleanup;
677 
678  result = create_ct_root_pipe(ports[0], true, true, DOCA_FLOW_L4_META_TCP, ct_pipe, &ctrl_status, &tcp_pipe);
679  if (result != DOCA_SUCCESS)
680  goto cleanup;
681 
683  if (result != DOCA_SUCCESS) {
684  DOCA_LOG_ERR("Failed to process Flow CT entries: %s", doca_error_get_descr(result));
685  goto cleanup;
686  }
687  if (ctrl_status.nb_processed != nb_entries || ctrl_status.failure) {
688  DOCA_LOG_ERR("Failed to process entries");
690  goto cleanup;
691  }
692 
693  DOCA_LOG_INFO("Wait few seconds for 'SYN' packet ipv4 to arrive");
694 
695  sleep(5);
696  result = process_packets(ports[0], ct_queue, &ct_status, &tcp_entry);
697  if (result != DOCA_SUCCESS)
698  goto cleanup;
699 
700  sleep(7);
701  result = process_packets(ports[0], ct_queue, &ct_status, &tcp_entry);
702  if (result != DOCA_SUCCESS)
703  goto cleanup;
704 
705 cleanup:
706  cleanup_procedure(ct_pipe, nb_ports, ports);
707  return result;
708 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
struct doca_flow_port * init_doca_flow(uint16_t port_id, uint8_t rxq_num)
Definition: flow.c:37
static void cleanup(struct cache_invalidate_sample_state *state)
#define unlikely(x)
Definition: utils.h:42
doca_error_t init_doca_flow_ct(uint32_t flags, uint32_t nb_arm_queues, uint32_t nb_ctrl_queues, uint32_t nb_user_actions, doca_flow_ct_entry_finalize_cb entry_finalize_cb, uint32_t nb_ipv4_sessions, uint32_t nb_ipv6_sessions, uint32_t dup_filter_sz, bool o_match_inner, struct doca_flow_meta *o_zone_mask, struct doca_flow_meta *o_modify_mask, bool r_match_inner, struct doca_flow_meta *r_zone_mask, struct doca_flow_meta *r_modify_mask)
doca_error_t create_ct_root_pipe(struct doca_flow_port *port, bool is_ipv4, bool is_ipv6, enum doca_flow_l4_meta l4_type, struct doca_flow_pipe *fwd_pipe, struct entries_status *status, struct doca_flow_pipe **pipe)
void cleanup_procedure(struct doca_flow_pipe *ct_pipe, int nb_ports, struct doca_flow_port *ports[])
static int nb_entries
DOCA_LOG_REGISTER(FLOW_CT_TCP_IPV4_IPV6)
#define PACKET_BURST
doca_error_t flow_ct_tcp_ipv4_ipv6(uint16_t nb_queues, struct doca_dev *ct_dev)
static doca_error_t create_ct_pipe(struct doca_flow_port *port, struct doca_flow_pipe *fwd_pipe, struct doca_flow_pipe *fwd_miss_pipe, struct doca_flow_pipe **pipe)
static doca_error_t process_packets(struct doca_flow_port *port, uint16_t ct_queue, struct entries_status *ct_status, struct doca_flow_pipe_entry **entry)
static doca_error_t create_rss_pipe(struct doca_flow_port *port, struct entries_status *status, struct doca_flow_pipe **pipe)
static doca_error_t create_egress_pipe(struct doca_flow_port *port, int port_id, struct entries_status *status, struct doca_flow_pipe **pipe)
static doca_error_t create_ct_miss_pipe(struct doca_flow_port *port, struct doca_flow_pipe *fwd_pipe, struct entries_status *status, struct doca_flow_pipe **pipe)
static doca_error_t create_tcp_flags_filter_pipe(struct doca_flow_port *port, struct entries_status *status, struct doca_flow_pipe *fwd_pipe, struct doca_flow_pipe *fwd_miss_pipe, struct doca_flow_pipe **pipe)
static void parse_packet(struct rte_mbuf *packet, struct doca_flow_ct_match *match_o, struct doca_flow_ct_match *match_r, uint8_t *tcp_state)
static uint16_t sessions
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static struct doca_flow_fwd fwd_miss
Definition: flow_parser.c:110
static uint16_t * rss_queues
Definition: flow_parser.c:114
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_BAD_STATE
Definition: doca_error.h:56
@ DOCA_ERROR_NOT_SUPPORTED
Definition: doca_error.h:42
@ DOCA_SUCCESS
Definition: doca_error.h:38
DOCA_EXPERIMENTAL doca_error_t doca_flow_ct_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint32_t min_room, uint32_t max_processed_entries, uint32_t *queue_room)
Process CT entries in queue.
DOCA_EXPERIMENTAL doca_error_t doca_flow_ct_add_entry(uint16_t queue, struct doca_flow_pipe *pipe, uint32_t flags, struct doca_flow_ct_match *match_origin, struct doca_flow_ct_match *match_reply, const struct doca_flow_ct_actions *actions_origin, const struct doca_flow_ct_actions *actions_reply, uint32_t fwd_handle_origin, uint32_t fwd_handle_reply, uint32_t timeout_s, void *usr_ctx, struct doca_flow_pipe_entry *entry)
Add new entry to doca flow CT pipe.
DOCA_EXPERIMENTAL void doca_flow_ct_destroy(void)
Destroy the doca flow ct.
DOCA_EXPERIMENTAL doca_error_t doca_flow_ct_rm_entry(uint16_t queue, struct doca_flow_pipe *pipe, uint32_t flags, struct doca_flow_pipe_entry *entry)
remove CT entry.
DOCA_EXPERIMENTAL doca_error_t doca_flow_ct_entry_prepare(uint16_t queue, struct doca_flow_pipe *pipe, uint32_t flags, struct doca_flow_ct_match *match_origin, uint32_t hash_origin, struct doca_flow_ct_match *match_reply, uint32_t hash_reply, struct doca_flow_pipe_entry **entry, bool *conn_found)
Lookup recent CT entry and create on miss.
DOCA_EXPERIMENTAL doca_error_t doca_flow_ct_entry_add_dir(uint16_t queue, struct doca_flow_pipe *pipe, uint32_t flags, struct doca_flow_ct_match *match, const struct doca_flow_ct_actions *actions, uint32_t fwd_handle, struct doca_flow_pipe_entry *entry)
Add missing direction rule to CT connection.
@ DOCA_FLOW_CT_ENTRY_FLAGS_DIR_ORIGIN
Definition: doca_flow_ct.h:667
@ DOCA_FLOW_CT_ENTRY_FLAGS_IPV6_REPLY
Definition: doca_flow_ct.h:673
@ DOCA_FLOW_CT_ENTRY_FLAGS_NO_WAIT
Definition: doca_flow_ct.h:665
@ DOCA_FLOW_CT_ENTRY_FLAGS_DIR_REPLY
Definition: doca_flow_ct.h:669
@ DOCA_FLOW_CT_ENTRY_FLAGS_ALLOC_ON_MISS
Definition: doca_flow_ct.h:683
@ DOCA_FLOW_CT_FLAG_NO_AGING
Definition: doca_flow_ct.h:58
@ DOCA_FLOW_CT_FLAG_ASYMMETRIC_TUNNEL
Definition: doca_flow_ct.h:59
#define DOCA_FLOW_PROTO_TCP
Definition: doca_flow_net.h:41
@ DOCA_FLOW_L4_TYPE_EXT_TCP
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_destroy(struct doca_flow_pipe_cfg *cfg)
Destroy DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_create(struct doca_flow_pipe_cfg **cfg, struct doca_flow_port *port)
Create DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_add_entry(uint16_t pipe_queue, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_actions *actions, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a pipe.
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
@ DOCA_FLOW_PIPE_CT
Definition: doca_flow.h:227
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_MATCH_TCP_FLAG_FIN
Definition: doca_flow.h:403
@ DOCA_FLOW_MATCH_TCP_FLAG_RST
Definition: doca_flow.h:407
@ DOCA_FLOW_MATCH_TCP_FLAG_SYN
Definition: doca_flow.h:405
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
Definition: doca_flow.h:615
@ DOCA_FLOW_FWD_PORT
Definition: doca_flow.h:744
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_FWD_RSS
Definition: doca_flow.h:742
@ DOCA_FLOW_L4_META_TCP
Definition: doca_flow.h:308
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
Definition: doca_log.h:476
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
uint32_t doca_be32_t
Definition: doca_types.h:121
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
struct tcp_hdr l4_hdr
Definition: packets.h:2
doca_error_t init_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin, struct doca_dev *dev_arr[], uint32_t actions_mem_size[])
Definition: flow_common.c:296
doca_error_t set_flow_pipe_cfg(struct doca_flow_pipe_cfg *cfg, const char *name, enum doca_flow_pipe_type type, bool is_root)
Definition: flow_common.c:305
#define SHARED_RESOURCE_NUM_VALUES
Definition: flow_common.h:59
#define ACTIONS_MEM_SIZE(nr_queues, entries)
Definition: flow_common.h:66
#define ARRAY_INIT(array, val)
Definition: flow_common.h:71
struct doca_flow_header_l4_port l4_port
Definition: doca_flow_ct.h:623
doca_be32_t src_ip
Definition: doca_flow_ct.h:625
struct doca_flow_header_l4_port l4_port
Definition: doca_flow_ct.h:639
doca_be32_t src_ip[4]
Definition: doca_flow_ct.h:641
doca_be32_t dst_ip[4]
Definition: doca_flow_ct.h:643
doca flow CT match pattern
Definition: doca_flow_ct.h:654
struct doca_flow_ct_match4 ipv4
Definition: doca_flow_ct.h:656
struct doca_flow_ct_match6 ipv6
Definition: doca_flow_ct.h:657
forwarding configuration
Definition: doca_flow.h:779
struct doca_flow_pipe * next_pipe
Definition: doca_flow.h:800
struct doca_flow_pipe * pipe
Definition: doca_flow.h:806
uint16_t port_id
Definition: doca_flow.h:795
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
enum doca_flow_resource_type rss_type
Definition: doca_flow.h:784
struct doca_flow_resource_rss_cfg rss
Definition: doca_flow.h:787
enum doca_flow_l4_type_ext l4_type_ext
Definition: doca_flow.h:454
struct doca_flow_header_tcp tcp
Definition: doca_flow.h:461
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_header_format outer
Definition: doca_flow.h:498
doca flow meta data
Definition: doca_flow.h:358
user context struct that will be used in entries process callback
Definition: flow_common.h:78
uint32_t nr_counters
Definition: flow_common.h:96
uint32_t src_addr
Definition: packets.h:75
uint16_t src_port
Definition: packets.h:80
uint8_t tcp_flags
Definition: packets.h:85
uint16_t dst_port
Definition: packets.h:81
static int nb_ports
Definition: switch_core.c:44
static uint32_t actions_mem_size[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:43
static struct doca_flow_port * ports[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:42