NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_ct_udp_update_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 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 DOCA_LOG_REGISTER(FLOW_CT_UDP_UPDATE);
40 
41 /*
42  * Entry processing callback
43  *
44  * @entry [in]: DOCA Flow entry pointer
45  * @pipe_queue [in]: queue identifier
46  * @status [in]: DOCA Flow entry status
47  * @op [in]: DOCA Flow entry operation
48  * @user_ctx [out]: user context
49  */
50 static void check_for_valid_entry_aging(struct doca_flow_pipe_entry *entry,
51  uint16_t pipe_queue,
52  enum doca_flow_entry_status status,
53  enum doca_flow_entry_op op,
54  void *user_ctx)
55 {
56  (void)entry;
57  (void)op;
58  (void)pipe_queue;
59  struct entries_status *entry_status = (struct entries_status *)user_ctx;
60 
61  if (entry_status == NULL)
62  return;
63 
64  if (status != DOCA_FLOW_ENTRY_STATUS_SUCCESS)
65  entry_status->failure = true; /* set failure to true if processing failed */
66  if (op == DOCA_FLOW_ENTRY_OP_AGED) {
68  DOCA_LOG_INFO("Entry aged out and removed");
69  } else
70  entry_status->nb_processed++;
71 }
72 
73 /*
74  * Create RSS pipe
75  *
76  * @port [in]: Pipe port
77  * @status [in]: User context for adding entry
78  * @pipe [out]: Created pipe pointer
79  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
80  */
81 static doca_error_t create_rss_pipe(struct doca_flow_port *port,
82  struct entries_status *status,
83  struct doca_flow_pipe **pipe)
84 {
85  struct doca_flow_match match;
86  struct doca_flow_pipe_cfg *cfg;
87  struct doca_flow_fwd fwd;
88  uint16_t rss_queues[1];
90 
91  memset(&match, 0, sizeof(match));
92  memset(&fwd, 0, sizeof(fwd));
93 
95  if (result != DOCA_SUCCESS) {
96  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
97  return result;
98  }
99 
100  result = set_flow_pipe_cfg(cfg, "RSS_PIPE", DOCA_FLOW_PIPE_BASIC, false);
101  if (result != DOCA_SUCCESS) {
102  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
103  goto destroy_pipe_cfg;
104  }
106  if (result != DOCA_SUCCESS) {
107  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
108  goto destroy_pipe_cfg;
109  }
110 
111  /* RSS queue - send matched traffic to queue 0 */
112  rss_queues[0] = 0;
117  fwd.rss.nr_queues = 1;
118 
120  if (result != DOCA_SUCCESS) {
121  DOCA_LOG_ERR("Failed to create RSS pipe: %s", doca_error_get_descr(result));
122  goto destroy_pipe_cfg;
123  }
125 
126  /* Match on any packet */
127  result = doca_flow_pipe_add_entry(0, *pipe, &match, NULL, NULL, &fwd, 0, status, NULL);
128  if (result != DOCA_SUCCESS) {
129  DOCA_LOG_ERR("Failed to add RSS pipe entry: %s", doca_error_get_descr(result));
130  return result;
131  }
132 
134  if (result != DOCA_SUCCESS)
135  DOCA_LOG_ERR("Failed to process RSS entry: %s", doca_error_get_descr(result));
136 
137  return result;
138 
141  return result;
142 }
143 
144 /*
145  * Create CT pipe
146  *
147  * @port [in]: Pipe port
148  * @fwd_pipe [in]: Forward pipe pointer
149  * @fwd_miss_pipe [in]: Forward miss pipe pointer
150  * @pipe [out]: Created pipe pointer
151  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
152  */
153 static doca_error_t create_ct_pipe(struct doca_flow_port *port,
154  struct doca_flow_pipe *fwd_pipe,
155  struct doca_flow_pipe *fwd_miss_pipe,
156  struct doca_flow_pipe **pipe)
157 {
158  struct doca_flow_match match;
159  struct doca_flow_match mask;
160  struct doca_flow_pipe_cfg *cfg;
161  struct doca_flow_fwd fwd;
162  struct doca_flow_fwd fwd_miss;
164 
165  memset(&match, 0, sizeof(match));
166  memset(&mask, 0, sizeof(mask));
167  memset(&fwd, 0, sizeof(fwd));
168  memset(&fwd_miss, 0, sizeof(fwd));
169 
171  if (result != DOCA_SUCCESS) {
172  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
173  return result;
174  }
175 
176  result = set_flow_pipe_cfg(cfg, "CT_PIPE", DOCA_FLOW_PIPE_CT, false);
177  if (result != DOCA_SUCCESS) {
178  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
179  goto destroy_pipe_cfg;
180  }
181  result = doca_flow_pipe_cfg_set_match(cfg, &match, &mask);
182  if (result != DOCA_SUCCESS) {
183  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
184  goto destroy_pipe_cfg;
185  }
186 
188  fwd.next_pipe = fwd_pipe;
189 
191  fwd_miss.next_pipe = fwd_miss_pipe;
192 
194  if (result != DOCA_SUCCESS)
195  DOCA_LOG_ERR("Failed to add CT pipe: %s", doca_error_get_descr(result));
198  return result;
199 }
200 
201 /*
202  * Create VxLAN encapsulation pipe
203  *
204  * @port [in]: Pipe port
205  * @port_id [in]: Forward port ID
206  * @status [in]: User context for adding entry
207  * @pipe [out]: Created pipe pointer
208  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
209  */
210 static doca_error_t create_vxlan_encap_pipe(struct doca_flow_port *port,
211  int port_id,
212  struct entries_status *status,
213  struct doca_flow_pipe **pipe)
214 {
215  struct doca_flow_match match;
216  struct doca_flow_actions actions;
217  struct doca_flow_actions *actions_list[] = {&actions};
218  struct doca_flow_fwd fwd;
219  struct doca_flow_pipe_cfg *pipe_cfg;
220  uint8_t src_mac[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
221  uint8_t dst_mac[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
223 
224  memset(&match, 0, sizeof(match));
225  memset(&actions, 0, sizeof(actions));
226  memset(&fwd, 0, sizeof(fwd));
227 
228  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
229  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
231  actions.encap_cfg.encap.outer.ip4.src_ip = 0xffffffff;
232  actions.encap_cfg.encap.outer.ip4.dst_ip = 0xffffffff;
237  actions.encap_cfg.encap.tun.vxlan_tun_id = 0xffffffff;
239  actions.encap_cfg.is_l2 = true;
240 
241  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
242  if (result != DOCA_SUCCESS) {
243  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
244  return result;
245  }
246 
247  result = set_flow_pipe_cfg(pipe_cfg, "VXLAN_ENCAP_PIPE", DOCA_FLOW_PIPE_BASIC, true);
248  if (result != DOCA_SUCCESS) {
249  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
250  goto destroy_pipe_cfg;
251  }
253  if (result != DOCA_SUCCESS) {
254  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
255  goto destroy_pipe_cfg;
256  }
257  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
258  if (result != DOCA_SUCCESS) {
259  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
260  goto destroy_pipe_cfg;
261  }
262  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_list, NULL, NULL, 1);
263  if (result != DOCA_SUCCESS) {
264  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
265  goto destroy_pipe_cfg;
266  }
267 
269  fwd.port_id = port_id;
270 
271  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
272  if (result != DOCA_SUCCESS) {
273  DOCA_LOG_ERR("Failed to create VxLAN Encap pipe: %s", doca_error_get_descr(result));
274  goto destroy_pipe_cfg;
275  }
276  doca_flow_pipe_cfg_destroy(pipe_cfg);
277 
278  memset(&actions, 0, sizeof(actions));
280  src_mac[0],
281  src_mac[1],
282  src_mac[2],
283  src_mac[3],
284  src_mac[4],
285  src_mac[5]);
287  dst_mac[0],
288  dst_mac[1],
289  dst_mac[2],
290  dst_mac[3],
291  dst_mac[4],
292  dst_mac[5]);
293  actions.encap_cfg.encap.outer.ip4.src_ip = BE_IPV4_ADDR(11, 21, 31, 41);
294  actions.encap_cfg.encap.outer.ip4.dst_ip = BE_IPV4_ADDR(81, 81, 81, 81);
297  actions.action_idx = 0;
298 
299  result = doca_flow_pipe_add_entry(0, *pipe, &match, &actions, NULL, NULL, 0, status, NULL);
300  if (result != DOCA_SUCCESS) {
301  DOCA_LOG_ERR("Failed to add VxLAN Encap pipe entry: %s", doca_error_get_descr(result));
302  return result;
303  }
304 
306  if (result != DOCA_SUCCESS)
307  DOCA_LOG_ERR("Failed to process UDP entry: %s", doca_error_get_descr(result));
308 
309  return result;
310 
312  doca_flow_pipe_cfg_destroy(pipe_cfg);
313  return result;
314 }
315 
316 /*
317  * Create pipe to count packets based on 5 tuple match
318  *
319  * @port [in]: Pipe port
320  * @fwd_pipe [in]: Next pipe pointer
321  * @status [in]: User context for adding entry
322  * @pipe [out]: Created pipe pointer
323  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
324  */
325 static doca_error_t create_count_pipe(struct doca_flow_port *port,
326  struct doca_flow_pipe *fwd_pipe,
327  struct entries_status *status,
328  struct doca_flow_pipe **pipe)
329 {
330  struct doca_flow_match match;
331  struct doca_flow_monitor monitor;
332  struct doca_flow_fwd fwd;
333  struct doca_flow_fwd fwd_miss;
334  struct doca_flow_pipe_cfg *pipe_cfg;
336 
337  memset(&match, 0, sizeof(match));
338  memset(&monitor, 0, sizeof(monitor));
339  memset(&fwd, 0, sizeof(fwd));
340  memset(&fwd_miss, 0, sizeof(fwd_miss));
341 
342  /* 5 tuple match */
347  match.outer.ip4.src_ip = 0xffffffff;
348  match.outer.ip4.dst_ip = 0xffffffff;
349  match.outer.udp.l4_port.src_port = 0xffff;
350  match.outer.udp.l4_port.dst_port = 0xffff;
351 
353 
354  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
355  if (result != DOCA_SUCCESS) {
356  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
357  return result;
358  }
359 
360  result = set_flow_pipe_cfg(pipe_cfg, "COUNT_PIPE", DOCA_FLOW_PIPE_BASIC, false);
361  if (result != DOCA_SUCCESS) {
362  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
363  goto destroy_pipe_cfg;
364  }
365  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
366  if (result != DOCA_SUCCESS) {
367  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
368  goto destroy_pipe_cfg;
369  }
371  if (result != DOCA_SUCCESS) {
372  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
373  goto destroy_pipe_cfg;
374  }
375 
377  fwd.next_pipe = fwd_pipe;
378 
380  fwd_miss.next_pipe = fwd_pipe;
381 
382  result = doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, pipe);
383  if (result != DOCA_SUCCESS) {
384  DOCA_LOG_ERR("Failed to create count pipe: %s", doca_error_get_descr(result));
385  goto destroy_pipe_cfg;
386  }
387  doca_flow_pipe_cfg_destroy(pipe_cfg);
388 
389  memset(&match, 0, sizeof(match));
390  match.outer.ip4.dst_ip = BE_IPV4_ADDR(8, 8, 8, 8);
391  match.outer.ip4.src_ip = BE_IPV4_ADDR(1, 2, 3, 4);
392  match.outer.udp.l4_port.dst_port = rte_cpu_to_be_16(80);
393  match.outer.udp.l4_port.src_port = rte_cpu_to_be_16(1234);
394 
395  result = doca_flow_pipe_add_entry(0, *pipe, &match, NULL, NULL, NULL, 0, status, NULL);
396  if (result != DOCA_SUCCESS) {
397  DOCA_LOG_ERR("Failed to add count pipe entry: %s", doca_error_get_descr(result));
398  return result;
399  }
400 
402  if (result != DOCA_SUCCESS)
403  DOCA_LOG_ERR("Failed to process count entry: %s", doca_error_get_descr(result));
404 
405  return result;
406 
408  doca_flow_pipe_cfg_destroy(pipe_cfg);
409  return result;
410 }
411 
412 /*
413  * Parse UDP packet to update CT tables
414  *
415  * @packet [in]: Packet to parse
416  * @match_o [out]: Origin match struct to fill
417  * @match_r [out]: Reply match struct to fill
418  */
419 static void parse_packet(struct rte_mbuf *packet,
420  struct doca_flow_ct_match *match_o,
421  struct doca_flow_ct_match *match_r)
422 {
423  uint8_t *l4_hdr;
424  struct rte_ipv4_hdr *ipv4_hdr;
425  const struct rte_udp_hdr *udp_hdr;
426 
427  ipv4_hdr = rte_pktmbuf_mtod_offset(packet, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
428 
429  match_o->ipv4.src_ip = ipv4_hdr->src_addr;
430  match_o->ipv4.dst_ip = ipv4_hdr->dst_addr;
431  match_r->ipv4.src_ip = match_o->ipv4.dst_ip;
432  match_r->ipv4.dst_ip = match_o->ipv4.src_ip;
433 
434  l4_hdr = (typeof(l4_hdr))ipv4_hdr + rte_ipv4_hdr_len(ipv4_hdr);
435  udp_hdr = (typeof(udp_hdr))l4_hdr;
436 
437  match_o->ipv4.l4_port.src_port = udp_hdr->src_port;
438  match_o->ipv4.l4_port.dst_port = udp_hdr->dst_port;
439  match_r->ipv4.l4_port.src_port = match_o->ipv4.l4_port.dst_port;
440  match_r->ipv4.l4_port.dst_port = match_o->ipv4.l4_port.src_port;
441 
444 }
445 
446 /*
447  * Dequeue packets from DPDK queues, parse and update CT tables with new connection 5 tuple
448  *
449  * @port [in]: Port id to which an entry should be inserted
450  * @ct_queue [in]: DOCA Flow CT queue number
451  * @ct_status [in]: User context for adding CT entry
452  * @ct_entries_arr [out]: DOCA Flow CT entries array
453  * @ct_entries_arr_len [out]: DOCA Flow CT entries array length
454  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
455  */
456 static doca_error_t process_packets(struct doca_flow_port *port,
457  uint16_t ct_queue,
458  struct entries_status *ct_status,
459  struct doca_flow_pipe_entry *ct_entries_arr[PACKET_BURST],
460  int *ct_entries_arr_len)
461 {
462  struct rte_mbuf *packets[PACKET_BURST];
463  struct doca_flow_ct_match match_o;
464  struct doca_flow_ct_match match_r;
465  uint32_t flags;
467  int i, entries, nb_packets;
468  bool conn_found = false;
469 
470  memset(&match_o, 0, sizeof(match_o));
471  memset(&match_r, 0, sizeof(match_r));
472 
473  nb_packets = rte_eth_rx_burst(0, 0, packets, PACKET_BURST);
474  if (nb_packets == 0) {
475  DOCA_LOG_INFO("Sample didn't receive packets to process");
476  return DOCA_ERROR_BAD_STATE;
477  }
478 
479  entries = 0;
480  DOCA_LOG_INFO("Sample received %d packets", nb_packets);
481  for (i = 0; i < PACKET_BURST && i < nb_packets; i++) {
482  parse_packet(packets[i], &match_o, &match_r);
485  /* Allocate CT entry */
487  NULL,
488  flags,
489  &match_o,
490  packets[i]->hash.rss,
491  &match_r,
492  packets[i]->hash.rss,
493  &ct_entries_arr[i],
494  &conn_found);
495  if (result != DOCA_SUCCESS) {
496  DOCA_LOG_ERR("Failed to prepare CT entry\n");
497  return result;
498  }
499 
500  if (!conn_found) {
504  result = doca_flow_ct_add_entry(ct_queue,
505  NULL,
506  flags,
507  &match_o,
508  &match_r,
509  NULL,
510  NULL,
511  0,
512  0,
513  0,
514  ct_status,
515  ct_entries_arr[i]);
516  if (result != DOCA_SUCCESS) {
517  DOCA_LOG_ERR("Failed to add CT pipe an entry: %s", doca_error_get_descr(result));
518  return result;
519  }
520  entries++;
521  }
522  }
523 
524  while (ct_status->nb_processed != entries) {
525  result = doca_flow_ct_entries_process(port, ct_queue, 0, 0, NULL);
526  if (result != DOCA_SUCCESS) {
527  DOCA_LOG_ERR("Failed to process Flow CT entries: %s", doca_error_get_descr(result));
528  return result;
529  }
530 
531  if (ct_status->failure) {
532  DOCA_LOG_ERR("Flow CT entries process returned with a failure");
533  return DOCA_ERROR_BAD_STATE;
534  }
535  }
536 
537  *ct_entries_arr_len = entries;
538 
539  return DOCA_SUCCESS;
540 }
541 
542 /*
543  * Update non-active session with aging timeout
544  *
545  * @port [in]: Port id to which an entry should be inserted
546  * @ct_pipe [in]: DOCA Flow CT pipe
547  * @entries_arr [in]: CT entries array
548  * @entries_arr_len [in]: CT entries array length
549  * @ct_queue [in]: DOCA Flow CT queue number
550  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
551  */
552 static doca_error_t update_nonactive_entries(struct doca_flow_port *port,
553  struct doca_flow_pipe *ct_pipe,
554  struct doca_flow_pipe_entry **entries_arr,
555  int entries_arr_len,
556  uint16_t ct_queue)
557 {
558  struct doca_flow_resource_query query_o, query_r;
559  uint64_t last_hit_s = 0;
560  uint32_t aging_s = 2, flags = DOCA_FLOW_CT_ENTRY_FLAGS_NO_WAIT;
562  int i, aging_res, aged_entry_counter = 0, nb_aged_entries = 0;
563 
564  for (i = 0; i < entries_arr_len; i++) {
565  result = doca_flow_ct_query_entry(ct_queue,
566  ct_pipe,
567  flags,
568  entries_arr[i],
569  &query_o,
570  &query_r,
571  &last_hit_s);
572  if (result != DOCA_SUCCESS) {
573  DOCA_LOG_ERR("Failed to query CT entry: %s", doca_error_get_descr(result));
574  return result;
575  }
576 
577  /* Nonactive session should be aged and deleted */
578  if (query_o.counter.total_pkts == 0 && query_r.counter.total_pkts == 0) {
579  result = doca_flow_ct_update_entry(ct_queue, NULL, flags, entries_arr[i], 0, 0, 0, 0, aging_s);
580  if (result != DOCA_SUCCESS) {
581  DOCA_LOG_ERR("Failed to query CT entry: %s", doca_error_get_descr(result));
582  return result;
583  }
584  nb_aged_entries++;
585  }
586  }
587 
588  /* handle aging in loop until all entries aged out */
589  while (aged_entry_counter < nb_aged_entries) {
590  result = doca_flow_ct_entries_process(port, ct_queue, 0, 0, NULL);
591  if (result != DOCA_SUCCESS) {
592  DOCA_LOG_ERR("Failed to process CT entries: %s", doca_error_get_descr(result));
593  break;
594  }
595  sleep(0);
596  aging_res = doca_flow_aging_handle(port, ct_queue, 0, 0);
597  if (aging_res > 0)
598  aged_entry_counter += aging_res;
599  }
600 
601  return DOCA_SUCCESS;
602 }
603 
604 /*
605  * Run flow_ct_udp_update sample
606  *
607  * @nb_queues [in]: number of queues the sample will use
608  * @ct_dev [in]: Flow CT device
609  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
610  */
611 doca_error_t flow_ct_udp_update(uint16_t nb_queues, struct doca_dev *ct_dev)
612 {
613  const int nb_ports = 2, nb_entries = 6;
614  int ct_entries_arr_len = 0;
615  struct flow_resources resource;
616  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
617  struct doca_flow_pipe_entry *ct_entries_arr[PACKET_BURST];
618  struct doca_flow_pipe *rss_pipe, *encap_pipe, *count_pipe, *ct_pipe = NULL, *udp_pipe;
619  struct doca_flow_port *ports[nb_ports];
620  struct doca_flow_meta o_zone_mask, o_modify_mask, r_zone_mask, r_modify_mask;
621  struct doca_dev *dev_arr[nb_ports];
622  uint32_t actions_mem_size[nb_ports];
623  struct entries_status ctrl_status, ct_status;
624  uint32_t ct_flags = 0, nb_arm_queues = 1, nb_ctrl_queues = 1, nb_user_actions = 0, nb_ipv4_sessions = 1024,
625  nb_ipv6_sessions = 0; /* On BF2 should always be 0 */
626  uint16_t ct_queue = nb_queues;
628 
629  memset(&ctrl_status, 0, sizeof(ctrl_status));
630  memset(&ct_status, 0, sizeof(ct_status));
631  memset(&resource, 0, sizeof(resource));
632 
633  resource.nr_counters = 1;
634 
635  result = init_doca_flow_cb(nb_queues,
636  "switch,hws",
637  &resource,
638  nr_shared_resources,
640  NULL,
641  NULL);
642  if (result != DOCA_SUCCESS) {
643  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
644  return result;
645  }
646 
647  /* Dont use zone masking */
648  memset(&o_zone_mask, 0, sizeof(o_zone_mask));
649  memset(&o_modify_mask, 0, sizeof(o_modify_mask));
650  memset(&r_zone_mask, 0, sizeof(r_zone_mask));
651  memset(&r_modify_mask, 0, sizeof(r_modify_mask));
652 
653  result = init_doca_flow_ct(ct_flags,
654  nb_arm_queues,
655  nb_ctrl_queues,
656  nb_user_actions,
657  NULL,
658  nb_ipv4_sessions,
659  nb_ipv6_sessions,
661  false,
662  &o_zone_mask,
663  &o_modify_mask,
664  false,
665  &r_zone_mask,
666  &r_modify_mask);
667  if (result != DOCA_SUCCESS) {
669  return result;
670  }
671 
672  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
673  dev_arr[0] = ct_dev;
676  if (result != DOCA_SUCCESS) {
677  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
680  return result;
681  }
682 
683  result = create_rss_pipe(ports[0], &ctrl_status, &rss_pipe);
684  if (result != DOCA_SUCCESS)
685  goto cleanup;
686 
687  result = create_vxlan_encap_pipe(ports[0], 0, &ctrl_status, &encap_pipe);
688  if (result != DOCA_SUCCESS)
689  goto cleanup;
690 
691  result = create_count_pipe(ports[0], rss_pipe, &ctrl_status, &count_pipe);
692  if (result != DOCA_SUCCESS)
693  goto cleanup;
694 
695  result = create_ct_pipe(ports[0], encap_pipe, count_pipe, &ct_pipe);
696  if (result != DOCA_SUCCESS)
697  goto cleanup;
698 
699  result = create_ct_root_pipe(ports[0], true, false, DOCA_FLOW_L4_META_UDP, ct_pipe, &ctrl_status, &udp_pipe);
700  if (result != DOCA_SUCCESS)
701  goto cleanup;
702 
703  if (ctrl_status.nb_processed != nb_entries || ctrl_status.failure) {
704  DOCA_LOG_ERR("Failed to process control path entries");
706  goto cleanup;
707  }
708 
709  DOCA_LOG_INFO("Wait few seconds for packets to arrive");
710  sleep(5);
711 
712  result = process_packets(ports[0], ct_queue, &ct_status, ct_entries_arr, &ct_entries_arr_len);
713  if (result != DOCA_SUCCESS)
714  goto cleanup;
715 
716  DOCA_LOG_INFO("Same UDP packets should be resent, if not, sessions will be aged");
717  sleep(5);
718 
719  result = update_nonactive_entries(ports[0], ct_pipe, ct_entries_arr, ct_entries_arr_len, ct_queue);
720  if (result != DOCA_SUCCESS)
721  goto cleanup;
722 
723 cleanup:
724  cleanup_procedure(ct_pipe, nb_ports, ports);
725  return result;
726 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
#define SET_MAC_ADDR(addr, a, b, c, d, e, f)
Definition: flow_common.h:60
static void cleanup(struct cache_invalidate_sample_state *state)
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[])
#define DUP_FILTER_CONN_NUM
static int nb_entries
static doca_error_t create_count_pipe(struct doca_flow_port *port, struct doca_flow_pipe *fwd_pipe, struct entries_status *status, struct doca_flow_pipe **pipe)
#define PACKET_BURST
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 *ct_entries_arr[PACKET_BURST], int *ct_entries_arr_len)
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 void check_for_valid_entry_aging(struct doca_flow_pipe_entry *entry, uint16_t pipe_queue, enum doca_flow_entry_status status, enum doca_flow_entry_op op, void *user_ctx)
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_vxlan_encap_pipe(struct doca_flow_port *port, int port_id, struct entries_status *status, struct doca_flow_pipe **pipe)
static doca_error_t update_nonactive_entries(struct doca_flow_port *port, struct doca_flow_pipe *ct_pipe, struct doca_flow_pipe_entry **entries_arr, int entries_arr_len, uint16_t ct_queue)
doca_error_t flow_ct_udp_update(uint16_t nb_queues, struct doca_dev *ct_dev)
static void parse_packet(struct rte_mbuf *packet, struct doca_flow_ct_match *match_o, struct doca_flow_ct_match *match_r)
DOCA_LOG_REGISTER(FLOW_CT_UDP_UPDATE)
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static struct doca_flow_pipe_entry * entries[NB_ENTRIES]
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_actions actions
Definition: flow_parser.c:107
#define BE_IPV4_ADDR(a, b, c, d)
Definition: flow_parser.c:64
static struct doca_flow_monitor monitor
Definition: flow_parser.c:108
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
#define DOCA_HTOBE32(_x)
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_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_query_entry(uint16_t queue, struct doca_flow_pipe *pipe, uint32_t flags, struct doca_flow_pipe_entry *entry, struct doca_flow_resource_query *stats_origin, struct doca_flow_resource_query *stats_reply, uint64_t *last_hit_s)
Extract information about specific entry.
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_update_entry(uint16_t queue, struct doca_flow_pipe *pipe, uint32_t flags, struct doca_flow_pipe_entry *entry, 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)
Update CT entry meta or counter.
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_FLOW_CT_ENTRY_FLAGS_COUNTER_REPLY
Definition: doca_flow_ct.h:677
@ DOCA_FLOW_CT_ENTRY_FLAGS_DIR_ORIGIN
Definition: doca_flow_ct.h:667
@ DOCA_FLOW_CT_ENTRY_FLAGS_NO_WAIT
Definition: doca_flow_ct.h:665
@ DOCA_FLOW_CT_ENTRY_FLAGS_ALLOC_ON_MISS
Definition: doca_flow_ct.h:683
@ DOCA_FLOW_CT_ENTRY_FLAGS_DUP_FILTER_REPLY
Definition: doca_flow_ct.h:687
@ DOCA_FLOW_CT_ENTRY_FLAGS_DUP_FILTER_ORIGIN
Definition: doca_flow_ct.h:685
@ DOCA_FLOW_CT_ENTRY_FLAGS_COUNTER_ORIGIN
Definition: doca_flow_ct.h:675
#define DOCA_FLOW_VXLAN_DEFAULT_PORT
Definition: doca_flow_net.h:49
#define DOCA_FLOW_PROTO_UDP
Definition: doca_flow_net.h:42
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L3_TYPE_IP4
@ DOCA_FLOW_TUN_VXLAN
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_flow_entry_op
doca flow entry operation
Definition: doca_flow.h:146
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_cfg_set_actions(struct doca_flow_pipe_cfg *cfg, struct doca_flow_actions *const *actions, struct doca_flow_actions *const *actions_masks, struct doca_flow_action_descs *const *action_descs, size_t nr_actions)
Set pipe's actions, actions mask and actions descriptor.
DOCA_STABLE int doca_flow_aging_handle(struct doca_flow_port *port, uint16_t queue, uint64_t quota, uint64_t max_entries)
Handle aging of entries.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_monitor(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_monitor *monitor)
Set pipe's monitor.
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_flow_entry_status
doca flow entry status
Definition: doca_flow.h:160
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_domain(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_domain domain)
Set pipe's domain.
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_UDP
Definition: doca_flow.h:768
@ DOCA_FLOW_ENTRY_OP_AGED
Definition: doca_flow.h:153
@ DOCA_FLOW_PIPE_CT
Definition: doca_flow.h:227
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_NO_WAIT
Definition: doca_flow.h:115
@ 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_ENTRY_STATUS_SUCCESS
Definition: doca_flow.h:163
@ DOCA_FLOW_L4_META_UDP
Definition: doca_flow.h:310
@ DOCA_FLOW_PIPE_DOMAIN_EGRESS
Definition: doca_flow.h:245
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
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
doca_error_t init_doca_flow_cb(int nb_queues, const char *mode, struct flow_resources *resource, uint32_t nr_shared_resources[], doca_flow_entry_process_cb cb, doca_flow_pipe_process_cb pipe_process_cb, struct doca_flow_definitions *defs)
Definition: flow_common.c:79
#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
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_resource_encap_cfg encap_cfg
Definition: doca_flow.h:710
enum doca_flow_resource_type encap_type
Definition: doca_flow.h:707
uint8_t action_idx
Definition: doca_flow.h:685
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
doca_be32_t dst_ip
Definition: doca_flow_ct.h:627
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_tun tun
Definition: doca_flow.h:569
struct doca_flow_header_format outer
Definition: doca_flow.h:567
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
uint8_t dst_mac[DOCA_FLOW_ETHER_ADDR_LEN]
uint8_t src_mac[DOCA_FLOW_ETHER_ADDR_LEN]
struct doca_flow_header_ip4 ip4
Definition: doca_flow.h:449
enum doca_flow_l4_type_ext l4_type_ext
Definition: doca_flow.h:454
struct doca_flow_header_eth eth
Definition: doca_flow.h:440
struct doca_flow_header_udp udp
Definition: doca_flow.h:459
enum doca_flow_l3_type l3_type
Definition: doca_flow.h:446
struct doca_flow_header_l4_port l4_port
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
struct doca_flow_header_format outer
Definition: doca_flow.h:498
doca flow meta data
Definition: doca_flow.h:358
doca monitor action configuration
Definition: doca_flow.h:968
enum doca_flow_resource_type counter_type
Definition: doca_flow.h:988
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
struct doca_flow_encap_action encap
Definition: doca_flow.h:663
flow resource query
Definition: doca_flow.h:1101
struct doca_flow_resource_query::@115::@117 counter
enum doca_flow_tun_type type
doca_be32_t vxlan_tun_id
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
uint32_t dst_addr
Definition: packets.h:76
uint16_t dst_port
Definition: packets.h:99
uint16_t src_port
Definition: packets.h:98
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