NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_switch_to_wire_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 <string.h>
27 #include <unistd.h>
28 
29 #include <rte_byteorder.h>
30 #include <rte_ethdev.h>
31 #include <rte_mempool.h>
32 #include <rte_mbuf.h>
33 #include <rte_net.h>
34 
35 #include <doca_log.h>
36 #include <doca_flow.h>
37 #include <doca_dev.h>
38 
39 #include "flow_common.h"
40 #include "flow_switch_common.h"
41 
42 DOCA_LOG_REGISTER(FLOW_SWITCH_TO_WIRE);
43 
44 #define NB_EGRESS_ENTRIES 3
45 
46 #define NB_INGRESS_ENTRIES 2
47 
48 #define NB_VPORT_ENTRIES 3
49 
50 #define NB_TOTAL_ENTRIES (NB_EGRESS_ENTRIES + NB_INGRESS_ENTRIES + NB_VPORT_ENTRIES + 1)
51 
52 #define MAX_PKTS 16
53 
54 #define WAIT_SECS 15
55 
56 static struct doca_flow_pipe *pipe_egress;
57 static struct doca_flow_pipe *pipe_ingress;
58 static struct doca_flow_pipe *pipe_rss;
59 static struct doca_flow_pipe *pipe_vport;
60 
61 /* array for storing created egress entries */
62 static struct doca_flow_pipe_entry *egress_entries[NB_EGRESS_ENTRIES];
63 
64 /* array for storing created ingress entries */
65 static struct doca_flow_pipe_entry *ingress_entries[NB_INGRESS_ENTRIES];
66 
67 /* array for storing created ingress entries */
68 static struct doca_flow_pipe_entry *vport_entries[NB_VPORT_ENTRIES];
69 
70 static struct doca_flow_pipe_entry *rss_entry;
71 
72 /*
73  * Handle received traffic and check the pkt_meta value added by internal pipe.
74  *
75  * @port_id [in]: proxy port id
76  * @nb_queues [in]: number of queues the sample has
77  */
78 static void handle_rx_tx_pkts(uint32_t port_id, uint16_t nb_queues)
79 {
80  int rc;
81  uint32_t queue_id;
82  uint32_t secs = WAIT_SECS;
83  uint32_t nb_rx;
84  uint32_t i;
85  uint32_t sw_packet_type;
86  uint32_t dst_port;
87  uint32_t nb_tx;
88  uint32_t retry;
89  struct rte_mbuf *mbufs[MAX_PKTS];
90 
91  rc = rte_flow_dynf_metadata_register();
92  if (unlikely(rc)) {
93  DOCA_LOG_ERR("Enable metadata failed");
94  return;
95  }
96 
97  while (secs--) {
98  sleep(1);
99  for (queue_id = 0; queue_id < nb_queues; queue_id++) {
100  nb_rx = rte_eth_rx_burst(port_id, queue_id, mbufs, MAX_PKTS);
101  for (i = 0; i < nb_rx; i++) {
102  sw_packet_type = rte_net_get_ptype(mbufs[i], NULL, RTE_PTYPE_ALL_MASK);
103  if (mbufs[i]->ol_flags & RTE_MBUF_F_RX_FDIR_ID) {
104  if (sw_packet_type & RTE_PTYPE_L4_TCP)
105  dst_port = 0;
106  else if (sw_packet_type & RTE_PTYPE_L4_UDP)
107  dst_port = 1;
108  else
109  dst_port = 2;
110  DOCA_LOG_INFO("The pkt meta:0x%x, dst_port:%d",
111  mbufs[i]->hash.fdir.hi,
112  dst_port);
113  rte_flow_dynf_metadata_set(mbufs[i], dst_port);
114  mbufs[i]->ol_flags |= RTE_MBUF_DYNFLAG_TX_METADATA;
115  } else {
116  DOCA_LOG_INFO("Pkt received: 0x%x\n", sw_packet_type);
117  }
118 
119  retry = 0;
120  do {
121  nb_tx = rte_eth_tx_burst(port_id, queue_id, &mbufs[i], 1);
122  if (nb_tx == 1)
123  break;
124  else
125  rte_delay_us(50000);
126  } while (++retry < 5);
127  rte_pktmbuf_free(mbufs[i]);
128  }
129  }
130  }
131 }
132 
133 /*
134  * Create DOCA Flow pipe with 5 tuple match, and forward RSS
135  *
136  * @port [in]: port of the pipe
137  * @pipe [out]: created pipe pointer
138  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
139  */
140 static doca_error_t create_rss_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
141 {
142  struct doca_flow_match match;
143  struct doca_flow_monitor monitor;
144  struct doca_flow_fwd fwd;
145  struct doca_flow_pipe_cfg *pipe_cfg;
146  uint16_t rss_queues[1];
148 
149  memset(&match, 0, sizeof(match));
150  memset(&fwd, 0, sizeof(fwd));
151  memset(&monitor, 0, sizeof(monitor));
152 
154 
155  /* L3 match */
157 
158  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
159  if (result != DOCA_SUCCESS) {
160  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
161  return result;
162  }
163 
164  result = set_flow_pipe_cfg(pipe_cfg, "RSS_META_PIPE", DOCA_FLOW_PIPE_BASIC, false);
165  if (result != DOCA_SUCCESS) {
166  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
167  goto destroy_pipe_cfg;
168  }
169  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
170  if (result != DOCA_SUCCESS) {
171  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
172  goto destroy_pipe_cfg;
173  }
175  if (result != DOCA_SUCCESS) {
176  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
177  goto destroy_pipe_cfg;
178  }
179 
180  /* RSS queue - send matched traffic to queue 0 */
181  rss_queues[0] = 0;
186  fwd.rss.nr_queues = 1;
187 
188  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
190  doca_flow_pipe_cfg_destroy(pipe_cfg);
191  return result;
192 }
193 
194 /*
195  * Add DOCA Flow pipe entry with example 5 tuple
196  *
197  * @pipe [in]: pipe of the entry
198  * @status [in]: user context for adding entry
199  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
200  */
201 static doca_error_t add_rss_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
202 {
203  struct doca_flow_match match;
204  struct doca_flow_actions actions;
206 
207  memset(&match, 0, sizeof(match));
208  memset(&actions, 0, sizeof(actions));
209 
210  actions.action_idx = 0;
211 
212  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &rss_entry);
213  if (result != DOCA_SUCCESS)
214  return result;
215 
216  return DOCA_SUCCESS;
217 }
218 
219 /*
220  * Create DOCA Flow pipe with 5 tuple match on the switch port.
221  * Matched traffic will be forwarded to the port defined per entry.
222  * Unmatched traffic will be dropped.
223  *
224  * @sw_port [in]: switch port
225  * @pipe [out]: created pipe pointer
226  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
227  */
228 static doca_error_t create_switch_egress_pipe(struct doca_flow_port *sw_port, struct doca_flow_pipe **pipe)
229 {
230  struct doca_flow_match match;
231  struct doca_flow_monitor monitor;
232  struct doca_flow_fwd fwd;
233  struct doca_flow_pipe_cfg *pipe_cfg;
235 
236  memset(&match, 0, sizeof(match));
237  memset(&monitor, 0, sizeof(monitor));
238  memset(&fwd, 0, sizeof(fwd));
239 
244 
245  /* Source, destination IP addresses and source, destination TCP ports are defined per entry */
246  match.outer.ip4.dst_ip = 0xffffffff;
247  match.outer.tcp.l4_port.src_port = 0xffff;
248  match.outer.tcp.l4_port.dst_port = 0xffff;
249 
251 
252  /* Port ID to forward to is defined per entry */
253  fwd.port_id = 0xffff;
254 
256 
257  result = doca_flow_pipe_cfg_create(&pipe_cfg, sw_port);
258  if (result != DOCA_SUCCESS) {
259  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
260  return result;
261  }
262 
263  result = set_flow_pipe_cfg(pipe_cfg, "SWITCH_PIPE", DOCA_FLOW_PIPE_BASIC, true);
264  if (result != DOCA_SUCCESS) {
265  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
266  goto destroy_pipe_cfg;
267  }
269  if (result != DOCA_SUCCESS) {
270  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
271  goto destroy_pipe_cfg;
272  }
274  if (result != DOCA_SUCCESS) {
275  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
276  goto destroy_pipe_cfg;
277  }
278  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
279  if (result != DOCA_SUCCESS) {
280  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
281  goto destroy_pipe_cfg;
282  }
284  if (result != DOCA_SUCCESS) {
285  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
286  goto destroy_pipe_cfg;
287  }
288 
289  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
291  doca_flow_pipe_cfg_destroy(pipe_cfg);
292  return result;
293 }
294 
295 /*
296  * Create DOCA Flow pipe with 5 tuple match on the switch port.
297  * Matched traffic will be forwarded to the port defined per entry.
298  * Unmatched traffic will be dropped.
299  *
300  * @sw_port [in]: switch port
301  * @mirror_id [in]: mirror ID
302  * @pipe [out]: created pipe pointer
303  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
304  */
305 static doca_error_t create_switch_ingress_pipe(struct doca_flow_port *sw_port,
306  uint32_t mirror_id,
307  struct doca_flow_pipe **pipe)
308 {
309  struct doca_flow_match match;
310  struct doca_flow_monitor monitor;
311  struct doca_flow_fwd fwd;
312  struct doca_flow_pipe_cfg *pipe_cfg;
314  struct doca_flow_fwd fwd_miss;
315 
316  memset(&match, 0, sizeof(match));
317  memset(&monitor, 0, sizeof(monitor));
318  memset(&fwd, 0, sizeof(fwd));
319  memset(&fwd_miss, 0, sizeof(fwd_miss));
320 
325 
326  /* Source, destination IP addresses and source, destination TCP ports are defined per entry */
327  match.outer.ip4.src_ip = 0xffffffff;
328  match.outer.tcp.l4_port.src_port = 0xffff;
329  match.outer.tcp.l4_port.dst_port = 0xffff;
330 
331  monitor.shared_mirror_id = mirror_id;
332 
333  /* Port ID to forward to is defined per entry */
335  fwd.next_pipe = NULL;
338 
340 
341  result = doca_flow_pipe_cfg_create(&pipe_cfg, sw_port);
342  if (result != DOCA_SUCCESS) {
343  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
344  return result;
345  }
346 
347  result = set_flow_pipe_cfg(pipe_cfg, "SWITCH_PIPE", DOCA_FLOW_PIPE_BASIC, true);
348  if (result != DOCA_SUCCESS) {
349  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
350  goto destroy_pipe_cfg;
351  }
353  if (result != DOCA_SUCCESS) {
354  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
355  goto destroy_pipe_cfg;
356  }
358  if (result != DOCA_SUCCESS) {
359  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
360  goto destroy_pipe_cfg;
361  }
362  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
363  if (result != DOCA_SUCCESS) {
364  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
365  goto destroy_pipe_cfg;
366  }
368  if (result != DOCA_SUCCESS) {
369  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
370  goto destroy_pipe_cfg;
371  }
372 
373  result = doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, pipe);
375  doca_flow_pipe_cfg_destroy(pipe_cfg);
376  return result;
377 }
378 
379 /*
380  * Create DOCA Flow pipe with 5 tuple match on the switch port.
381  * Matched traffic will be forwarded to the port defined per entry.
382  * Unmatched traffic will be dropped.
383  *
384  * @sw_port [in]: switch port
385  * @pipe [out]: created pipe pointer
386  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
387  */
388 static doca_error_t create_switch_vport_pipe(struct doca_flow_port *sw_port, struct doca_flow_pipe **pipe)
389 {
390  struct doca_flow_match match;
391  struct doca_flow_monitor monitor;
392  struct doca_flow_fwd fwd;
393  struct doca_flow_pipe_cfg *pipe_cfg;
395 
396  memset(&match, 0, sizeof(match));
397  memset(&monitor, 0, sizeof(monitor));
398  memset(&fwd, 0, sizeof(fwd));
399  memset(&pipe_cfg, 0, sizeof(pipe_cfg));
400 
405 
406  /* Source IP addresses and source TCP ports are defined per entry */
407  match.outer.ip4.dst_ip = 0xffffffff;
408  match.outer.tcp.l4_port.src_port = 0xffff;
409 
410  /* Port ID to forward to is defined per entry */
412  fwd.port_id = 0xffff;
413 
415 
416  result = doca_flow_pipe_cfg_create(&pipe_cfg, sw_port);
417  if (result != DOCA_SUCCESS) {
418  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
419  return result;
420  }
421 
422  result = set_flow_pipe_cfg(pipe_cfg, "SWITCH_VPORT_PIPE", DOCA_FLOW_PIPE_BASIC, false);
423  if (result != DOCA_SUCCESS) {
424  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
425  goto destroy_pipe_cfg;
426  }
428  if (result != DOCA_SUCCESS) {
429  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
430  goto destroy_pipe_cfg;
431  }
433  if (result != DOCA_SUCCESS) {
434  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
435  goto destroy_pipe_cfg;
436  }
437  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
438  if (result != DOCA_SUCCESS) {
439  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
440  goto destroy_pipe_cfg;
441  }
443  if (result != DOCA_SUCCESS) {
444  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
445  goto destroy_pipe_cfg;
446  }
447 
448  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
450  doca_flow_pipe_cfg_destroy(pipe_cfg);
451  return result;
452 }
453 
454 /*
455  * Add DOCA Flow pipe entry to the pipe
456  *
457  * @pipe [in]: pipe of the entry
458  * @status [in]: user context for adding entry
459  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
460  */
461 static doca_error_t add_switch_egress_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
462 {
463  struct doca_flow_match match;
464  struct doca_flow_fwd fwd;
467  int entry_index = 0;
468 
469  doca_be32_t dst_ip_addr;
472 
473  memset(&fwd, 0, sizeof(fwd));
474  memset(&match, 0, sizeof(match));
475 
476  for (entry_index = 0; entry_index < NB_EGRESS_ENTRIES; entry_index++) {
477  dst_ip_addr = BE_IPV4_ADDR(8, 8, 8, 8 + entry_index);
478  dst_port = rte_cpu_to_be_16(80);
479  src_port = rte_cpu_to_be_16(1234);
480 
481  match.outer.ip4.dst_ip = dst_ip_addr;
484 
486  /* First port as wire to wire, second wire to VF */
487  fwd.port_id = entry_index;
488 
489  /* last entry should be inserted with DOCA_FLOW_NO_WAIT flag */
490  if (entry_index == NB_EGRESS_ENTRIES - 1)
491  flags = DOCA_FLOW_NO_WAIT;
492 
494  pipe,
495  &match,
496  NULL,
497  NULL,
498  &fwd,
499  flags,
500  status,
501  &egress_entries[entry_index]);
502 
503  if (result != DOCA_SUCCESS) {
504  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
505  return result;
506  }
507  }
508 
509  return DOCA_SUCCESS;
510 }
511 
512 /*
513  * Add DOCA Flow pipe entry to the pipe
514  *
515  * @pipe [in]: pipe of the entry
516  * @status [in]: user context for adding entry
517  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
518  */
519 static doca_error_t add_switch_ingress_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
520 {
521  struct doca_flow_match match;
522  struct doca_flow_fwd fwd;
525  int entry_index = 0;
526 
527  doca_be32_t src_ip_addr;
530 
531  memset(&fwd, 0, sizeof(fwd));
532  memset(&match, 0, sizeof(match));
533 
534  for (entry_index = 0; entry_index < NB_INGRESS_ENTRIES; entry_index++) {
535  src_ip_addr = BE_IPV4_ADDR(1, 2, 3, 4 + entry_index);
536  dst_port = rte_cpu_to_be_16(80);
537  src_port = rte_cpu_to_be_16(1234);
538 
539  match.outer.ip4.src_ip = src_ip_addr;
542 
544  /* First entry to egress, second to vport */
545  fwd.next_pipe = entry_index ? pipe_vport : pipe_egress;
546 
548  pipe,
549  &match,
550  NULL,
551  NULL,
552  &fwd,
553  flags,
554  status,
555  &ingress_entries[entry_index]);
556 
557  if (result != DOCA_SUCCESS) {
558  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
559  return result;
560  }
561  }
562 
563  return DOCA_SUCCESS;
564 }
565 
566 /*
567  * Add DOCA Flow pipe entry to the pipe
568  *
569  * @pipe [in]: pipe of the entry
570  * @status [in]: user context for adding entry
571  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
572  */
573 static doca_error_t add_switch_vport_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
574 {
575  struct doca_flow_match match;
576  struct doca_flow_fwd fwd;
579  int entry_index = 0;
580 
581  doca_be32_t dst_ip_addr;
583 
584  memset(&fwd, 0, sizeof(fwd));
585  memset(&match, 0, sizeof(match));
586 
587  for (entry_index = 0; entry_index < NB_VPORT_ENTRIES; entry_index++) {
588  dst_ip_addr = BE_IPV4_ADDR(8, 8, 8, 8 + entry_index);
589  src_port = rte_cpu_to_be_16(1234);
590 
591  match.outer.ip4.dst_ip = dst_ip_addr;
593 
595  /* First port as wire to wire, second wire to VF */
596  fwd.port_id = entry_index;
597 
599  pipe,
600  &match,
601  NULL,
602  NULL,
603  &fwd,
604  flags,
605  status,
606  &vport_entries[entry_index]);
607 
608  if (result != DOCA_SUCCESS) {
609  DOCA_LOG_ERR("Failed to add pipe entry: %s", doca_error_get_descr(result));
610  return result;
611  }
612  }
613 
614  return DOCA_SUCCESS;
615 }
616 
617 /*
618  * Run flow_switch_to_wire sample
619  *
620  * @nb_queues [in]: number of queues the sample will use
621  * @nb_ports [in]: number of ports the sample will use
622  * @ctx [in]: flow switch context the sample will use
623  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
624  */
626 {
627  struct flow_resources resource = {0};
628  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
629  struct doca_flow_port *ports[nb_ports];
630  struct doca_dev *dev_arr[nb_ports];
631  uint32_t actions_mem_size[nb_ports];
632  struct doca_flow_resource_query query_stats;
633  struct entries_status status;
635  int entry_idx;
636  uint32_t shared_mirror_ids = 1;
637  struct doca_flow_mirror_target target = {0};
638  struct doca_flow_shared_resource_cfg cfg = {0};
639  struct doca_flow_resource_mirror_cfg mirror_cfg = {0};
640  struct doca_dev *doca_dev = ctx->doca_dev[0];
641  const char *start_str;
642  bool is_expert = ctx->is_expert;
643 
644  memset(&status, 0, sizeof(status));
645  nr_shared_resources[DOCA_FLOW_SHARED_RESOURCE_MIRROR] = 4;
646  resource.nr_counters = 2 * NB_TOTAL_ENTRIES; /* counter per entry */
647  /* Use isolated mode as we will create the RSS pipe later */
648  if (is_expert)
649  start_str = "switch,hws,isolated,hairpinq_num=4,expert";
650  else
651  start_str = "switch,hws,isolated,hairpinq_num=4";
652  result = init_doca_flow(nb_queues, start_str, &resource, nr_shared_resources);
653  if (result != DOCA_SUCCESS) {
654  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
655  return result;
656  }
657 
658  /* Doca_dev is opened for proxy_port only */
659  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
660  dev_arr[0] = doca_dev;
662  result = init_doca_flow_ports(nb_ports, ports, false /* is_hairpin */, dev_arr, actions_mem_size);
663  if (result != DOCA_SUCCESS) {
664  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
666  return result;
667  }
668 
669  /* Create rss pipe and entry */
671  if (result != DOCA_SUCCESS) {
672  DOCA_LOG_ERR("Failed to create rss pipe: %s", doca_error_get_descr(result));
675  return result;
676  }
677 
678  result = add_rss_pipe_entry(pipe_rss, &status);
679  if (result != DOCA_SUCCESS) {
680  DOCA_LOG_ERR("Failed to add entry: %s", doca_error_get_descr(result));
683  return result;
684  }
685 
686  mirror_cfg.nr_targets = 1;
687  mirror_cfg.target = &target;
688  target.fwd.type = DOCA_FLOW_FWD_PORT;
689  target.fwd.port_id = 1;
690  cfg.mirror_cfg = mirror_cfg;
691  /* Create the function and reset later to verify the mirror update supporting. */
693  if (result != DOCA_SUCCESS) {
694  DOCA_LOG_ERR("Failed to cfg shared mirror");
697  return result;
698  }
699  /* bind shared mirror to port */
701  if (result != DOCA_SUCCESS) {
702  DOCA_LOG_ERR("Failed to bind shared mirror to port");
705  return result;
706  }
707 
708  /* Create egress pipe and entries */
710  if (result != DOCA_SUCCESS) {
711  DOCA_LOG_ERR("Failed to create egress pipe: %s", doca_error_get_descr(result));
714  return result;
715  }
716 
718  if (result != DOCA_SUCCESS) {
719  DOCA_LOG_ERR("Failed to add egress_entries to the pipe: %s", doca_error_get_descr(result));
722  return result;
723  }
724 
725  /* Create vport pipe and entries */
727  if (result != DOCA_SUCCESS) {
728  DOCA_LOG_ERR("Failed to create vport pipe: %s", doca_error_get_descr(result));
731  return result;
732  }
733 
735  if (result != DOCA_SUCCESS) {
736  DOCA_LOG_ERR("Failed to add vport_entries to the pipe: %s", doca_error_get_descr(result));
739  return result;
740  }
741 
742  mirror_cfg.nr_targets = 1;
743  mirror_cfg.target = &target;
744  target.fwd.type = DOCA_FLOW_FWD_PIPE;
745  target.fwd.next_pipe = pipe_egress;
746  cfg.mirror_cfg = mirror_cfg;
747  /* Update mirror configuration here */
749  if (result != DOCA_SUCCESS) {
750  DOCA_LOG_ERR("Failed to cfg shared mirror");
753  return result;
754  }
755 
756  /* Create ingress pipe and entries */
758  if (result != DOCA_SUCCESS) {
759  DOCA_LOG_ERR("Failed to create ingress pipe: %s", doca_error_get_descr(result));
762  return result;
763  }
764 
766  if (result != DOCA_SUCCESS) {
767  DOCA_LOG_ERR("Failed to add ingress_entries to the pipe: %s", doca_error_get_descr(result));
770  return result;
771  }
772 
773  result =
775  if (result != DOCA_SUCCESS) {
776  DOCA_LOG_ERR("Failed to process egress_entries: %s", doca_error_get_descr(result));
779  return result;
780  }
781 
782  if (status.nb_processed != NB_TOTAL_ENTRIES || status.failure) {
783  DOCA_LOG_ERR("Failed to process all entries");
786  return DOCA_ERROR_BAD_STATE;
787  }
788 
789  DOCA_LOG_INFO("Wait few seconds for packets to arrive");
790 
791  handle_rx_tx_pkts(0, nb_queues);
792 
793  /* dump egress entries counters */
796  if (result != DOCA_SUCCESS) {
797  DOCA_LOG_ERR("Failed to query entry: %s", doca_error_get_descr(result));
800  return result;
801  }
802  DOCA_LOG_INFO("Egress Entry in index: %d", entry_idx);
803  DOCA_LOG_INFO("Total bytes: %ld", query_stats.counter.total_bytes);
804  DOCA_LOG_INFO("Total packets: %ld", query_stats.counter.total_pkts);
805  }
806 
809  if (result != DOCA_SUCCESS) {
810  DOCA_LOG_ERR("Failed to query vport pipe entry: %s", doca_error_get_descr(result));
813  return result;
814  }
815  DOCA_LOG_INFO("Vport Entry in index: %d", entry_idx);
816  DOCA_LOG_INFO("Total bytes: %ld", query_stats.counter.total_bytes);
817  DOCA_LOG_INFO("Total packets: %ld", query_stats.counter.total_pkts);
818  }
819 
822  if (result != DOCA_SUCCESS) {
823  DOCA_LOG_ERR("Failed to query entry: %s", doca_error_get_descr(result));
826  return result;
827  }
828  DOCA_LOG_INFO("Ingress Entry in index: %d", entry_idx);
829  DOCA_LOG_INFO("Total bytes: %ld", query_stats.counter.total_bytes);
830  DOCA_LOG_INFO("Total packets: %ld", query_stats.counter.total_pkts);
831  }
832 
834  if (result != DOCA_SUCCESS) {
835  DOCA_LOG_ERR("Failed to query entry: %s", doca_error_get_descr(result));
838  return result;
839  }
840  DOCA_LOG_INFO("RSS Entry in index: %d", entry_idx);
841  DOCA_LOG_INFO("Total bytes: %ld", query_stats.counter.total_bytes);
842  DOCA_LOG_INFO("Total packets: %ld", query_stats.counter.total_pkts);
843 
846  return result;
847 }
#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
#define unlikely(x)
Definition: utils.h:42
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_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
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
static uint8_t entry_idx
static doca_error_t add_switch_vport_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
static struct doca_flow_pipe_entry * egress_entries[NB_EGRESS_ENTRIES]
static struct doca_flow_pipe * pipe_rss
static struct doca_flow_pipe * pipe_egress
static doca_error_t add_rss_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
#define MAX_PKTS
static doca_error_t create_switch_ingress_pipe(struct doca_flow_port *sw_port, uint32_t mirror_id, struct doca_flow_pipe **pipe)
static struct doca_flow_pipe * pipe_vport
static doca_error_t create_switch_vport_pipe(struct doca_flow_port *sw_port, struct doca_flow_pipe **pipe)
static doca_error_t create_switch_egress_pipe(struct doca_flow_port *sw_port, struct doca_flow_pipe **pipe)
#define NB_TOTAL_ENTRIES
doca_error_t flow_switch_to_wire(int nb_queues, int nb_ports, struct flow_switch_ctx *ctx)
#define NB_VPORT_ENTRIES
#define NB_EGRESS_ENTRIES
static struct doca_flow_pipe_entry * vport_entries[NB_VPORT_ENTRIES]
static doca_error_t add_switch_ingress_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
#define NB_INGRESS_ENTRIES
#define WAIT_SECS
static doca_error_t create_rss_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
static doca_error_t add_switch_egress_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
static struct doca_flow_pipe * pipe_ingress
static void handle_rx_tx_pkts(uint32_t port_id, uint16_t nb_queues)
static struct doca_flow_pipe_entry * rss_entry
static struct doca_flow_pipe_entry * ingress_entries[NB_INGRESS_ENTRIES]
DOCA_LOG_REGISTER(FLOW_SWITCH_TO_WIRE)
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_FLOW_L4_TYPE_EXT_TCP
@ DOCA_FLOW_L3_TYPE_IP4
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_STABLE doca_error_t doca_flow_shared_resources_bind(enum doca_flow_shared_resource_type type, uint32_t *res_array, uint32_t res_array_len, void *bindable_obj)
Binds a bulk of shared resources to a bindable object.
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_flow_flags_type
doca flow flags type
Definition: doca_flow.h:114
DOCA_EXPERIMENTAL doca_error_t doca_flow_shared_resource_set_cfg(enum doca_flow_shared_resource_type type, uint32_t id, struct doca_flow_shared_resource_cfg *cfg)
Configure a single shared resource.
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_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_nr_entries(struct doca_flow_pipe_cfg *cfg, uint32_t nr_entries)
Set pipe's maximum number of flow rules.
DOCA_STABLE struct doca_flow_port * doca_flow_port_switch_get(const struct doca_flow_port *port)
Get doca flow switch port.
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_EXPERIMENTAL doca_error_t doca_flow_resource_query_entry(struct doca_flow_pipe_entry *entry, struct doca_flow_resource_query *query_stats)
Extract information about specific entry.
@ DOCA_FLOW_RSS_TCP
Definition: doca_flow.h:770
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_SHARED_RESOURCE_MIRROR
Definition: doca_flow.h:99
@ 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_WAIT_FOR_BATCH
Definition: doca_flow.h:117
@ 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
@ DOCA_FLOW_PIPE_DOMAIN_EGRESS
Definition: doca_flow.h:245
@ DOCA_FLOW_PIPE_DOMAIN_DEFAULT
Definition: doca_flow.h:241
#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
uint32_t doca_be32_t
Definition: doca_types.h:121
uint16_t doca_be16_t
Declare DOCA endianity types.
Definition: doca_types.h:120
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
uint16_t queue_id
Definition: ip_frag_dp.c:1
uint16_t src_port
Definition: packets.h:0
uint16_t dst_port
Definition: packets.h:1
doca_error_t stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
Definition: flow_common.c:240
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
doca flow actions information
Definition: doca_flow.h:684
uint8_t action_idx
Definition: doca_flow.h:685
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
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
enum doca_flow_l3_type l3_type
Definition: doca_flow.h:446
struct doca_flow_header_tcp tcp
Definition: doca_flow.h:461
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 mirror target
Definition: doca_flow.h:929
struct doca_flow_fwd fwd
Definition: doca_flow.h:934
doca monitor action configuration
Definition: doca_flow.h:968
uint32_t shared_mirror_id
Definition: doca_flow.h:997
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
doca flow mirror resource configuration
Definition: doca_flow.h:941
struct doca_flow_mirror_target * target
Definition: doca_flow.h:944
flow resource query
Definition: doca_flow.h:1101
struct doca_flow_resource_query::@115::@117 counter
doca flow shared resource configuration
Definition: doca_flow.h:953
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
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
struct upf_accel_ctx * ctx