NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_fwd_miss_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <stdbool.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include <rte_byteorder.h>
31 
32 #include <doca_log.h>
33 #include <doca_flow.h>
34 
35 #include "flow_common.h"
36 
37 DOCA_LOG_REGISTER(FLOW_FWD_MISS);
38 
39 /* The number of seconds app waits for traffic to come */
40 #define WAITING_TIME 5
41 
42 /*
43  * Create pipe configure structure.
44  *
45  * @port [in]: port of the pipe.
46  * @name [in]: name of the pipe.
47  * @match [in]: match structure for this pipe.
48  * @actions [in]: actions array for this pipe.
49  * @descs [in]: action descriptor array for this pipe.
50  * @nb_actions [in]: nb_actions of the pipe.
51  * @nb_flows [in]: nb_flows of the pipe.
52  * @is_root [in]: indicator whether this pipe is root.
53  * @miss_counter [in]: pipe has miss counter.
54  * @pipe_cfg [out]: created pipe configuration pointer.
55  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
56  */
57 static doca_error_t create_pipe_cfg(struct doca_flow_port *port,
58  const char *name,
59  struct doca_flow_match *match,
60  struct doca_flow_actions **actions,
61  struct doca_flow_action_descs **descs,
62  uint32_t nb_actions,
63  uint32_t nb_flows,
64  bool is_root,
65  bool miss_counter,
66  struct doca_flow_pipe_cfg **pipe_cfg)
67 {
68  struct doca_flow_pipe_cfg *cfg;
70 
72  if (result != DOCA_SUCCESS) {
73  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
74  return result;
75  }
76 
78  if (result != DOCA_SUCCESS) {
79  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
81  return result;
82  }
83 
85  if (result != DOCA_SUCCESS) {
86  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg number entries: %s", doca_error_get_descr(result));
88  return result;
89  }
90 
92  if (result != DOCA_SUCCESS) {
93  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg miss counter: %s", doca_error_get_descr(result));
95  return result;
96  }
97 
99  if (result != DOCA_SUCCESS) {
100  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
102  return result;
103  }
104 
105  if (actions || descs) {
106  result = doca_flow_pipe_cfg_set_actions(cfg, actions, NULL, descs, nb_actions);
107  if (result != DOCA_SUCCESS) {
108  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
110  return result;
111  }
112  }
113 
114  *pipe_cfg = cfg;
115  return DOCA_SUCCESS;
116 }
117 
118 /*
119  * Destroy pipe configure structure.
120  *
121  * @cfg [in]: pipe cfg structure to destroy.
122  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
123  */
124 static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
125 {
127 }
128 
129 /*
130  * Create basic pipe and its configure structure.
131  *
132  * @port [in]: port of the pipe.
133  * @name [in]: name of the pipe.
134  * @match [in]: match structure for this pipe.
135  * @actions [in]: actions array for this pipe.
136  * @descs [in]: action descriptor array for this pipe.
137  * @fwd [in]: action descriptor array for this pipe.
138  * @fwd_miss [in]: action descriptor array for this pipe.
139  * @nb_actions [in]: nb_actions of the pipe.
140  * @nb_flows [in]: nb_flows of the pipe.
141  * @is_root [in]: indicator whether this pipe is root.
142  * @miss_counter [in]: pipe has miss counter.
143  * @pipe [out]: created pipe configuration pointer.
144  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
145  */
146 static doca_error_t create_basic_pipe(struct doca_flow_port *port,
147  const char *name,
148  struct doca_flow_match *match,
149  struct doca_flow_actions **actions,
150  struct doca_flow_action_descs **descs,
151  struct doca_flow_fwd *fwd,
152  struct doca_flow_fwd *fwd_miss,
153  uint32_t nb_actions,
154  uint32_t nb_flows,
155  bool is_root,
156  bool miss_counter,
157  struct doca_flow_pipe **pipe)
158 {
159  struct doca_flow_pipe_cfg *cfg;
161 
162  result = create_pipe_cfg(port, name, match, actions, descs, nb_actions, nb_flows, is_root, miss_counter, &cfg);
163  if (result != DOCA_SUCCESS) {
164  DOCA_LOG_ERR("Failed to create basic pipe, configuration failed");
165  return result;
166  }
167 
169  if (result != DOCA_SUCCESS) {
170  DOCA_LOG_ERR("Failed to create basic pipe, pipe creation failed");
172  return result;
173  }
174 
176  if (result != DOCA_SUCCESS) {
177  DOCA_LOG_ERR("Failed to create basic pipe, configuration destruction failed");
178  doca_flow_pipe_destroy(*pipe);
179  return result;
180  }
181 
182  DOCA_LOG_DBG("Basic pipe %s is created successfully", name);
183  return DOCA_SUCCESS;
184 }
185 
186 /*
187  * Create DOCA Flow pipe that modify IP field and goes to the pair port.
188  *
189  * @port [in]: port of the pipe.
190  * @fwd [in]: forward the traffic that hit the pipe rule.
191  * @status [in]: user context for adding entry.
192  * @pipe_ptr [out]: created pipe pointer.
193  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
194  */
195 static doca_error_t create_modify_pipe(struct doca_flow_port *port,
196  struct doca_flow_fwd *fwd,
197  struct entries_status *status,
198  struct doca_flow_pipe **pipe_ptr)
199 {
200  struct doca_flow_match match = {.parser_meta = {.outer_l3_type = UINT32_MAX}};
201  struct doca_flow_actions actions = {0};
202  struct doca_flow_action_desc ip4_desc = {0};
203  struct doca_flow_action_desc ip6_desc = {0};
204  struct doca_flow_action_descs ip4_descs = {.nb_action_desc = 1, .desc_array = &ip4_desc};
205  struct doca_flow_action_descs ip6_descs = {.nb_action_desc = 1, .desc_array = &ip6_desc};
206  struct doca_flow_action_descs *descs_arr[] = {&ip4_descs, &ip6_descs};
207  struct doca_flow_pipe *pipe;
208  struct doca_flow_pipe_entry *entry;
210 
211  ip4_desc.type = DOCA_FLOW_ACTION_COPY;
212  ip4_desc.field_op.src.field_string = "outer.ipv4.version_ihl";
213  ip4_desc.field_op.dst.field_string = "outer.ipv4.dscp_ecn";
214  ip4_desc.field_op.width = 4;
215 
216  ip6_desc.type = DOCA_FLOW_ACTION_COPY;
217  ip6_desc.field_op.src.field_string = "outer.ipv6.payload_len";
218  ip6_desc.field_op.dst.field_string = "outer.ipv6.traffic_class";
219  ip6_desc.field_op.width = 8;
220 
221  result = create_basic_pipe(port, "MODIFY_PIPE", &match, NULL, descs_arr, fwd, NULL, 2, 2, false, false, &pipe);
222  if (result != DOCA_SUCCESS) {
223  DOCA_LOG_ERR("Failed to create modify pipe, pipe creation failed");
224  return result;
225  }
226 
228  actions.action_idx = 0;
229  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
230  if (result != DOCA_SUCCESS) {
231  DOCA_LOG_ERR("Failed to create modify pipe, IPv4 entry adding failed");
233  return result;
234  }
235 
237  actions.action_idx = 1;
238  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
239  if (result != DOCA_SUCCESS) {
240  DOCA_LOG_ERR("Failed to create modify pipe, IPv6 entry adding failed");
242  return result;
243  }
244 
245  *pipe_ptr = pipe;
246  return DOCA_SUCCESS;
247 }
248 
249 /*
250  * Create DOCA Flow pipe that push VLAN header and goes to the pair port.
251  *
252  * @port [in]: port of the pipe.
253  * @fwd [in]: forward the traffic that hit the pipe rule.
254  * @status [in]: user context for adding entry.
255  * @pipe_ptr [out]: created pipe pointer.
256  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
257  */
258 static doca_error_t create_push_pipe(struct doca_flow_port *port,
259  struct doca_flow_fwd *fwd,
260  struct entries_status *status,
261  struct doca_flow_pipe **pipe_ptr)
262 {
263  struct doca_flow_match match = {0};
264  struct doca_flow_actions actions = {0};
265  struct doca_flow_actions *actions_arr[] = {&actions};
266  struct doca_flow_pipe *pipe;
267  struct doca_flow_pipe_entry *entry;
269 
270  actions.has_push = true;
272  actions.push.vlan.eth_type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_VLAN);
273  actions.push.vlan.vlan_hdr.tci = rte_cpu_to_be_16(0x1234);
274 
275  result = create_basic_pipe(port, "PUSH_PIPE", &match, actions_arr, NULL, fwd, NULL, 1, 1, false, false, &pipe);
276  if (result != DOCA_SUCCESS) {
277  DOCA_LOG_ERR("Failed to create push pipe, pipe creation failed");
278  return result;
279  }
280 
281  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
282  if (result != DOCA_SUCCESS) {
283  DOCA_LOG_ERR("Failed to create push pipe, entry adding failed");
285  return result;
286  }
287 
288  *pipe_ptr = pipe;
289  return DOCA_SUCCESS;
290 }
291 
292 /*
293  * Create DOCA Flow pipe matching on IP addresses.
294  *
295  * @port [in]: port of the pipe.
296  * @fwd [in]: forward the traffic that hit the pipe rule.
297  * @modify_pipe [in]: pipe to forward the traffic that didn't hit the pipe rule.
298  * @status [in]: user context for adding entry.
299  * @pipe_ptr [out]: created pipe pointer
300  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
301  */
302 static doca_error_t create_ipv4_pipe(struct doca_flow_port *port,
303  struct doca_flow_fwd *fwd,
304  struct doca_flow_pipe *modify_pipe,
305  struct entries_status *status,
306  struct doca_flow_pipe **pipe_ptr)
307 {
308  struct doca_flow_fwd fwd_miss = {.type = DOCA_FLOW_FWD_PIPE, .next_pipe = modify_pipe};
309  struct doca_flow_match match = {0};
310  struct doca_flow_pipe *pipe;
311  struct doca_flow_pipe_entry *entry;
313 
315  match.outer.ip4.src_ip = BE_IPV4_ADDR(1, 2, 3, 4);
316  match.outer.ip4.dst_ip = BE_IPV4_ADDR(8, 8, 8, 8);
317 
318  result = create_basic_pipe(port, "IPV4_PIPE", &match, NULL, NULL, fwd, &fwd_miss, 0, 1, false, false, &pipe);
319  if (result != DOCA_SUCCESS) {
320  DOCA_LOG_ERR("Failed to create IPv4 pipe, pipe creation failed");
321  return result;
322  }
323 
324  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
325  if (result != DOCA_SUCCESS) {
326  DOCA_LOG_ERR("Failed to create IPv4 pipe, entry adding failed");
328  return result;
329  }
330 
331  *pipe_ptr = pipe;
332  return DOCA_SUCCESS;
333 }
334 
335 /*
336  * Create DOCA Flow pipe that match on outer IP type and send IPv4 to next pipe and IPv6 to miss pipe.
337  *
338  * @port [in]: port of the pipe.
339  * @ipv4_pipe [in]: pipe to forward the traffic that hit the pipe rule.
340  * @modify_pipe [in]: pipe to forward the traffic that didn't hit the pipe rule.
341  * @status [in]: user context for adding entry.
342  * @pipe_ptr [out]: created pipe pointer
343  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
344  */
345 static doca_error_t create_ip_selector_pipe(struct doca_flow_port *port,
346  struct doca_flow_pipe *ipv4_pipe,
347  struct doca_flow_pipe *modify_pipe,
348  struct entries_status *status,
349  struct doca_flow_pipe **pipe_ptr)
350 {
352  struct doca_flow_fwd fwd = {.type = DOCA_FLOW_FWD_PIPE, .next_pipe = ipv4_pipe};
353  struct doca_flow_fwd fwd_miss = {.type = DOCA_FLOW_FWD_PIPE, .next_pipe = modify_pipe};
354  struct doca_flow_pipe *pipe;
355  struct doca_flow_pipe_entry *entry;
357 
358  result = create_basic_pipe(port,
359  "IP_SELECTOR_PIPE",
360  &match,
361  NULL /* actions */,
362  NULL /* descs */,
363  &fwd,
364  &fwd_miss,
365  0 /* nb_actions */,
366  1 /* nb_flows */,
367  false /* is_root */,
368  true /* miss_counter */,
369  &pipe);
370  if (result != DOCA_SUCCESS) {
371  DOCA_LOG_ERR("Failed to create ip selector pipe, pipe creation failed");
372  return result;
373  }
374 
375  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
376  if (result != DOCA_SUCCESS) {
377  DOCA_LOG_ERR("Failed to create ip selector pipe, entry adding failed");
379  return result;
380  }
381 
382  *pipe_ptr = pipe;
383  return DOCA_SUCCESS;
384 }
385 
386 /*
387  * Create DOCA Flow pipe that modify IP field and goes to the hairpin pipe.
388  *
389  * @port [in]: port of the pipe.
390  * @next_pipe [in]: IP selector pipe to forward to.
391  * @status [in]: user context for adding entry.
392  * @pipe_ptr [out]: created pipe pointer.
393  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
394  */
395 static doca_error_t create_root_pipe(struct doca_flow_port *port,
396  struct doca_flow_pipe *next_pipe,
397  struct entries_status *status,
398  struct doca_flow_pipe **pipe_ptr)
399 {
400  struct doca_flow_match match = {.parser_meta = {.outer_l3_type = UINT32_MAX}};
401  struct doca_flow_fwd fwd = {.type = DOCA_FLOW_FWD_PIPE, .next_pipe = next_pipe};
403  struct doca_flow_pipe *pipe;
404  struct doca_flow_pipe_entry *entry;
406 
407  result = create_basic_pipe(port, "ROOT_PIPE", &match, NULL, NULL, &fwd, &fwd_miss, 0, 2, true, true, &pipe);
408  if (result != DOCA_SUCCESS) {
409  DOCA_LOG_ERR("Failed to create root pipe, pipe creation failed");
410  return result;
411  }
412 
414  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
415  if (result != DOCA_SUCCESS) {
416  DOCA_LOG_ERR("Failed to create root pipe, IPv4 entry adding failed");
418  return result;
419  }
420 
422  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
423  if (result != DOCA_SUCCESS) {
424  DOCA_LOG_ERR("Failed to create root pipe, IPv6 entry adding failed");
426  return result;
427  }
428 
429  *pipe_ptr = pipe;
430  return DOCA_SUCCESS;
431 }
432 
433 /*
434  * Query the miss counters and show the results.
435  *
436  * @root_pipe [in]: root pipe containing miss counter for drop action.
437  * @ip_selector_pipe [in]: IP selector pipe containing miss counter for group action.
438  * @miss_is_updated [in]: indicator whether miss updating is done.
439  * @port_id [in]: port ID of the pipes.
440  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
441  */
442 static doca_error_t miss_counters_query(struct doca_flow_pipe *root_pipe,
443  struct doca_flow_pipe *ip_selector_pipe,
444  bool miss_is_updated,
445  int port_id)
446 {
447  struct doca_flow_resource_query query_stats;
449 
450  result = doca_flow_resource_query_pipe_miss(root_pipe, &query_stats);
451  if (result != DOCA_SUCCESS) {
452  DOCA_LOG_ERR("Port %u failed to query root pipe miss: %s", port_id, doca_error_get_descr(result));
453  return result;
454  }
455 
456  DOCA_LOG_INFO("Port %d root pipe miss %ld packets %s updating",
457  port_id,
458  query_stats.counter.total_pkts,
459  miss_is_updated ? "after" : "before");
460 
461  result = doca_flow_resource_query_pipe_miss(ip_selector_pipe, &query_stats);
462  if (result != DOCA_SUCCESS) {
463  DOCA_LOG_ERR("Port %u failed to query IP selector pipe miss: %s",
464  port_id,
466  return result;
467  }
468 
469  DOCA_LOG_INFO("Port %d IP selector pipe miss %ld packets %s updating",
470  port_id,
471  query_stats.counter.total_pkts,
472  miss_is_updated ? "after" : "before");
473 
474  return DOCA_SUCCESS;
475 }
476 
477 /*
478  * Update the the pipe target of FWD miss action.
479  *
480  * @pipe [in]: pipe to update its miss action.
481  * @next_pipe [in]: a new pipe to forward the traffic that didn't hit the pipe rule.
482  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
483  */
484 static doca_error_t update_miss_fwd_next_pipe(struct doca_flow_pipe *pipe, struct doca_flow_pipe *next_pipe)
485 {
486  struct doca_flow_fwd fwd_miss = {.type = DOCA_FLOW_FWD_PIPE, .next_pipe = next_pipe};
487 
489 }
490 
491 enum {
498 };
499 
500 /*
501  * Run flow_fwd_miss sample
502  *
503  * @nb_queues [in]: number of queues the sample will use
504  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
505  */
507 {
508  const int nb_ports = 2;
509  struct flow_resources resource = {.nr_counters = 4};
510  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
511  struct doca_flow_port *port, *ports[nb_ports];
512  struct doca_dev *dev_arr[nb_ports];
513  uint32_t actions_mem_size[nb_ports];
514  struct doca_flow_pipe **pipes, *pipes_array[nb_ports][NUMBER_OF_PIPES];
515  struct doca_flow_fwd fwd_port = {.type = DOCA_FLOW_FWD_PORT};
516  struct entries_status status;
517  uint32_t num_of_entries = 6;
519  int port_id;
520 
521  result = init_doca_flow(nb_queues, "vnf,hws", &resource, nr_shared_resources);
522  if (result != DOCA_SUCCESS) {
523  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
524  return result;
525  }
526 
527  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
528  ARRAY_INIT(actions_mem_size, ACTIONS_MEM_SIZE(nb_queues, num_of_entries));
530  if (result != DOCA_SUCCESS) {
531  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
533  return result;
534  }
535 
536  for (port_id = 0; port_id < nb_ports; port_id++) {
537  memset(&status, 0, sizeof(status));
538  pipes = pipes_array[port_id];
539  port = ports[port_id];
540  fwd_port.port_id = port_id ^ 1;
541 
542  DOCA_LOG_DBG("Port %u starts preparing the first pipeline", port_id);
543 
544  result = create_modify_pipe(port, &fwd_port, &status, &pipes[MODIFY]);
545  if (result != DOCA_SUCCESS) {
546  DOCA_LOG_ERR("Port %u failed to create modify pipe: %s", port_id, doca_error_get_descr(result));
549  return result;
550  }
551 
552  result = create_ipv4_pipe(port, &fwd_port, pipes[MODIFY], &status, &pipes[IPV4]);
553  if (result != DOCA_SUCCESS) {
554  DOCA_LOG_ERR("Port %u failed to create IPv4 pipe: %s", port_id, doca_error_get_descr(result));
557  return result;
558  }
559 
560  result = create_ip_selector_pipe(port, pipes[IPV4], pipes[MODIFY], &status, &pipes[IP_SELECTOR]);
561  if (result != DOCA_SUCCESS) {
562  DOCA_LOG_ERR("Port %u failed to create IP selector pipe: %s",
563  port_id,
567  return result;
568  }
569 
570  result = create_root_pipe(port, pipes[IP_SELECTOR], &status, &pipes[ROOT]);
571  if (result != DOCA_SUCCESS) {
572  DOCA_LOG_ERR("Port %u failed to create root pipe: %s", port_id, doca_error_get_descr(result));
575  return result;
576  }
577 
578  result = flow_process_entries(port, &status, num_of_entries);
579  if (result != DOCA_SUCCESS) {
580  DOCA_LOG_ERR("Port %u failed to process %u entries: %s",
581  port_id,
582  num_of_entries,
586  return result;
587  }
588  }
589 
590  /* wait few seconds for packets to arrive so query will not return zero */
591  DOCA_LOG_INFO("Wait %d seconds for first batch of packets to arrive", WAITING_TIME);
592  sleep(WAITING_TIME);
593 
594  DOCA_LOG_DBG("Show miss counter results after first batch of packets");
595 
596  for (port_id = 0; port_id < nb_ports; port_id++) {
597  pipes = pipes_array[port_id];
598 
599  result = miss_counters_query(pipes[ROOT], pipes[IP_SELECTOR], false, port_id);
600  if (result != DOCA_SUCCESS) {
601  DOCA_LOG_ERR("Port %u failed to query miss counters before updating: %s",
602  port_id,
606  return result;
607  }
608  }
609 
610  for (port_id = 0; port_id < nb_ports; port_id++) {
611  memset(&status, 0, sizeof(status));
612  pipes = pipes_array[port_id];
613  port = ports[port_id];
614  fwd_port.port_id = port_id ^ 1;
615 
616  DOCA_LOG_DBG("Port %u starts preparing the second pipeline", port_id);
617 
618  result = create_push_pipe(port, &fwd_port, &status, &pipes[PUSH]);
619  if (result != DOCA_SUCCESS) {
620  DOCA_LOG_ERR("Port %u failed to create push pipe: %s", port_id, doca_error_get_descr(result));
623  return result;
624  }
625 
626  result = flow_process_entries(port, &status, 1);
627  if (result != DOCA_SUCCESS) {
628  DOCA_LOG_ERR("Port %u failed to process pipe push entry: %s",
629  port_id,
633  return result;
634  }
635 
636  DOCA_LOG_DBG("Port %u updates the FWD miss actions", port_id);
637 
638  result = update_miss_fwd_next_pipe(pipes[IPV4], pipes[PUSH]);
639  if (result != DOCA_SUCCESS) {
640  DOCA_LOG_ERR("Port %u failed to update fwd miss for IPv4 pipe: %s",
641  port_id,
645  return result;
646  }
647 
649  if (result != DOCA_SUCCESS) {
650  DOCA_LOG_ERR("Port %u failed to update fwd miss for IP selector pipe: %s",
651  port_id,
655  return result;
656  }
657  }
658 
659  /* wait few seconds for packets to arrive so query will not return zero */
660  DOCA_LOG_INFO("Wait %d seconds for second batch of packets to arrive", WAITING_TIME);
661  sleep(WAITING_TIME);
662 
663  DOCA_LOG_DBG("Show miss counter results after second batch of packets");
664 
665  for (port_id = 0; port_id < nb_ports; port_id++) {
666  pipes = pipes_array[port_id];
667 
668  result = miss_counters_query(pipes[ROOT], pipes[IP_SELECTOR], true, port_id);
669  if (result != DOCA_SUCCESS) {
670  DOCA_LOG_ERR("Port %u failed to query miss counters after updating: %s",
671  port_id,
675  return result;
676  }
677  }
678 
681  return result;
682 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
struct doca_flow_port * init_doca_flow(uint16_t port_id, uint8_t rxq_num)
Definition: flow.c:37
static doca_error_t update_miss_fwd_next_pipe(struct doca_flow_pipe *pipe, struct doca_flow_pipe *next_pipe)
doca_error_t flow_fwd_miss(int nb_queues)
static doca_error_t miss_counters_query(struct doca_flow_pipe *root_pipe, struct doca_flow_pipe *ip_selector_pipe, bool miss_is_updated, int port_id)
static doca_error_t create_root_pipe(struct doca_flow_port *port, struct doca_flow_pipe *next_pipe, struct entries_status *status, struct doca_flow_pipe **pipe_ptr)
@ NUMBER_OF_PIPES
@ IP_SELECTOR
static doca_error_t create_pipe_cfg(struct doca_flow_port *port, const char *name, struct doca_flow_match *match, struct doca_flow_actions **actions, struct doca_flow_action_descs **descs, uint32_t nb_actions, uint32_t nb_flows, bool is_root, bool miss_counter, struct doca_flow_pipe_cfg **pipe_cfg)
static doca_error_t create_ip_selector_pipe(struct doca_flow_port *port, struct doca_flow_pipe *ipv4_pipe, struct doca_flow_pipe *modify_pipe, struct entries_status *status, struct doca_flow_pipe **pipe_ptr)
static doca_error_t create_basic_pipe(struct doca_flow_port *port, const char *name, struct doca_flow_match *match, struct doca_flow_actions **actions, struct doca_flow_action_descs **descs, struct doca_flow_fwd *fwd, struct doca_flow_fwd *fwd_miss, uint32_t nb_actions, uint32_t nb_flows, bool is_root, bool miss_counter, struct doca_flow_pipe **pipe)
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static doca_error_t create_modify_pipe(struct doca_flow_port *port, struct doca_flow_fwd *fwd, struct entries_status *status, struct doca_flow_pipe **pipe_ptr)
#define WAITING_TIME
DOCA_LOG_REGISTER(FLOW_FWD_MISS)
static doca_error_t create_ipv4_pipe(struct doca_flow_port *port, struct doca_flow_fwd *fwd, struct doca_flow_pipe *modify_pipe, struct entries_status *status, struct doca_flow_pipe **pipe_ptr)
static doca_error_t create_push_pipe(struct doca_flow_port *port, struct doca_flow_fwd *fwd, struct entries_status *status, struct doca_flow_pipe **pipe_ptr)
static struct doca_flow_fwd fwd_miss
Definition: flow_parser.c:110
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_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
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_SUCCESS
Definition: doca_error.h:38
#define DOCA_FLOW_ETHER_TYPE_VLAN
Definition: doca_flow_net.h:61
@ 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_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_update_miss(struct doca_flow_pipe *pipe, const struct doca_flow_fwd *fwd_miss)
Update the forward miss action.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_miss_counter(struct doca_flow_pipe_cfg *cfg, bool miss_counter)
Set to enable pipe's miss counter.
DOCA_STABLE void doca_flow_pipe_destroy(struct doca_flow_pipe *pipe)
Destroy one pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_actions(struct doca_flow_pipe_cfg *cfg, struct doca_flow_actions *const *actions, struct doca_flow_actions *const *actions_masks, struct doca_flow_action_descs *const *action_descs, size_t nr_actions)
Set pipe's actions, actions mask and actions descriptor.
DOCA_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_EXPERIMENTAL doca_error_t doca_flow_resource_query_pipe_miss(struct doca_flow_pipe *pipe, struct doca_flow_resource_query *query_stats)
Extract information about pipe miss entry.
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_L3_META_IPV6
Definition: doca_flow.h:298
@ DOCA_FLOW_ACTION_COPY
Definition: doca_flow.h:1012
@ DOCA_FLOW_PUSH_ACTION_VLAN
Definition: doca_flow.h:587
@ DOCA_FLOW_FWD_PORT
Definition: doca_flow.h:744
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_FWD_DROP
Definition: doca_flow.h:748
#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
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
Definition: doca_log.h:496
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
doca_error_t flow_process_entries(struct doca_flow_port *port, struct entries_status *status, uint32_t nr_entries)
Definition: flow_common.c:338
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
action description
Definition: doca_flow.h:1019
enum doca_flow_action_type type
Definition: doca_flow.h:1020
struct doca_flow_action_desc::@108::@110 field_op
action descriptor array
Definition: doca_flow.h:1033
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_push_action push
Definition: doca_flow.h:717
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
struct doca_flow_header_ip4 ip4
Definition: doca_flow.h:449
enum doca_flow_l3_type l3_type
Definition: doca_flow.h:446
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
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
struct doca_flow_push_vlan_action vlan
Definition: doca_flow.h:597
enum doca_flow_push_action_type type
Definition: doca_flow.h:594
struct doca_flow_header_eth_vlan vlan_hdr
Definition: doca_flow.h:579
flow resource query
Definition: doca_flow.h:1101
struct doca_flow_resource_query::@115::@117 counter
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