NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
simple_fwd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021-2022 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 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <arpa/inet.h>
30 
31 #include <rte_random.h>
32 
33 #include <doca_flow.h>
34 #include <doca_log.h>
35 #include <doca_bitfield.h>
36 
37 #include "app_vnf.h"
38 #include "simple_fwd.h"
39 #include "simple_fwd_ft.h"
40 #include "utils.h"
41 
42 DOCA_LOG_REGISTER(SIMPLE_FWD);
43 
44 /* Convert IPv4 address to big endian */
45 #define BE_IPV4_ADDR(a, b, c, d) (RTE_BE32(((uint32_t)a << 24) + (b << 16) + (c << 8) + d))
46 
47 /* Set the MAC address with respect to the given 6 bytes */
48 #define SET_MAC_ADDR(addr, a, b, c, d, e, f) \
49  do { \
50  addr[0] = a & 0xff; \
51  addr[1] = b & 0xff; \
52  addr[2] = c & 0xff; \
53  addr[3] = d & 0xff; \
54  addr[4] = e & 0xff; \
55  addr[5] = f & 0xff; \
56  } while (0)
57 
58 /* Set match l4 port */
59 #define SET_L4_PORT(layer, port, value) \
60  do { \
61  if (match->layer.l4_type_ext == DOCA_FLOW_L4_TYPE_EXT_TCP) \
62  match->layer.tcp.l4_port.port = (value); \
63  else if (match->layer.l4_type_ext == DOCA_FLOW_L4_TYPE_EXT_UDP) \
64  match->layer.udp.l4_port.port = (value); \
65  } while (0)
66 
67 /*
68  * Currently we only can get the ft_entry ctx, but for the aging,
69  * we need get the ft_entry pointer, add destroy the ft entry.
70  */
71 #define GET_FT_ENTRY(ctx) container_of(ctx, struct simple_fwd_ft_entry, user_ctx)
72 
73 #define PULL_TIME_OUT 10000 /* Maximum timeout for pulling */
74 #define NB_ACTION_ARRAY (1) /* Used as the size of muti-actions array for DOCA Flow API */
75 #define NB_ACTION_DESC (1) /* Used as the size of muti-action descs array for DOCA Flow API */
76 
77 static struct simple_fwd_app *simple_fwd_ins; /* Instance holding all allocated resources needed for a proper run */
78 
79 /* user context struct that will be used in entries process callback */
80 struct entries_status {
81  bool failure; /* will be set to true if some entry status will not be success */
82  int nb_processed; /* will hold the number of entries that was already processed */
83  void *ft_entry; /* pointer to struct simple_fwd_ft_entry */
84 };
85 
86 /*
87  * Entry processing callback
88  *
89  * @entry [in]: DOCA Flow entry pointer
90  * @pipe_queue [in]: queue identifier
91  * @status [in]: DOCA Flow entry status
92  * @op [in]: DOCA Flow entry operation
93  * @user_ctx [out]: user context
94  */
95 static void simple_fwd_check_for_valid_entry(struct doca_flow_pipe_entry *entry,
96  uint16_t pipe_queue,
97  enum doca_flow_entry_status status,
98  enum doca_flow_entry_op op,
99  void *user_ctx)
100 {
101  (void)entry;
102  (void)op;
103  (void)pipe_queue;
104 
105  struct simple_fwd_ft_entry *ft_entry;
106  struct entries_status *entry_status = (struct entries_status *)user_ctx;
107 
108  if (entry_status == NULL)
109  return;
110  if (status != DOCA_FLOW_ENTRY_STATUS_SUCCESS)
111  entry_status->failure = true; /* set failure to true if processing failed */
112  if (op == DOCA_FLOW_ENTRY_OP_AGED) {
113  ft_entry = GET_FT_ENTRY((void *)(entry_status->ft_entry));
115  } else if (op == DOCA_FLOW_ENTRY_OP_ADD)
116  entry_status->nb_processed++;
117  else if (op == DOCA_FLOW_ENTRY_OP_DEL) {
118  entry_status->nb_processed--;
119  if (entry_status->nb_processed == 0)
120  free(entry_status);
121  }
122 }
123 
124 /*
125  * Initialize DOCA Flow library
126  *
127  * @nb_queues [in]: number of queues the sample will use
128  * @mode [in]: doca flow architecture mode
129  * @nr_counters [in]: number of counters to configure
130  * @nr_meters [in]: number of meters to configure
131  * @return: 0 on success, negative errno value otherwise and error is set.
132  */
133 static int simple_fwd_init_doca_flow(int nb_queues, const char *mode, uint32_t nr_counters, uint32_t nr_meters)
134 {
135  struct doca_flow_cfg *flow_cfg;
136  uint16_t rss_queues[nb_queues];
137  struct doca_flow_resource_rss_cfg rss = {0};
138  doca_error_t result, tmp_result;
139 
140  result = doca_flow_cfg_create(&flow_cfg);
141  if (result != DOCA_SUCCESS) {
142  DOCA_LOG_ERR("Failed to create doca_flow_cfg: %s", doca_error_get_descr(result));
143  return -1;
144  }
145 
146  result = doca_flow_cfg_set_pipe_queues(flow_cfg, nb_queues);
147  if (result != DOCA_SUCCESS) {
148  DOCA_LOG_ERR("Failed to set doca_flow_cfg pipe_queues: %s", doca_error_get_descr(result));
149  goto destroy_cfg;
150  }
151 
152  result = doca_flow_cfg_set_mode_args(flow_cfg, mode);
153  if (result != DOCA_SUCCESS) {
154  DOCA_LOG_ERR("Failed to set doca_flow_cfg mode_args: %s", doca_error_get_descr(result));
155  goto destroy_cfg;
156  }
157 
158  result = doca_flow_cfg_set_nr_counters(flow_cfg, nr_counters);
159  if (result != DOCA_SUCCESS) {
160  DOCA_LOG_ERR("Failed to set doca_flow_cfg nr_counters: %s", doca_error_get_descr(result));
161  goto destroy_cfg;
162  }
163 
164  result = doca_flow_cfg_set_nr_meters(flow_cfg, nr_meters);
165  if (result != DOCA_SUCCESS) {
166  DOCA_LOG_ERR("Failed to set doca_flow_cfg nr_meters: %s", doca_error_get_descr(result));
167  goto destroy_cfg;
168  }
169 
171  if (result != DOCA_SUCCESS) {
172  DOCA_LOG_ERR("Failed to set doca_flow_cfg cb_entry_process: %s", doca_error_get_descr(result));
173  goto destroy_cfg;
174  }
175 
176  linear_array_init_u16(rss_queues, nb_queues);
177  rss.nr_queues = nb_queues;
178  rss.queues_array = rss_queues;
179  result = doca_flow_cfg_set_default_rss(flow_cfg, &rss);
180  if (result != DOCA_SUCCESS) {
181  DOCA_LOG_ERR("Failed to set doca_flow_cfg rss: %s", doca_error_get_descr(result));
182  goto destroy_cfg;
183  }
184 
185  result = doca_flow_init(flow_cfg);
186  if (result != DOCA_SUCCESS)
187  DOCA_LOG_ERR("Failed to initialize doca flow: %s", doca_error_get_descr(result));
188 
189 destroy_cfg:
190  tmp_result = doca_flow_cfg_destroy(flow_cfg);
191  if (tmp_result != DOCA_SUCCESS) {
192  DOCA_LOG_ERR("Failed to destroy doca_flow_cfg: %s", doca_error_get_descr(tmp_result));
193  DOCA_ERROR_PROPAGATE(result, tmp_result);
194  }
195  return (result == DOCA_SUCCESS) ? 0 : -1;
196 }
197 
198 /*
199  * Create DOCA Flow port by port id
200  *
201  * @port_id [in]: port ID
202  * @return: port handler on success, NULL otherwise and error is set.
203  */
204 static struct doca_flow_port *simple_fwd_create_doca_flow_port(int port_id)
205 {
206  struct doca_flow_port_cfg *port_cfg;
207  doca_error_t result, tmp_result;
208  struct doca_flow_port *port;
209 
210  result = doca_flow_port_cfg_create(&port_cfg);
211  if (result != DOCA_SUCCESS) {
212  DOCA_LOG_ERR("Failed to create doca_flow_port_cfg: %s", doca_error_get_descr(result));
213  return NULL;
214  }
215 
216  result = doca_flow_port_cfg_set_port_id(port_cfg, port_id);
217  if (result != DOCA_SUCCESS) {
218  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg port_id: %s", doca_error_get_descr(result));
219  goto destroy_port_cfg;
220  }
221 
223  if (result != DOCA_SUCCESS) {
224  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg priv_data_size: %s", doca_error_get_descr(result));
225  goto destroy_port_cfg;
226  }
227 
229  port_cfg,
231  if (result != DOCA_SUCCESS) {
232  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg actions mem size: %s", doca_error_get_descr(result));
233  goto destroy_port_cfg;
234  }
235 
236  result = doca_flow_port_start(port_cfg, &port);
237  if (result != DOCA_SUCCESS) {
238  DOCA_LOG_ERR("Failed to start doca_flow port: %s", doca_error_get_descr(result));
239  goto destroy_port_cfg;
240  }
241 
242 destroy_port_cfg:
243  tmp_result = doca_flow_port_cfg_destroy(port_cfg);
244  if (tmp_result != DOCA_SUCCESS) {
245  DOCA_LOG_ERR("Failed to destroy doca_flow port: %s", doca_error_get_descr(tmp_result));
246  DOCA_ERROR_PROPAGATE(result, tmp_result);
247  }
248 
249  return result == DOCA_SUCCESS ? port : NULL;
250 }
251 
252 /*
253  * Stop DOCA Flow ports
254  *
255  * @nb_ports [in]: number of ports to stop
256  * @ports [in]: array of DOCA flow ports to stop
257  */
258 static void simple_fwd_stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
259 {
260  int portid;
261 
262  for (portid = 0; portid < nb_ports; portid++) {
263  if (ports[portid] != NULL)
264  doca_flow_port_stop(ports[portid]);
265  }
266 }
267 
268 /*
269  * Initialize DOCA Flow ports
270  *
271  * @nb_ports [in]: number of ports to create
272  * @ports [in]: array of ports to create
273  * @is_hairpin [in]: port pair should run if is_hairpin = true
274  * @return: 0 on success and negative value otherwise.
275  */
276 static int simple_fwd_init_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin)
277 {
278  int portid;
279 
280  for (portid = 0; portid < nb_ports; portid++) {
281  /* Create doca flow port */
282  ports[portid] = simple_fwd_create_doca_flow_port(portid);
283  if (ports[portid] == NULL) {
285  return -1;
286  }
287 
288  /* Pair ports should be done in the following order: port0 with port1, port2 with port3 etc */
289  if (!is_hairpin || !portid || !(portid % 2))
290  continue;
291 
292  /* pair odd port with previous port */
293  if (doca_flow_port_pair(ports[portid], ports[portid ^ 1]) != DOCA_SUCCESS) {
295  return -1;
296  }
297  }
298  return 0;
299 }
300 
301 /*
302  * Callback function for removing aged flow
303  *
304  * @ctx [in]: the context of the aged flow to remove
305  */
307 {
308  struct simple_fwd_pipe_entry *entry = (struct simple_fwd_pipe_entry *)&ctx->data[0];
309 
310  if (entry->is_hw) {
311  doca_flow_pipe_remove_entry(entry->pipe_queue, DOCA_FLOW_NO_WAIT, entry->hw_entry);
312  entry->hw_entry = NULL;
313  }
314 }
315 
316 /*
317  * Destroy flow table used by the application
318  *
319  * @return: 0 on success and negative value otherwise
320  */
321 static int simple_fwd_destroy_ins(void)
322 {
323  uint16_t idx;
324 
325  if (simple_fwd_ins == NULL)
326  return 0;
327 
329 
330  for (idx = 0; idx < SIMPLE_FWD_PORTS; idx++) {
331  if (simple_fwd_ins->ports[idx])
333  }
334  free(simple_fwd_ins);
336  return 0;
337 }
338 
339 /*
340  * Destroy application allocated resources
341  *
342  * @return: 0 on success and negative value otherwise
343  */
344 static int simple_fwd_destroy(void)
345 {
348  return 0;
349 }
350 
351 /*
352  * Initializes flow tables used by the application for a given port
353  *
354  * @port_cfg [in]: the port configuration to allocate the resources
355  * @return: 0 on success and negative value otherwise
356  */
357 static int simple_fwd_create_ins(struct simple_fwd_port_cfg *port_cfg)
358 {
359  uint16_t index;
360 
361  simple_fwd_ins = (struct simple_fwd_app *)
362  calloc(1, sizeof(struct simple_fwd_app) + sizeof(struct doca_flow_aged_query *) * port_cfg->nb_queues);
363  if (simple_fwd_ins == NULL) {
364  DOCA_LOG_ERR("Failed to allocate SF");
365  goto fail_init;
366  }
367 
369  sizeof(struct simple_fwd_pipe_entry),
371  NULL,
372  port_cfg->age_thread);
373  if (simple_fwd_ins->ft == NULL) {
374  DOCA_LOG_ERR("Failed to allocate FT");
375  goto fail_init;
376  }
377  simple_fwd_ins->nb_queues = port_cfg->nb_queues;
378  for (index = 0; index < SIMPLE_FWD_PORTS; index++)
379  simple_fwd_ins->hairpin_peer[index] = index ^ 1;
380  return 0;
381 fail_init:
383  return -1;
384 }
385 
386 /*
387  * Create DOCA Flow "RSS pipe" and adds entry that match every packet, and forwards to SW, for a given port
388  *
389  * @port_id [in]: port identifier
390  * @return: 0 on success, negative value otherwise and error is set.
391  */
392 static int simple_fwd_build_rss_flow(uint16_t port_id)
393 {
394  struct doca_flow_match match;
395  struct doca_flow_actions actions, *actions_arr[NB_ACTION_ARRAY];
396  struct doca_flow_fwd fwd;
397  struct doca_flow_pipe_cfg *pipe_cfg;
398  struct doca_flow_pipe_entry *entry;
399  struct simple_fwd_port_cfg *port_cfg =
401  struct entries_status *status;
402  uint16_t rss_queues[port_cfg->nb_queues];
403  int num_of_entries = 1;
404  int i;
406 
407  memset(&match, 0, sizeof(match));
408  memset(&actions, 0, sizeof(actions));
409  memset(&fwd, 0, sizeof(fwd));
410 
411  actions_arr[0] = &actions;
412 
413  result = doca_flow_pipe_cfg_create(&pipe_cfg, simple_fwd_ins->ports[port_cfg->port_id]);
414  if (result != DOCA_SUCCESS) {
415  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
416  return result;
417  }
418 
419  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "RSS_PIPE");
420  if (result != DOCA_SUCCESS) {
421  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
422  goto destroy_pipe_cfg;
423  }
424  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
425  if (result != DOCA_SUCCESS) {
426  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
427  goto destroy_pipe_cfg;
428  }
429  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
430  if (result != DOCA_SUCCESS) {
431  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
432  goto destroy_pipe_cfg;
433  }
434  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTION_ARRAY);
435  if (result != DOCA_SUCCESS) {
436  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
437  goto destroy_pipe_cfg;
438  }
439 
440  for (i = 0; i < port_cfg->nb_queues; i++)
441  rss_queues[i] = i;
442 
446  fwd.rss.nr_queues = port_cfg->nb_queues;
448 
449  status = (struct entries_status *)calloc(1, sizeof(struct entries_status));
450 
451  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &simple_fwd_ins->pipe_rss[port_cfg->port_id]);
452  if (result != DOCA_SUCCESS) {
453  free(status);
454  goto destroy_pipe_cfg;
455  }
456 
457  doca_flow_pipe_cfg_destroy(pipe_cfg);
458 
460  simple_fwd_ins->pipe_rss[port_cfg->port_id],
461  &match,
462  &actions,
463  NULL,
464  &fwd,
465  0,
466  status,
467  &entry);
468  if (result != DOCA_SUCCESS) {
469  free(status);
470  return -1;
471  }
472  result = doca_flow_entries_process(simple_fwd_ins->ports[port_cfg->port_id], 0, PULL_TIME_OUT, num_of_entries);
473  if (result != DOCA_SUCCESS)
474  return -1;
475 
476  if (status->nb_processed != num_of_entries || status->failure)
477  return -1;
478 
479  return 0;
480 
482  doca_flow_pipe_cfg_destroy(pipe_cfg);
483  return -1;
484 }
485 
486 /*
487  * Create DOCA Flow hairpin pipe and adds entry that match every packet for a given port
488  *
489  * @port_id [in]: port identifier
490  * @return: 0 on success, negative value otherwise and error is set.
491  */
492 static int simple_fwd_build_hairpin_flow(uint16_t port_id)
493 {
494  struct doca_flow_match match;
495  struct doca_flow_actions actions, *actions_arr[NB_ACTION_ARRAY];
496  struct doca_flow_fwd fwd;
497  struct doca_flow_pipe_cfg *pipe_cfg;
498  struct doca_flow_pipe_entry *entry;
499  struct simple_fwd_port_cfg *port_cfg =
501  struct entries_status *status;
502  int num_of_entries = 1;
504 
505  memset(&match, 0, sizeof(match));
506  memset(&actions, 0, sizeof(actions));
507  memset(&fwd, 0, sizeof(fwd));
508 
509  actions_arr[0] = &actions;
510 
511  result = doca_flow_pipe_cfg_create(&pipe_cfg, simple_fwd_ins->ports[port_cfg->port_id]);
512  if (result != DOCA_SUCCESS) {
513  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
514  return result;
515  }
516 
517  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "HAIRPIN_PIPE");
518  if (result != DOCA_SUCCESS) {
519  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
520  goto destroy_pipe_cfg;
521  }
522  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
523  if (result != DOCA_SUCCESS) {
524  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
525  goto destroy_pipe_cfg;
526  }
527  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
528  if (result != DOCA_SUCCESS) {
529  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
530  goto destroy_pipe_cfg;
531  }
532  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTION_ARRAY);
533  if (result != DOCA_SUCCESS) {
534  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
535  goto destroy_pipe_cfg;
536  }
537 
539  fwd.port_id = port_cfg->port_id ^ 1;
540 
541  status = (struct entries_status *)calloc(1, sizeof(struct entries_status));
542 
544  if (result != DOCA_SUCCESS) {
545  free(status);
546  goto destroy_pipe_cfg;
547  }
548 
549  doca_flow_pipe_cfg_destroy(pipe_cfg);
550 
552  simple_fwd_ins->pipe_hairpin[port_cfg->port_id],
553  &match,
554  &actions,
555  NULL,
556  &fwd,
557  0,
558  status,
559  &entry);
560  if (result != DOCA_SUCCESS) {
561  free(status);
562  return -1;
563  }
564 
565  result = doca_flow_entries_process(simple_fwd_ins->ports[port_cfg->port_id], 0, PULL_TIME_OUT, num_of_entries);
566  if (result != DOCA_SUCCESS) {
567  free(status);
568  return -1;
569  }
570 
571  if (status->nb_processed != num_of_entries || status->failure) {
572  free(status);
573  return -1;
574  }
575 
576  return 0;
577 
579  doca_flow_pipe_cfg_destroy(pipe_cfg);
580  return -1;
581 }
582 
583 /*
584  * Build DOCA Flow FWD component based on the port configuration provided by the user
585  *
586  * @port_cfg [in]: port configuration as provided by the user
587  * @fwd [out]: DOCA Flow FWD component to fill its fields
588  */
589 static void simple_fwd_build_fwd(struct simple_fwd_port_cfg *port_cfg, struct doca_flow_fwd *fwd)
590 {
591  if (port_cfg->is_hairpin > 0) {
593  fwd->port_id = port_cfg->port_id ^ 1;
594  }
595 
596  else {
599  }
600 }
601 
602 /*
603  * Build common fields in the DOCA Flow match for layers in DOCA Flow match for VxLAN, GRE and GTP pipes creation
604  *
605  * @match [out]: DOCA Flow match to fill its inner layers
606  */
608 {
609  if (match->tun.type != DOCA_FLOW_TUN_GRE) {
613  }
614 
616  match->outer.ip4.src_ip = UINT32_MAX;
617  match->outer.ip4.dst_ip = UINT32_MAX;
619  match->inner.ip4.src_ip = UINT32_MAX;
620  match->inner.ip4.dst_ip = UINT32_MAX;
622  match->inner.tcp.l4_port.src_port = UINT16_MAX;
623  match->inner.tcp.l4_port.dst_port = UINT16_MAX;
624 }
625 
626 /*
627  * Create DOCA Flow pipe that match VXLAN traffic with changeable VXLAN tunnel ID and decap action
628  *
629  * @port_cfg [in]: port configuration as provided by the user
630  * @type [in]: DOCA Flow tunnel type to determine what pipe to create
631  * @return: 0 on success, negative value otherwise and error is set
632  */
634 {
635  struct doca_flow_match match;
636  struct doca_flow_actions actions, *actions_arr[NB_ACTION_ARRAY];
637  struct doca_flow_action_descs descs;
638  struct doca_flow_monitor monitor;
639  struct doca_flow_fwd fwd;
640  struct doca_flow_fwd fwd_miss;
641  struct doca_flow_pipe_cfg *pipe_cfg;
642  struct doca_flow_pipe **pipe;
643  const char *pipe_name;
645 
646  memset(&match, 0, sizeof(match));
647  memset(&actions, 0, sizeof(actions));
648  memset(&descs, 0, sizeof(descs));
649  memset(&monitor, 0, sizeof(monitor));
650  memset(&fwd, 0, sizeof(fwd));
651  memset(&fwd_miss, 0, sizeof(fwd_miss));
652 
653  actions_arr[0] = &actions;
654 
655  match.tun.type = type;
657 
658  switch (type) {
659  case DOCA_FLOW_TUN_VXLAN:
660  pipe_name = "VXLAN_PIPE";
663  match.outer.udp.l4_port.dst_port = rte_cpu_to_be_16(DOCA_FLOW_VXLAN_DEFAULT_PORT);
664  match.tun.vxlan_tun_id = UINT32_MAX;
667  actions.decap_cfg.is_l2 = true;
668  pipe = &simple_fwd_ins->pipe_vxlan[port_cfg->port_id];
669  break;
670  case DOCA_FLOW_TUN_GTPU:
671  pipe_name = "GTP_FWD";
674  match.outer.udp.l4_port.dst_port = rte_cpu_to_be_16(DOCA_FLOW_GTPU_DEFAULT_PORT);
675  match.tun.gtp_teid = UINT32_MAX;
676 
678  actions.decap_cfg.is_l2 = false;
679  SET_MAC_ADDR(actions.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
680  SET_MAC_ADDR(actions.outer.eth.dst_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
681  actions.outer.eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
682  pipe = &simple_fwd_ins->pipe_gtp[port_cfg->port_id];
683  break;
684  case DOCA_FLOW_TUN_GRE:
685  pipe_name = "GRE_PIPE";
686  match.tun.gre_key = UINT32_MAX;
687  match.tun.key_present = true;
689  actions.decap_cfg.is_l2 = false;
690  SET_MAC_ADDR(actions.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
691  SET_MAC_ADDR(actions.outer.eth.dst_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
692  actions.outer.eth.type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
695  pipe = &simple_fwd_ins->pipe_gre[port_cfg->port_id];
696  break;
697  default:
698  return -1;
699  }
700 
701  /* build monitor part */
703  monitor.aging_sec = 0xffffffff;
704 
705  result = doca_flow_pipe_cfg_create(&pipe_cfg, simple_fwd_ins->ports[port_cfg->port_id]);
706  if (result != DOCA_SUCCESS) {
707  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
708  return result;
709  }
710 
711  result = doca_flow_pipe_cfg_set_name(pipe_cfg, pipe_name);
712  if (result != DOCA_SUCCESS) {
713  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
714  goto destroy_pipe_cfg;
715  }
717  if (result != DOCA_SUCCESS) {
718  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
719  goto destroy_pipe_cfg;
720  }
721  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
722  if (result != DOCA_SUCCESS) {
723  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
724  goto destroy_pipe_cfg;
725  }
726  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
727  if (result != DOCA_SUCCESS) {
728  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
729  goto destroy_pipe_cfg;
730  }
731  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTION_ARRAY);
732  if (result != DOCA_SUCCESS) {
733  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
734  goto destroy_pipe_cfg;
735  }
737  if (result != DOCA_SUCCESS) {
738  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
739  goto destroy_pipe_cfg;
740  }
741 
742  simple_fwd_build_fwd(port_cfg, &fwd);
743 
746 
747  if (doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, pipe) != DOCA_SUCCESS)
748  goto destroy_pipe_cfg;
749 
750  doca_flow_pipe_cfg_destroy(pipe_cfg);
751 
752  return 0;
753 
755  doca_flow_pipe_cfg_destroy(pipe_cfg);
756  return -1;
757 }
758 
759 /*
760  * Create DOCA Flow control pipe
761  *
762  * @port_cfg [in]: port configuration as provided by the user
763  * @return: 0 on success, negative value otherwise and error is set.
764  */
766 {
767  struct doca_flow_pipe_cfg *pipe_cfg;
769 
770  result = doca_flow_pipe_cfg_create(&pipe_cfg, simple_fwd_ins->ports[port_cfg->port_id]);
771  if (result != DOCA_SUCCESS) {
772  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
773  return result;
774  }
775 
776  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "CONTROL_PIPE");
777  if (result != DOCA_SUCCESS) {
778  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
779  goto destroy_pipe_cfg;
780  }
782  if (result != DOCA_SUCCESS) {
783  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
784  goto destroy_pipe_cfg;
785  }
786  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, true);
787  if (result != DOCA_SUCCESS) {
788  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
789  goto destroy_pipe_cfg;
790  }
791 
792  if (doca_flow_pipe_create(pipe_cfg, NULL, NULL, &simple_fwd_ins->pipe_control[port_cfg->port_id]) !=
793  DOCA_SUCCESS)
794  goto destroy_pipe_cfg;
795  doca_flow_pipe_cfg_destroy(pipe_cfg);
796  return 0;
797 
799  doca_flow_pipe_cfg_destroy(pipe_cfg);
800  return -1;
801 }
802 
803 /*
804  * Add DOCA Flow pipe entries to the control pipe:
805  * - entry with VXLAN match that forward the matched packet to VxLAN pipe
806  * - entry with GRE match that forward the matched packet to GRE pipe
807  * - entry with GTP match that forward the matched packet to GTP pipe
808  *
809  * @port_cfg [in]: port configuration as provided by the user
810  * @return: 0 on success, negative value otherwise and error is set.
811  */
813 {
814  struct doca_flow_match match;
815  struct doca_flow_fwd fwd;
816  struct doca_flow_pipe_entry *entry;
817  struct entries_status *status;
819  uint8_t priority = 0;
820  int nb_entries = 4;
821 
822  status = (struct entries_status *)calloc(1, sizeof(struct entries_status));
823  if (unlikely(status == NULL))
824  return -1;
825 
826  memset(&match, 0, sizeof(match));
827  memset(&fwd, 0, sizeof(fwd));
828 
832  match.outer.udp.l4_port.dst_port = rte_cpu_to_be_16(DOCA_FLOW_VXLAN_DEFAULT_PORT);
833 
836 
838  priority,
839  simple_fwd_ins->pipe_control[port_cfg->port_id],
840  &match,
841  NULL,
842  NULL,
843  NULL,
844  NULL,
845  NULL,
846  NULL,
847  &fwd,
848  status,
849  &entry);
850  if (result != DOCA_SUCCESS) {
851  free(status);
852  return -1;
853  }
854 
855  memset(&match, 0, sizeof(match));
856  memset(&fwd, 0, sizeof(fwd));
857 
861 
864 
866  priority,
867  simple_fwd_ins->pipe_control[port_cfg->port_id],
868  &match,
869  NULL,
870  NULL,
871  NULL,
872  NULL,
873  NULL,
874  NULL,
875  &fwd,
876  status,
877  &entry);
878  if (result != DOCA_SUCCESS) {
879  free(status);
880  return -1;
881  }
882 
883  memset(&match, 0, sizeof(match));
884  memset(&fwd, 0, sizeof(fwd));
885 
889  match.outer.udp.l4_port.dst_port = rte_cpu_to_be_16(DOCA_FLOW_GTPU_DEFAULT_PORT);
890 
893 
895  priority,
896  simple_fwd_ins->pipe_control[port_cfg->port_id],
897  &match,
898  NULL,
899  NULL,
900  NULL,
901  NULL,
902  NULL,
903  NULL,
904  &fwd,
905  status,
906  &entry);
907  if (result != DOCA_SUCCESS) {
908  free(status);
909  return -1;
910  }
911 
912  memset(&match, 0, sizeof(match));
913  memset(&fwd, 0, sizeof(fwd));
914 
915  priority = 1;
918 
920  priority,
921  simple_fwd_ins->pipe_control[port_cfg->port_id],
922  &match,
923  NULL,
924  NULL,
925  NULL,
926  NULL,
927  NULL,
928  NULL,
929  &fwd,
930  status,
931  &entry);
932  if (result != DOCA_SUCCESS) {
933  free(status);
934  return -1;
935  }
936 
938  if (result != DOCA_SUCCESS)
939  return result;
940 
941  if (status->nb_processed != nb_entries || status->failure)
942  return DOCA_ERROR_BAD_STATE;
943 
944  return 0;
945 }
946 
947 /*
948  * Create DOCA Flow pipe on EGRESS domain with match on the packet meta and encap action with changeable values
949  *
950  * @port_cfg [in]: port configuration
951  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
952  */
954 {
955  struct doca_flow_match match;
957  struct doca_flow_actions actions, *actions_arr[NB_ACTION_ARRAY];
958  struct doca_flow_fwd fwd;
959  struct doca_flow_pipe_cfg *pipe_cfg;
961 
962  memset(&match, 0, sizeof(match));
963  memset(&match_mask, 0, sizeof(match_mask));
964  memset(&actions, 0, sizeof(actions));
965  memset(&fwd, 0, sizeof(fwd));
966 
967  /* match on pkt meta */
968  match_mask.meta.pkt_meta = UINT32_MAX;
969 
970  /* build basic outer VXLAN encap data*/
971  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
972  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
974  actions.encap_cfg.encap.outer.ip4.src_ip = 0xffffffff;
975  actions.encap_cfg.encap.outer.ip4.dst_ip = 0xffffffff;
980  actions.encap_cfg.encap.tun.vxlan_tun_id = 0xffffffff;
981  actions.encap_cfg.is_l2 = true;
983  actions_arr[0] = &actions;
984 
985  result = doca_flow_pipe_cfg_create(&pipe_cfg, simple_fwd_ins->ports[port_cfg->port_id]);
986  if (result != DOCA_SUCCESS) {
987  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
988  return result;
989  }
990 
991  result = doca_flow_pipe_cfg_set_name(pipe_cfg, "VXLAN_ENCAP_PIPE");
992  if (result != DOCA_SUCCESS) {
993  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
994  goto destroy_pipe_cfg;
995  }
997  if (result != DOCA_SUCCESS) {
998  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
999  goto destroy_pipe_cfg;
1000  }
1001  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, true);
1002  if (result != DOCA_SUCCESS) {
1003  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
1004  goto destroy_pipe_cfg;
1005  }
1006  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
1007  if (result != DOCA_SUCCESS) {
1008  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
1009  goto destroy_pipe_cfg;
1010  }
1011  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTION_ARRAY);
1012  if (result != DOCA_SUCCESS) {
1013  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
1014  goto destroy_pipe_cfg;
1015  }
1016 
1017  /* forwarding traffic to the wire */
1019  fwd.port_id = port_cfg->port_id;
1020 
1021  if (doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &simple_fwd_ins->vxlan_encap_pipe[port_cfg->port_id]) !=
1022  DOCA_SUCCESS)
1023  goto destroy_pipe_cfg;
1024 
1025  doca_flow_pipe_cfg_destroy(pipe_cfg);
1026 
1027  return 0;
1028 
1030  doca_flow_pipe_cfg_destroy(pipe_cfg);
1031  return -1;
1032 }
1033 
1034 /*
1035  * Add DOCA Flow pipe entry with example encap values
1036  *
1037  * @port_cfg [in]: port configuration
1038  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
1039  */
1041 {
1042  struct doca_flow_match match;
1043  struct doca_flow_actions actions;
1044  struct doca_flow_pipe_entry *entry;
1045  struct entries_status *status;
1047  int num_of_entries = 1;
1048 
1049  doca_be32_t encap_dst_ip_addr = BE_IPV4_ADDR(81, 81, 81, 81);
1050  doca_be32_t encap_src_ip_addr = BE_IPV4_ADDR(11, 21, 31, 41);
1051  uint8_t encap_ttl = 17;
1052  doca_be32_t encap_vxlan_tun_id = DOCA_HTOBE32(0xadadad);
1053  uint8_t src_mac[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
1054  uint8_t dst_mac[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
1055 
1056  status = (struct entries_status *)calloc(1, sizeof(struct entries_status));
1057 
1058  memset(&match, 0, sizeof(match));
1059  memset(&actions, 0, sizeof(actions));
1060  memset(status, 0, sizeof(*status));
1061  match.meta.pkt_meta = DOCA_HTOBE32(1);
1062 
1064  src_mac[0],
1065  src_mac[1],
1066  src_mac[2],
1067  src_mac[3],
1068  src_mac[4],
1069  src_mac[5]);
1071  dst_mac[0],
1072  dst_mac[1],
1073  dst_mac[2],
1074  dst_mac[3],
1075  dst_mac[4],
1076  dst_mac[5]);
1079  actions.encap_cfg.encap.outer.ip4.src_ip = encap_src_ip_addr;
1080  actions.encap_cfg.encap.outer.ip4.dst_ip = encap_dst_ip_addr;
1081  actions.encap_cfg.encap.outer.ip4.ttl = encap_ttl;
1083  actions.encap_cfg.encap.tun.vxlan_tun_id = encap_vxlan_tun_id;
1084  actions.action_idx = 0;
1085 
1088  &match,
1089  &actions,
1090  NULL,
1091  NULL,
1092  0,
1093  status,
1094  &entry);
1095  if (result != DOCA_SUCCESS) {
1096  free(status);
1097  return -1;
1098  }
1099 
1100  result = doca_flow_entries_process(simple_fwd_ins->ports[port_cfg->port_id], 0, PULL_TIME_OUT, num_of_entries);
1101  if (result != DOCA_SUCCESS)
1102  return result;
1103 
1104  if (status->nb_processed != num_of_entries || status->failure)
1105  return DOCA_ERROR_BAD_STATE;
1106 
1107  return DOCA_SUCCESS;
1108 }
1109 
1110 /*
1111  * Initialize simple FWD application DOCA Flow ports and pipes
1112  *
1113  * @port_cfg [in]: a pointer to the port configuration to initialize
1114  * @return: 0 on success and negative value otherwise
1115  */
1117 {
1118  int nb_ports = SIMPLE_FWD_PORTS;
1119  struct simple_fwd_port_cfg *curr_port_cfg;
1120  int port_id;
1121  int result;
1122 
1123  if (simple_fwd_init_doca_flow(port_cfg->nb_queues, "vnf,hws", port_cfg->nb_counters, port_cfg->nb_meters) < 0) {
1124  DOCA_LOG_ERR("Failed to init DOCA Flow");
1126  return -1;
1127  }
1128 
1130  DOCA_LOG_ERR("Failed to init DOCA ports");
1131  return -1;
1132  }
1133 
1134  for (port_id = 0; port_id < nb_ports; port_id++) {
1135  curr_port_cfg =
1137  curr_port_cfg->port_id = port_id;
1138  curr_port_cfg->nb_queues = port_cfg->nb_queues;
1139  curr_port_cfg->is_hairpin = port_cfg->is_hairpin;
1140  curr_port_cfg->nb_meters = port_cfg->nb_meters;
1141  curr_port_cfg->nb_counters = port_cfg->nb_counters;
1142  curr_port_cfg->age_thread = port_cfg->age_thread;
1143 
1144  result = simple_fwd_build_hairpin_flow(curr_port_cfg->port_id);
1145  if (result < 0) {
1146  DOCA_LOG_ERR("Failed building hairpin flow");
1147  return -1;
1148  }
1149 
1150  result = simple_fwd_build_rss_flow(curr_port_cfg->port_id);
1151  if (result < 0) {
1152  DOCA_LOG_ERR("Failed building RSS flow");
1153  return -1;
1154  }
1155 
1157  if (result < 0) {
1158  DOCA_LOG_ERR("Failed building VXLAN pipe");
1159  return -1;
1160  }
1161 
1163  if (result < 0) {
1164  DOCA_LOG_ERR("Failed building GTPU pipe");
1165  return -1;
1166  }
1167 
1169  if (result < 0) {
1170  DOCA_LOG_ERR("Failed building GRE pipe");
1171  return -1;
1172  }
1173 
1174  result = simple_fwd_create_control_pipe(curr_port_cfg);
1175  if (result < 0) {
1176  DOCA_LOG_ERR("Failed building control pipe");
1177  return -1;
1178  }
1179 
1181  if (result < 0) {
1182  DOCA_LOG_ERR("Failed adding entries to the control pipe");
1183  return -1;
1184  }
1185 
1186  curr_port_cfg->port_id = port_id ^ 1;
1187  result = simple_fwd_create_vxlan_encap_pipe(curr_port_cfg);
1188  if (result != DOCA_SUCCESS) {
1189  DOCA_LOG_ERR("Failed to create vxlan encap pipe: %s", doca_error_get_descr(result));
1190  return -1;
1191  }
1192 
1194  if (result != DOCA_SUCCESS) {
1195  DOCA_LOG_ERR("Failed to add entry to vxlan encap pipe: %s", doca_error_get_descr(result));
1196  return -1;
1197  }
1198  }
1199 
1200  return 0;
1201 }
1202 
1203 /*
1204  * Initialize simple FWD application resources
1205  *
1206  * @p [in]: a pointer to the port configuration
1207  * @return: 0 on success and negative value otherwise
1208  */
1209 static int simple_fwd_init(void *p)
1210 {
1211  struct simple_fwd_port_cfg *port_cfg;
1212  int ret = 0;
1213 
1214  port_cfg = (struct simple_fwd_port_cfg *)p;
1215  ret = simple_fwd_create_ins(port_cfg);
1216  if (ret)
1217  return ret;
1218  return simple_fwd_init_ports_and_pipes(port_cfg);
1219 }
1220 
1221 /*
1222  * Setting tunneling type in the match component
1223  *
1224  * @pinfo [in]: the packet info as represented in the application
1225  * @match [out]: match component to set the tunneling type in based on the packet info provided
1226  */
1227 static inline void simple_fwd_match_set_tun(struct simple_fwd_pkt_info *pinfo, struct doca_flow_match *match)
1228 {
1229  if (!pinfo->tun_type)
1230  return;
1231  match->tun.type = pinfo->tun_type;
1232  switch (match->tun.type) {
1233  case DOCA_FLOW_TUN_VXLAN:
1234  match->tun.vxlan_tun_id = DOCA_HTOBE32(DOCA_BETOH32(pinfo->tun.vni) >> 8);
1235  break;
1236  case DOCA_FLOW_TUN_GRE:
1237  match->tun.gre_key = pinfo->tun.gre_key;
1238  break;
1239  case DOCA_FLOW_TUN_GTPU:
1240  match->tun.gtp_teid = pinfo->tun.teid;
1241  break;
1242  default:
1243  DOCA_LOG_WARN("Unsupported tunnel type:%u", match->tun.type);
1244  break;
1245  }
1246 }
1247 
1248 /*
1249  * Transfer packet l4 type to doca l4 type
1250  *
1251  * @pkt_l4_type [in]: the l4 type of eth packet
1252  * @return: the doca type of the packet l4 type
1253  */
1254 static enum doca_flow_l4_type_ext simple_fwd_l3_type_transfer(uint8_t pkt_l4_type)
1255 {
1256  switch (pkt_l4_type) {
1257  case DOCA_FLOW_PROTO_TCP:
1259  case DOCA_FLOW_PROTO_UDP:
1261  case DOCA_FLOW_PROTO_GRE:
1262  /* set gre type in doca_flow_tun type */
1264  default:
1265  DOCA_LOG_WARN("The L4 type %u is not supported", pkt_l4_type);
1267  }
1268 }
1269 
1270 /*
1271  * Build action component
1272  *
1273  * @pinfo [in]: the packet info as represented in the application
1274  * @match [out]: the actions component to build
1275  */
1277 {
1278  SET_MAC_ADDR(actions->outer.eth.src_mac, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
1279  SET_MAC_ADDR(actions->outer.eth.dst_mac, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
1280 }
1281 
1282 /*
1283  * Build match component
1284  *
1285  * @pinfo [in]: the packet info as represented in the application
1286  * @match [out]: the match component to build
1287  */
1288 static void simple_fwd_build_entry_match(struct simple_fwd_pkt_info *pinfo, struct doca_flow_match *match)
1289 {
1290  memset(match, 0x0, sizeof(*match));
1291  /* set match all fields, pipe will select which field to match */
1300  if (!pinfo->tun_type)
1301  return;
1302  simple_fwd_match_set_tun(pinfo, match);
1309 }
1310 
1311 /*
1312  * Build monitor component
1313  *
1314  * @pinfo [in]: the packet info as represented in the application
1315  * @monitor [out]: the monitor component to build
1316  */
1318 {
1319  (void)pinfo;
1320 
1322  /* flows will be aged out in 5 - 60s */
1323  monitor->aging_sec = (uint32_t)rte_rand() % 55 + 5;
1324 }
1325 
1326 /*
1327  * Selects the pipe based on the tunneling type
1328  *
1329  * @pinfo [in]: the packet info as represented in the application
1330  * @return: a pointer for the selected pipe on success and NULL otherwise
1331  */
1332 static struct doca_flow_pipe *simple_fwd_select_pipe(struct simple_fwd_pkt_info *pinfo)
1333 {
1334  if (pinfo->tun_type == DOCA_FLOW_TUN_GRE)
1335  return simple_fwd_ins->pipe_gre[pinfo->orig_port_id];
1336  if (pinfo->tun_type == DOCA_FLOW_TUN_VXLAN)
1337  return simple_fwd_ins->pipe_vxlan[pinfo->orig_port_id];
1338  if (pinfo->tun_type == DOCA_FLOW_TUN_GTPU)
1339  return simple_fwd_ins->pipe_gtp[pinfo->orig_port_id];
1340  return NULL;
1341 }
1342 
1343 /*
1344  * Adds new entry, with respect to the packet info, to the flow table
1345  *
1346  * @pinfo [in]: the packet info as represented in the application
1347  * @user_ctx [in]: user context
1348  * @age_sec [out]: Aging time for the created entry in seconds
1349  * @return: created entry pointer on success and NULL otherwise
1350  */
1351 static struct doca_flow_pipe_entry *simple_fwd_pipe_add_entry(struct simple_fwd_pkt_info *pinfo,
1352  void *user_ctx,
1353  uint32_t *age_sec)
1354 {
1355  struct doca_flow_match match;
1356  struct doca_flow_monitor monitor = {};
1357  struct doca_flow_actions actions = {0};
1358  struct doca_flow_pipe *pipe;
1359  struct doca_flow_pipe_entry *entry;
1360  struct entries_status *status;
1361  int num_of_entries = 1;
1363 
1364  status = (struct entries_status *)calloc(1, sizeof(struct entries_status));
1365 
1366  memset(&match, 0, sizeof(match));
1367  memset(&actions, 0, sizeof(actions));
1368 
1369  pipe = simple_fwd_select_pipe(pinfo);
1370  if (pipe == NULL) {
1371  DOCA_LOG_WARN("Failed to select pipe on this packet");
1372  free(status);
1373  return NULL;
1374  }
1375 
1377  actions.action_idx = 0;
1378 
1379  status->ft_entry = user_ctx;
1380 
1381  if (pinfo->tun_type != DOCA_FLOW_TUN_VXLAN) {
1383  }
1384 
1385  simple_fwd_build_entry_match(pinfo, &match);
1388  pipe,
1389  &match,
1390  &actions,
1391  &monitor,
1392  NULL,
1394  status,
1395  &entry);
1396  if (result != DOCA_SUCCESS) {
1397  DOCA_LOG_ERR("Failed adding entry to pipe");
1398  free(status);
1399  return NULL;
1400  }
1401 
1403  pinfo->pipe_queue,
1404  PULL_TIME_OUT,
1405  num_of_entries);
1406 
1407  if (result != DOCA_SUCCESS)
1408  goto error;
1409 
1410  if (status->nb_processed != num_of_entries || status->failure)
1411  goto error;
1412 
1413  *age_sec = monitor.aging_sec;
1414  return entry;
1415 
1416 error:
1418  return NULL;
1419 }
1420 
1421 /*
1422  * Adds new flow, with respect to the packet info, to the flow table
1423  *
1424  * @pinfo [in]: the packet info as represented in the application
1425  * @ctx [in]: user context
1426  * @return: 0 on success and negative value otherwise
1427  */
1429 {
1431  struct simple_fwd_pipe_entry *entry = NULL;
1432  struct simple_fwd_ft_entry *ft_entry;
1433  uint32_t age_sec;
1434 
1436  if (result != DOCA_SUCCESS) {
1437  DOCA_LOG_DBG("Failed create new entry");
1438  return -1;
1439  }
1440  ft_entry = GET_FT_ENTRY(*ctx);
1441  entry = (struct simple_fwd_pipe_entry *)&(*ctx)->data[0];
1442  entry->pipe_queue = pinfo->pipe_queue;
1443  entry->hw_entry = simple_fwd_pipe_add_entry(pinfo, (void *)(*ctx), &age_sec);
1444  if (entry->hw_entry == NULL) {
1446  return -1;
1447  }
1448  simple_fwd_ft_update_age_sec(ft_entry, age_sec);
1450  entry->is_hw = true;
1451 
1452  return 0;
1453 }
1454 
1455 /*
1456  * Checks whether or not the received packet info is new.
1457  *
1458  * @pinfo [in]: the packet info as represented in the application
1459  * @return: true on success and false otherwise
1460  */
1462 {
1463  if (pinfo->outer.l3_type != IPV4) {
1464  DOCA_LOG_WARN("The outer L3 type %u is not supported", pinfo->outer.l3_type);
1465  return false;
1466  }
1467  if ((pinfo->outer.l4_type != DOCA_FLOW_PROTO_TCP) && (pinfo->outer.l4_type != DOCA_FLOW_PROTO_UDP) &&
1468  (pinfo->outer.l4_type != DOCA_FLOW_PROTO_GRE)) {
1469  DOCA_LOG_WARN("The outer L4 type %u is not supported", pinfo->outer.l4_type);
1470  return false;
1471  }
1472  return true;
1473 }
1474 
1475 /*
1476  * Adjust the mbuf pointer, to point on the packet's raw data
1477  *
1478  * @pinfo [in]: packet info representation in the application
1479  * @return: 0 on success and negative value otherwise
1480  */
1482 {
1483  struct simple_fwd_ft_user_ctx *ctx = NULL;
1484  struct simple_fwd_pipe_entry *entry = NULL;
1485 
1486  if (!simple_fwd_need_new_ft(pinfo))
1487  return -1;
1488  if (simple_fwd_ft_find(simple_fwd_ins->ft, pinfo, &ctx) != DOCA_SUCCESS) {
1489  if (simple_fwd_handle_new_flow(pinfo, &ctx))
1490  return -1;
1491  }
1492  entry = (struct simple_fwd_pipe_entry *)&ctx->data[0];
1493  entry->total_pkts++;
1494 
1495  return 0;
1496 }
1497 
1498 /*
1499  * Handles aged flows
1500  *
1501  * @port_id [in]: port identifier of the port to handle its aged flows
1502  * @queue [in]: queue index of the queue to handle its aged flows
1503  */
1504 static void simple_fwd_handle_aging(uint32_t port_id, uint16_t queue)
1505 {
1506 #define MAX_HANDLING_TIME_MS 10 /*ms*/
1507 
1508  if (queue > simple_fwd_ins->nb_queues)
1509  return;
1511 }
1512 
1513 /*
1514  * Dump stats of the given port identifier
1515  *
1516  * @port_id [in]: port identifier to dump its stats
1517  * @return: 0 on success and non-zero value on failure
1518  */
1519 static int simple_fwd_dump_stats(uint32_t port_id)
1520 {
1521  return simple_fwd_dump_port_stats(port_id, simple_fwd_ins->ports[port_id]);
1522 }
1523 
1524 /* Stores all functions pointers used by the application */
1525 static struct app_vnf simple_fwd_vnf = {
1526  .vnf_init = &simple_fwd_init, /* Simple Forward initialization resources function pointer */
1527  .vnf_process_pkt = &simple_fwd_handle_packet, /* Simple Forward packet processing function pointer */
1528  .vnf_flow_age = &simple_fwd_handle_aging, /* Simple Forward aging handling function pointer */
1529  .vnf_dump_stats = &simple_fwd_dump_stats, /* Simple Forward dumping stats function pointer */
1530  .vnf_destroy = &simple_fwd_destroy, /* Simple Forward destroy allocated resources function pointer */
1531 };
1532 
1533 /*
1534  * Sets and stores all function pointers, in order to call them later in the application
1535  */
1537 {
1538  return &simple_fwd_vnf;
1539 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
#define unlikely(x)
Definition: utils.h:42
if(bitoffset % 64+bitlength > 64) result|
static int nb_entries
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
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_match match_mask
Definition: flow_parser.c:106
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
#define DOCA_HTOBE32(_x)
#define DOCA_BETOH32(_x)
#define DOCA_ERROR_PROPAGATE(r, t)
Save the first encountered doca_error_t.
Definition: doca_error.h:83
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
doca flow layer 4 packet extend type
#define DOCA_FLOW_VXLAN_DEFAULT_PORT
Definition: doca_flow_net.h:49
#define DOCA_FLOW_PROTO_GRE
Definition: doca_flow_net.h:44
#define DOCA_FLOW_PROTO_UDP
Definition: doca_flow_net.h:42
#define DOCA_FLOW_PROTO_TCP
Definition: doca_flow_net.h:41
#define DOCA_FLOW_GTPU_DEFAULT_PORT
Definition: doca_flow_net.h:48
doca_flow_tun_type
doca flow tunnel type
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
#define DOCA_FLOW_ETHER_ADDR_LEN
Definition: doca_flow_net.h:36
@ DOCA_FLOW_L4_TYPE_EXT_TCP
@ DOCA_FLOW_L4_TYPE_EXT_NONE
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L3_TYPE_IP4
@ DOCA_FLOW_TUN_GRE
@ DOCA_FLOW_TUN_GTPU
@ 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_cfg_set_mode_args(struct doca_flow_cfg *cfg, const char *mode_args)
Set DOCA mode args.
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_STABLE doca_error_t doca_flow_pipe_cfg_set_name(struct doca_flow_pipe_cfg *cfg, const char *name)
Set pipe's name.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_pair(struct doca_flow_port *port, struct doca_flow_port *pair_port)
pair two doca flow ports.
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_cfg_set_nr_meters(struct doca_flow_cfg *cfg, uint32_t nr_meters)
Set number of traffic meters to configure.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_control_add_entry(uint16_t pipe_queue, uint32_t priority, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_match *match_mask, const struct doca_flow_match_condition *condition, const struct doca_flow_actions *actions, const struct doca_flow_actions *actions_mask, const struct doca_flow_action_descs *action_descs, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a control pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_start(const struct doca_flow_port_cfg *cfg, struct doca_flow_port **port)
Start a doca port.
doca_flow_entry_op
doca flow entry operation
Definition: doca_flow.h:146
DOCA_STABLE doca_error_t doca_flow_cfg_set_cb_entry_process(struct doca_flow_cfg *cfg, doca_flow_entry_process_cb cb)
Set callback for entry create/destroy.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_is_root(struct doca_flow_pipe_cfg *cfg, bool is_root)
Set if pipe is root or not.
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_STABLE doca_error_t doca_flow_cfg_create(struct doca_flow_cfg **cfg)
Create DOCA Flow configuration struct.
DOCA_STABLE uint8_t * doca_flow_port_priv_data(struct doca_flow_port *port)
Get pointer of user private data.
#define DOCA_FLOW_MAX_ENTRY_ACTIONS_MEM_SIZE
meter mark color
Definition: doca_flow.h:264
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_type(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_type type)
Set pipe's type.
DOCA_STABLE doca_error_t doca_flow_port_cfg_set_priv_data_size(struct doca_flow_port_cfg *cfg, uint16_t priv_data_size)
Set user private data size.
DOCA_EXPERIMENTAL doca_error_t doca_flow_init(struct doca_flow_cfg *cfg)
Initialize the doca flow.
DOCA_STABLE doca_error_t doca_flow_cfg_set_nr_counters(struct doca_flow_cfg *cfg, uint32_t nr_counters)
Set number of counters to configure.
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_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_actions_mem_size(struct doca_flow_port_cfg *cfg, uint32_t size)
Set max memory size used by actions.
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_STABLE doca_error_t doca_flow_port_stop(struct doca_flow_port *port)
Stop a doca port.
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 doca_error_t doca_flow_pipe_remove_entry(uint16_t pipe_queue, uint32_t flags, struct doca_flow_pipe_entry *entry)
Free one pipe entry.
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_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_port_id(struct doca_flow_port_cfg *cfg, uint16_t port_id)
Set the logical port ID.
DOCA_EXPERIMENTAL doca_error_t doca_flow_cfg_set_default_rss(struct doca_flow_cfg *cfg, const struct doca_flow_resource_rss_cfg *rss)
Set RSS global configuration.
DOCA_STABLE doca_error_t doca_flow_port_cfg_create(struct doca_flow_port_cfg **cfg)
Create DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_port_cfg_destroy(struct doca_flow_port_cfg *cfg)
Destroy DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_cfg_set_pipe_queues(struct doca_flow_cfg *cfg, uint16_t pipe_queues)
Set pipe queues.
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_STABLE doca_error_t doca_flow_cfg_destroy(struct doca_flow_cfg *cfg)
Destroy DOCA Flow configuration struct.
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_UDP
Definition: doca_flow.h:768
@ DOCA_FLOW_ENTRY_OP_ADD
Definition: doca_flow.h:147
@ DOCA_FLOW_ENTRY_OP_AGED
Definition: doca_flow.h:153
@ DOCA_FLOW_ENTRY_OP_DEL
Definition: doca_flow.h:149
@ DOCA_FLOW_PIPE_CONTROL
Definition: doca_flow.h:223
@ 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_L4_META_TCP
Definition: doca_flow.h:308
@ 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_WARN(format,...)
Generates a WARNING application log message.
Definition: doca_log.h:476
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
Definition: doca_log.h:496
uint32_t doca_be32_t
Definition: doca_types.h:121
uint8_t type
Definition: packets.h:0
uint16_t src_port
Definition: packets.h:0
uint16_t dst_port
Definition: packets.h:1
struct app_vnf * simple_fwd_get_vnf(void)
Definition: simple_fwd.c:1536
static struct doca_flow_pipe * simple_fwd_select_pipe(struct simple_fwd_pkt_info *pinfo)
Definition: simple_fwd.c:1332
static struct doca_flow_pipe_entry * simple_fwd_pipe_add_entry(struct simple_fwd_pkt_info *pinfo, void *user_ctx, uint32_t *age_sec)
Definition: simple_fwd.c:1351
static int simple_fwd_destroy(void)
Definition: simple_fwd.c:344
DOCA_LOG_REGISTER(SIMPLE_FWD)
static int simple_fwd_build_rss_flow(uint16_t port_id)
Definition: simple_fwd.c:392
static int simple_fwd_destroy_ins(void)
Definition: simple_fwd.c:321
static int simple_fwd_init_doca_flow(int nb_queues, const char *mode, uint32_t nr_counters, uint32_t nr_meters)
Definition: simple_fwd.c:133
static int simple_fwd_dump_stats(uint32_t port_id)
Definition: simple_fwd.c:1519
static void simple_fwd_build_entry_match(struct simple_fwd_pkt_info *pinfo, struct doca_flow_match *match)
Definition: simple_fwd.c:1288
static bool simple_fwd_need_new_ft(struct simple_fwd_pkt_info *pinfo)
Definition: simple_fwd.c:1461
static int simple_fwd_add_control_pipe_entries(struct simple_fwd_port_cfg *port_cfg)
Definition: simple_fwd.c:812
#define SET_L4_PORT(layer, port, value)
Definition: simple_fwd.c:59
static void simple_fwd_match_set_tun(struct simple_fwd_pkt_info *pinfo, struct doca_flow_match *match)
Definition: simple_fwd.c:1227
static void simple_fwd_build_entry_actions(struct doca_flow_actions *actions)
Definition: simple_fwd.c:1276
static struct doca_flow_port * simple_fwd_create_doca_flow_port(int port_id)
Definition: simple_fwd.c:204
static int simple_fwd_create_control_pipe(struct simple_fwd_port_cfg *port_cfg)
Definition: simple_fwd.c:765
static doca_error_t simple_fwd_create_vxlan_encap_pipe(struct simple_fwd_port_cfg *port_cfg)
Definition: simple_fwd.c:953
static void simple_fwd_aged_flow_cb(struct simple_fwd_ft_user_ctx *ctx)
Definition: simple_fwd.c:306
static int simple_fwd_init(void *p)
Definition: simple_fwd.c:1209
#define BE_IPV4_ADDR(a, b, c, d)
Definition: simple_fwd.c:45
static int simple_fwd_create_ins(struct simple_fwd_port_cfg *port_cfg)
Definition: simple_fwd.c:357
static int simple_fwd_handle_new_flow(struct simple_fwd_pkt_info *pinfo, struct simple_fwd_ft_user_ctx **ctx)
Definition: simple_fwd.c:1428
static struct simple_fwd_app * simple_fwd_ins
Definition: simple_fwd.c:77
#define SET_MAC_ADDR(addr, a, b, c, d, e, f)
Definition: simple_fwd.c:48
static int simple_fwd_init_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin)
Definition: simple_fwd.c:276
static void simple_fwd_stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
Definition: simple_fwd.c:258
static int simple_fwd_build_hairpin_flow(uint16_t port_id)
Definition: simple_fwd.c:492
static void simple_fwd_build_entry_monitor(struct simple_fwd_pkt_info *pinfo, struct doca_flow_monitor *monitor)
Definition: simple_fwd.c:1317
static int simple_fwd_handle_packet(struct simple_fwd_pkt_info *pinfo)
Definition: simple_fwd.c:1481
static void simple_fwd_build_fwd(struct simple_fwd_port_cfg *port_cfg, struct doca_flow_fwd *fwd)
Definition: simple_fwd.c:589
static int simple_fwd_init_ports_and_pipes(struct simple_fwd_port_cfg *port_cfg)
Definition: simple_fwd.c:1116
#define GET_FT_ENTRY(ctx)
Definition: simple_fwd.c:71
#define NB_ACTION_ARRAY
Definition: simple_fwd.c:74
static void simple_fwd_handle_aging(uint32_t port_id, uint16_t queue)
Definition: simple_fwd.c:1504
static void simple_fwd_check_for_valid_entry(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)
Definition: simple_fwd.c:95
static struct app_vnf simple_fwd_vnf
Definition: simple_fwd.c:1525
static enum doca_flow_l4_type_ext simple_fwd_l3_type_transfer(uint8_t pkt_l4_type)
Definition: simple_fwd.c:1254
#define PULL_TIME_OUT
Definition: simple_fwd.c:73
static int simple_fwd_create_match_pipe(struct simple_fwd_port_cfg *port_cfg, enum doca_flow_tun_type type)
Definition: simple_fwd.c:633
#define MAX_HANDLING_TIME_MS
static doca_error_t simple_fwd_add_vxlan_encap_pipe_entry(struct simple_fwd_port_cfg *port_cfg)
Definition: simple_fwd.c:1040
static void simple_fwd_build_pipe_common_match_fields(struct doca_flow_match *match)
Definition: simple_fwd.c:607
#define SIMPLE_FWD_PORTS
Definition: simple_fwd.h:37
#define SIMPLE_FWD_MAX_FLOWS
Definition: simple_fwd.h:38
void simple_fwd_ft_update_expiration(struct simple_fwd_ft_entry *e)
Definition: simple_fwd_ft.c:78
struct simple_fwd_ft * simple_fwd_ft_create(int nb_flows, uint32_t user_data_size, void(*simple_fwd_aging_cb)(struct simple_fwd_ft_user_ctx *ctx), void(*simple_fwd_aging_hw_cb)(void), bool age_thread)
doca_error_t simple_fwd_ft_find(struct simple_fwd_ft *ft, struct simple_fwd_pkt_info *pinfo, struct simple_fwd_ft_user_ctx **ctx)
doca_error_t simple_fwd_ft_destroy(struct simple_fwd_ft *ft)
void simple_fwd_ft_destroy_entry(struct simple_fwd_ft *ft, struct simple_fwd_ft_entry *ft_entry)
doca_error_t simple_fwd_ft_add_new(struct simple_fwd_ft *ft, struct simple_fwd_pkt_info *pinfo, struct simple_fwd_ft_user_ctx **ctx)
void simple_fwd_ft_update_age_sec(struct simple_fwd_ft_entry *e, uint32_t age_sec)
Definition: simple_fwd_ft.c:73
doca_be16_t simple_fwd_pinfo_inner_dst_port(struct simple_fwd_pkt_info *pinfo)
doca_be16_t simple_fwd_pinfo_outer_dst_port(struct simple_fwd_pkt_info *pinfo)
doca_be32_t simple_fwd_pinfo_outer_ipv4_src(struct simple_fwd_pkt_info *pinfo)
doca_be16_t simple_fwd_pinfo_inner_src_port(struct simple_fwd_pkt_info *pinfo)
doca_be16_t simple_fwd_pinfo_outer_src_port(struct simple_fwd_pkt_info *pinfo)
doca_be32_t simple_fwd_pinfo_inner_ipv4_src(struct simple_fwd_pkt_info *pinfo)
doca_be32_t simple_fwd_pinfo_inner_ipv4_dst(struct simple_fwd_pkt_info *pinfo)
uint8_t * simple_fwd_pinfo_outer_mac_src(struct simple_fwd_pkt_info *pinfo)
doca_be32_t simple_fwd_pinfo_outer_ipv4_dst(struct simple_fwd_pkt_info *pinfo)
uint8_t * simple_fwd_pinfo_outer_mac_dst(struct simple_fwd_pkt_info *pinfo)
int simple_fwd_dump_port_stats(uint16_t port_id, struct doca_flow_port *port)
int(* vnf_init)(void *p)
Definition: app_vnf.h:35
action descriptor array
Definition: doca_flow.h:1033
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_resource_encap_cfg encap_cfg
Definition: doca_flow.h:710
struct doca_flow_header_format outer
Definition: doca_flow.h:703
enum doca_flow_resource_type encap_type
Definition: doca_flow.h:707
struct doca_flow_meta meta
Definition: doca_flow.h:699
enum doca_flow_resource_type decap_type
Definition: doca_flow.h:689
struct doca_flow_resource_decap_cfg decap_cfg
Definition: doca_flow.h:692
uint8_t action_idx
Definition: doca_flow.h:685
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
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_tcp tcp
Definition: doca_flow.h:461
struct doca_flow_header_l4_port l4_port
struct doca_flow_header_l4_port l4_port
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_header_format inner
Definition: doca_flow.h:502
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
struct doca_flow_header_format outer
Definition: doca_flow.h:498
struct doca_flow_tun tun
Definition: doca_flow.h:500
struct doca_flow_meta meta
Definition: doca_flow.h:494
doca_be32_t pkt_meta
Definition: doca_flow.h:359
doca monitor action configuration
Definition: doca_flow.h:968
enum doca_flow_resource_type counter_type
Definition: doca_flow.h:988
uint32_t aging_sec
Definition: doca_flow.h:1000
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l3_meta inner_l3_type
Definition: doca_flow.h:385
enum doca_flow_l4_meta inner_l4_type
Definition: doca_flow.h:386
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
struct doca_flow_encap_action encap
Definition: doca_flow.h:663
doca flow rss resource configuration
Definition: doca_flow.h:180
enum doca_flow_tun_type type
doca_be32_t vxlan_tun_id
doca_be32_t gtp_teid
doca_be32_t gre_key
user context struct that will be used in entries process callback
Definition: flow_common.h:78
void * ft_entry
Definition: simple_fwd.c:83
struct doca_flow_pipe * pipe_rss[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:50
struct doca_flow_pipe * pipe_vxlan[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:45
struct simple_fwd_ft * ft
Definition: simple_fwd.h:42
struct doca_flow_pipe * pipe_hairpin[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:49
struct doca_flow_port * ports[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:44
uint16_t nb_queues
Definition: simple_fwd.h:52
struct doca_flow_pipe * pipe_gre[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:46
struct doca_flow_pipe * vxlan_encap_pipe[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:51
struct doca_flow_pipe * pipe_control[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:48
struct doca_flow_pipe * pipe_gtp[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:47
uint16_t hairpin_peer[SIMPLE_FWD_PORTS]
Definition: simple_fwd.h:43
Definition: simple_fwd_ft.h:47
uint32_t age_sec
Definition: simple_fwd_ft.h:51
Definition: simple_fwd.h:57
struct simple_fwd_pkt_format outer
enum doca_flow_tun_type tun_type
struct simple_fwd_pkt_format inner
struct simple_fwd_pkt_tun_format tun
static int nb_ports
Definition: switch_core.c:44
static struct doca_flow_port * ports[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:42
struct upf_accel_ctx * ctx
void linear_array_init_u16(uint16_t *array, uint16_t n)
Definition: utils.c:109