NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_ipv6_flow_label_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 <stdint.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include "doca_types.h"
31 #include <doca_log.h>
32 #include <doca_bitfield.h>
33 
34 #include "doca_flow.h"
35 #include "doca_flow_net.h"
36 
37 #include "flow_common.h"
38 
39 DOCA_LOG_REGISTER(FLOW_IPV6_FLOW_LABEL);
40 
41 /* The number of seconds app waits for traffic to come */
42 #define WAITING_TIME 10
43 #define NB_INGRESS_PIPE_ENTRIES (4)
44 #define NB_MODIFY_PIPE_ENTRIES (2)
45 #define NB_ENCAP_PIPE_ENTRIES (2)
46 #define NB_EGRESS_PIPE_ENTRIES (NB_MODIFY_PIPE_ENTRIES + NB_ENCAP_PIPE_ENTRIES)
47 #define TOTAL_ENTRIES (NB_INGRESS_PIPE_ENTRIES + NB_EGRESS_PIPE_ENTRIES)
48 /*
49  * Create DOCA Flow ingress pipe with transport layer match and set pkt meta value.
50  *
51  * @port [in]: port of the pipe.
52  * @port_id [in]: port ID of the pipe.
53  * @status [in]: user context for adding entries.
54  * @nb_entries [out]: pointer to put into number of entries.
55  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
56  */
57 static doca_error_t create_ingress_pipe(struct doca_flow_port *port,
58  int port_id,
59  struct entries_status *status,
60  uint32_t *nb_entries)
61 {
62  struct doca_flow_pipe *pipe;
63  struct doca_flow_pipe_entry *entry;
64  struct doca_flow_match match;
65  struct doca_flow_actions actions, *actions_arr[NB_ACTIONS_ARR];
66  struct doca_flow_fwd fwd;
67  struct doca_flow_pipe_cfg *pipe_cfg;
68  enum doca_flow_flags_type flags;
70 
71  memset(&match, 0, sizeof(match));
72  memset(&actions, 0, sizeof(actions));
73  memset(&fwd, 0, sizeof(fwd));
74 
75  /* Transport layer match */
76  match.parser_meta.outer_l4_type = 0xffffffff;
78  match.outer.transport.src_port = 0xffff;
79  match.outer.transport.dst_port = rte_cpu_to_be_16(80);
80 
81  /* Set meta data to match on the egress domain */
82  actions.meta.pkt_meta = UINT32_MAX;
83  actions_arr[0] = &actions;
84 
85  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
86  if (result != DOCA_SUCCESS) {
87  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
88  return result;
89  }
90 
91  result = set_flow_pipe_cfg(pipe_cfg, "MATCH_PIPE", DOCA_FLOW_PIPE_BASIC, true);
92  if (result != DOCA_SUCCESS) {
93  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
94  goto destroy_pipe_cfg;
95  }
97  if (result != DOCA_SUCCESS) {
98  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
99  goto destroy_pipe_cfg;
100  }
102  if (result != DOCA_SUCCESS) {
103  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
104  goto destroy_pipe_cfg;
105  }
106  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
107  if (result != DOCA_SUCCESS) {
108  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
109  goto destroy_pipe_cfg;
110  }
111  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTIONS_ARR);
112  if (result != DOCA_SUCCESS) {
113  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
114  goto destroy_pipe_cfg;
115  }
116 
117  /* Forwarding traffic to other port */
119  fwd.port_id = port_id ^ 1;
120 
121  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &pipe);
122  if (result != DOCA_SUCCESS) {
123  DOCA_LOG_ERR("Failed to create ingress selector pipe: %s", doca_error_get_descr(result));
124  goto destroy_pipe_cfg;
125  }
126  doca_flow_pipe_cfg_destroy(pipe_cfg);
127 
129  match.outer.transport.src_port = rte_cpu_to_be_16(1234);
131  flags = DOCA_FLOW_WAIT_FOR_BATCH;
132  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, flags, status, &entry);
133  if (result != DOCA_SUCCESS) {
134  DOCA_LOG_ERR("Failed to add TCP entry with source port 1234: %s", doca_error_get_descr(result));
135  return result;
136  }
137 
139  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, flags, status, &entry);
140  if (result != DOCA_SUCCESS) {
141  DOCA_LOG_ERR("Failed to add UDP entry with source port 1234: %s", doca_error_get_descr(result));
142  return result;
143  }
144 
146  match.outer.transport.src_port = rte_cpu_to_be_16(5678);
148  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, flags, status, &entry);
149  if (result != DOCA_SUCCESS) {
150  DOCA_LOG_ERR("Failed to add TCP entry with source port 5678: %s", doca_error_get_descr(result));
151  return result;
152  }
153 
155  flags = DOCA_FLOW_NO_WAIT;
156  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, flags, status, &entry);
157  if (result != DOCA_SUCCESS) {
158  DOCA_LOG_ERR("Failed to add UDP entry with source port 5678: %s", doca_error_get_descr(result));
159  return result;
160  }
161 
162  *nb_entries = 4;
163  return DOCA_SUCCESS;
164 
166  doca_flow_pipe_cfg_destroy(pipe_cfg);
167  return result;
168 }
169 
170 /*
171  * Add DOCA Flow pipe entries with example encap values.
172  *
173  * @pipe [in]: pipe of the entry
174  * @status [in]: user context for adding entry
175  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
176  */
177 static doca_error_t add_encap_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
178 {
179  struct doca_flow_match match;
180  struct doca_flow_actions actions;
181  struct doca_flow_pipe_entry *entry;
183 
184  uint8_t mac1[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
185  uint8_t mac2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
186  doca_be32_t ipv6_1[] = {htobe32(0x11115555), htobe32(0x22226666), htobe32(0x33337777), htobe32(0x44448888)};
187  doca_be32_t ipv6_2[] = {htobe32(0xaaaaeeee), htobe32(0xbbbbffff), htobe32(0xcccc0000), htobe32(0xdddd9999)};
188 
189  memset(&match, 0, sizeof(match));
190  memset(&actions, 0, sizeof(actions));
191 
192  match.meta.pkt_meta = DOCA_HTOBE32(1);
193  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, mac1[0], mac1[1], mac1[2], mac1[3], mac1[4], mac1[5]);
194  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, mac2[0], mac2[1], mac2[2], mac2[3], mac2[4], mac2[5]);
195  SET_IPV6_ADDR(actions.encap_cfg.encap.outer.ip6.src_ip, ipv6_1[0], ipv6_1[1], ipv6_1[2], ipv6_1[3]);
196  SET_IPV6_ADDR(actions.encap_cfg.encap.outer.ip6.dst_ip, ipv6_2[0], ipv6_2[1], ipv6_2[2], ipv6_2[3]);
197 
199  if (result != DOCA_SUCCESS) {
200  DOCA_LOG_ERR("Failed to encode MPLS first label for first entry: %s", doca_error_get_descr(result));
201  return result;
202  }
203 
205  if (result != DOCA_SUCCESS) {
206  DOCA_LOG_ERR("Failed to encode MPLS second label for first entry: %s", doca_error_get_descr(result));
207  return result;
208  }
209 
211  if (result != DOCA_SUCCESS) {
212  DOCA_LOG_ERR("Failed to encode MPLS third label for first entry: %s", doca_error_get_descr(result));
213  return result;
214  }
215 
216  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
217  if (result != DOCA_SUCCESS) {
218  DOCA_LOG_ERR("Failed to add entry matching on pkt meta 1: %s", doca_error_get_descr(result));
219  return result;
220  }
221 
222  match.meta.pkt_meta = DOCA_HTOBE32(2);
223  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, mac1[5], mac1[4], mac1[3], mac1[2], mac1[1], mac1[0]);
224  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, mac2[5], mac2[4], mac2[3], mac2[2], mac2[1], mac2[0]);
225  SET_IPV6_ADDR(actions.encap_cfg.encap.outer.ip6.src_ip, ipv6_2[0], ipv6_2[1], ipv6_2[2], ipv6_2[3]);
226  SET_IPV6_ADDR(actions.encap_cfg.encap.outer.ip6.dst_ip, ipv6_1[0], ipv6_1[1], ipv6_1[2], ipv6_1[3]);
227 
229  if (result != DOCA_SUCCESS) {
230  DOCA_LOG_ERR("Failed to encode MPLS first label for second entry: %s", doca_error_get_descr(result));
231  return result;
232  }
233 
235  if (result != DOCA_SUCCESS) {
236  DOCA_LOG_ERR("Failed to encode MPLS second label for second entry: %s", doca_error_get_descr(result));
237  return result;
238  }
239 
241  if (result != DOCA_SUCCESS) {
242  DOCA_LOG_ERR("Failed to encode MPLS third label for second entry: %s", doca_error_get_descr(result));
243  return result;
244  }
245 
246  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
247  if (result != DOCA_SUCCESS) {
248  DOCA_LOG_ERR("Failed to add entry matching on pkt meta 2: %s", doca_error_get_descr(result));
249  return result;
250  }
251 
252  return DOCA_SUCCESS;
253 }
254 
255 /*
256  * Create DOCA Flow pipe on EGRESS domain with match on the packet meta and encap action with changeable values.
257  *
258  * @port [in]: port of the pipe.
259  * @next_pipe [in]: pointer to modify pipe for forwarding to.
260  * @status [in]: user context for adding entries.
261  * @nb_entries [out]: pointer to put into number of entries.
262  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
263  */
264 static doca_error_t create_encap_pipe(struct doca_flow_port *port,
265  struct doca_flow_pipe *next_pipe,
266  struct entries_status *status,
267  uint32_t *nb_entries)
268 {
269  struct doca_flow_pipe *pipe;
270  struct doca_flow_match match;
272  struct doca_flow_actions actions, *actions_arr[NB_ACTIONS_ARR];
273  struct doca_flow_fwd fwd;
274  struct doca_flow_pipe_cfg *pipe_cfg;
276 
277  memset(&match, 0, sizeof(match));
278  memset(&match_mask, 0, sizeof(match_mask));
279  memset(&actions, 0, sizeof(actions));
280  memset(&fwd, 0, sizeof(fwd));
281 
282  /* Match on pkt meta */
283  match_mask.meta.pkt_meta = UINT32_MAX;
284 
285  /* Encap with IPv6 and MPLS tunnel - most fields are changeable */
287  actions.encap_cfg.is_l2 = false;
288  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
289  SET_MAC_ADDR(actions.encap_cfg.encap.outer.eth.dst_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
291  SET_IPV6_ADDR(actions.encap_cfg.encap.outer.ip6.src_ip, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
292  SET_IPV6_ADDR(actions.encap_cfg.encap.outer.ip6.dst_ip, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
298  actions.encap_cfg.encap.tun.mpls[0].label = 0xffffffff;
299  actions.encap_cfg.encap.tun.mpls[1].label = 0xffffffff;
300  actions.encap_cfg.encap.tun.mpls[2].label = 0xffffffff;
301  actions_arr[0] = &actions;
302 
303  /* MPLS is supported as L3 tunnel only */
304 
305  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
306  if (result != DOCA_SUCCESS) {
307  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
308  return result;
309  }
310 
311  result = set_flow_pipe_cfg(pipe_cfg, "ENCAP_PIPE", DOCA_FLOW_PIPE_BASIC, true);
312  if (result != DOCA_SUCCESS) {
313  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
314  goto destroy_pipe_cfg;
315  }
317  if (result != DOCA_SUCCESS) {
318  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
319  goto destroy_pipe_cfg;
320  }
322  if (result != DOCA_SUCCESS) {
323  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
324  goto destroy_pipe_cfg;
325  }
326  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
327  if (result != DOCA_SUCCESS) {
328  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
329  goto destroy_pipe_cfg;
330  }
331  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTIONS_ARR);
332  if (result != DOCA_SUCCESS) {
333  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
334  goto destroy_pipe_cfg;
335  }
336 
337  /* Forwarding traffic to update pipe */
339  fwd.next_pipe = next_pipe;
340 
341  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, &pipe);
342  if (result != DOCA_SUCCESS) {
343  DOCA_LOG_ERR("Failed to create MPLS encap pipe: %s", doca_error_get_descr(result));
344  goto destroy_pipe_cfg;
345  }
346  doca_flow_pipe_cfg_destroy(pipe_cfg);
347 
348  result = add_encap_pipe_entries(pipe, status);
349  if (result != DOCA_SUCCESS) {
350  DOCA_LOG_ERR("Failed to add entries to encap pipe: %s", doca_error_get_descr(result));
351  return result;
352  }
353 
354  *nb_entries = 2;
355  return DOCA_SUCCESS;
356 
358  doca_flow_pipe_cfg_destroy(pipe_cfg);
359  return result;
360 }
361 
362 /*
363  * Fill the descriptor which describes copy to outer IPv6 flow label field.
364  *
365  * @src_str [in]: the source field string.
366  * @src_bit_offset [in]: the source field bit offset.
367  * @desc [out]: the descriptor structure to fill.
368  * @descs [out]: the descriptors array structure contains the above desc.
369  */
370 static void fill_copy_to_outer_ipv6_fl_desc(const char *src_str,
371  uint32_t src_bit_offset,
372  struct doca_flow_action_desc *desc,
373  struct doca_flow_action_descs *descs)
374 {
375  descs->desc_array = desc;
376  descs->nb_action_desc = 1;
377 
378  desc->type = DOCA_FLOW_ACTION_COPY;
379  desc->field_op.src.field_string = src_str;
380  desc->field_op.src.bit_offset = src_bit_offset;
381  desc->field_op.dst.field_string = "outer.ipv6.flow_label";
382  desc->field_op.dst.bit_offset = 0;
383  desc->field_op.width = 20;
384 }
385 
386 /*
387  * Create DOCA Flow pipe on EGRESS domain with match on the inner L3 type and update IPv6 flow label accordingly.
388  *
389  * @port [in]: port of the pipe
390  * @port_id [in]: pipe port ID
391  * @pipe [out]: created pipe pointer
392  * @nb_entries [out]: pointer to put into number of entries.
393  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
394  */
395 static doca_error_t create_modify_pipe(struct doca_flow_port *port,
396  int port_id,
397  struct doca_flow_pipe **pipe,
398  uint32_t *nb_entries)
399 {
400  struct doca_flow_match match;
402  struct doca_flow_action_desc ip4_desc;
403  struct doca_flow_action_desc ip6_desc;
404  struct doca_flow_action_descs ip4_descs;
405  struct doca_flow_action_descs ip6_descs;
406  struct doca_flow_action_descs *descs_arr[2];
407  struct doca_flow_fwd fwd;
408  struct doca_flow_pipe_cfg *pipe_cfg;
410 
411  memset(&match, 0, sizeof(match));
412  memset(&match_mask, 0, sizeof(match_mask));
413  memset(&fwd, 0, sizeof(fwd));
414 
415  /* Match on inner L3 type */
416  match.parser_meta.inner_l3_type = UINT32_MAX;
417  match_mask.parser_meta.inner_l3_type = UINT32_MAX;
418 
419  /*
420  * Update outer IPv6 flow label according to original packet L3 type:
421  * IPv6 - copy flow label inner to outer.
422  * IPv4 - copy from metadata containing a new flow label calculated from this packet.
423  */
424  fill_copy_to_outer_ipv6_fl_desc("meta.data", 0, &ip4_desc, &ip4_descs);
425  fill_copy_to_outer_ipv6_fl_desc("inner.ipv6.flow_label", 0, &ip6_desc, &ip6_descs);
426  descs_arr[0] = &ip4_descs;
427  descs_arr[1] = &ip6_descs;
428 
429  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
430  if (result != DOCA_SUCCESS) {
431  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
432  return result;
433  }
434 
435  result = set_flow_pipe_cfg(pipe_cfg, "UPDATE_IPV6_FL_PIPE", DOCA_FLOW_PIPE_BASIC, false);
436  if (result != DOCA_SUCCESS) {
437  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
438  goto destroy_pipe_cfg;
439  }
441  if (result != DOCA_SUCCESS) {
442  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg domain: %s", doca_error_get_descr(result));
443  goto destroy_pipe_cfg;
444  }
446  if (result != DOCA_SUCCESS) {
447  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg nr_entries: %s", doca_error_get_descr(result));
448  goto destroy_pipe_cfg;
449  }
450  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
451  if (result != DOCA_SUCCESS) {
452  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
453  goto destroy_pipe_cfg;
454  }
455  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, NULL, NULL, descs_arr, 2);
456  if (result != DOCA_SUCCESS) {
457  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
458  goto destroy_pipe_cfg;
459  }
460 
461  *nb_entries = 2;
462 
463  /* Forwarding traffic to the wire */
465  fwd.port_id = port_id;
466 
467  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
469  doca_flow_pipe_cfg_destroy(pipe_cfg);
470  return result;
471 }
472 
473 /*
474  * Add DOCA Flow pipe entries updating outer IPv6
475  *
476  * @pipe [in]: pipe of the entry
477  * @status [in]: user context for adding entry
478  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
479  */
480 static doca_error_t add_modify_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
481 {
482  struct doca_flow_match match;
483  struct doca_flow_actions actions;
484  struct doca_flow_pipe_entry *entry;
486 
487  memset(&match, 0, sizeof(match));
488  memset(&actions, 0, sizeof(actions));
489 
491  actions.action_idx = 0;
492  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
493  if (result != DOCA_SUCCESS) {
494  DOCA_LOG_ERR("Failed to add IPv4 entry to modify pipe: %s", doca_error_get_descr(result));
495  return result;
496  }
497 
499  actions.action_idx = 1;
500  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
501  if (result != DOCA_SUCCESS) {
502  DOCA_LOG_ERR("Failed to add IPv6 entry to modify pipe: %s", doca_error_get_descr(result));
503  return result;
504  }
505 
506  return DOCA_SUCCESS;
507 }
508 
509 /*
510  * Prepare egress domain pipeline.
511  *
512  * @pair_port [in]: pointer to the pair port.
513  * @pair_port_id [in]: the ID of pair port.
514  * @status [in]: user context for adding entries.
515  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
516  */
517 static doca_error_t prepare_egress_pipeline(struct doca_flow_port *pair_port,
518  int pair_port_id,
519  struct entries_status *status)
520 {
521  struct doca_flow_pipe *pipe;
522  uint32_t total_entries = 0;
523  uint32_t nb_pipe_entries;
525 
526  result = create_modify_pipe(pair_port, pair_port_id, &pipe, &nb_pipe_entries);
527  if (result != DOCA_SUCCESS) {
528  DOCA_LOG_ERR("Failed to create outer updating pipe: %s", doca_error_get_descr(result));
529  return result;
530  }
531  total_entries += nb_pipe_entries;
532 
533  memset(status, 0, sizeof(*status));
534 
535  result = add_modify_pipe_entries(pipe, status);
536  if (result != DOCA_SUCCESS) {
537  DOCA_LOG_ERR("Failed to add entries to outer updating pipe: %s", doca_error_get_descr(result));
538  return result;
539  }
540 
541  result = create_encap_pipe(pair_port, pipe, status, &nb_pipe_entries);
542  if (result != DOCA_SUCCESS) {
543  DOCA_LOG_ERR("Failed to create encap pipe with entries: %s", doca_error_get_descr(result));
544  return result;
545  }
546  total_entries += nb_pipe_entries;
547 
548  result = flow_process_entries(pair_port, status, total_entries);
549  if (result != DOCA_SUCCESS) {
550  DOCA_LOG_ERR("Failed to process egress entries: %s", doca_error_get_descr(result));
551  return result;
552  }
553 
554  return DOCA_SUCCESS;
555 }
556 
557 /*
558  * Prepare ingress domain pipeline.
559  *
560  * @port [in]: pointer to port.
561  * @port_id [in]: port ID.
562  * @status [in]: user context for adding entries.
563  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
564  */
565 static doca_error_t prepare_ingress_pipeline(struct doca_flow_port *port, int port_id, struct entries_status *status)
566 {
567  uint32_t num_of_entries;
569 
570  memset(status, 0, sizeof(*status));
571 
572  result = create_ingress_pipe(port, port_id, status, &num_of_entries);
573  if (result != DOCA_SUCCESS) {
574  DOCA_LOG_ERR("Failed to create ingress pipe with entries: %s", 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("Failed to process ingress entries: %s", doca_error_get_descr(result));
581  return result;
582  }
583 
584  return DOCA_SUCCESS;
585 }
586 
587 /*
588  * Run flow_ipv6_flow_label sample.
589  *
590  * @nb_queues [in]: number of queues the sample will use.
591  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
592  */
594 {
595  const int nb_ports = 2;
596  struct flow_resources resource = {0};
597  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
598  struct doca_flow_port *ports[nb_ports];
599  struct doca_dev *dev_arr[nb_ports];
600  uint32_t actions_mem_size[nb_ports];
601  struct entries_status egress_status;
602  struct entries_status ingress_status;
604  int port_id;
605 
606  result = init_doca_flow(nb_queues, "vnf,hws", &resource, nr_shared_resources);
607  if (result != DOCA_SUCCESS) {
608  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
609  return result;
610  }
611 
612  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
615  if (result != DOCA_SUCCESS) {
616  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
618  return result;
619  }
620 
621  for (port_id = 0; port_id < nb_ports; port_id++) {
622  result = prepare_egress_pipeline(ports[port_id ^ 1], port_id ^ 1, &egress_status);
623  if (result != DOCA_SUCCESS) {
624  DOCA_LOG_ERR("Failed to prepare egress pipeline: %s", doca_error_get_descr(result));
627  return result;
628  }
629 
630  result = prepare_ingress_pipeline(ports[port_id], port_id, &ingress_status);
631  if (result != DOCA_SUCCESS) {
632  DOCA_LOG_ERR("Failed to prepare ingress pipeline: %s", doca_error_get_descr(result));
635  return result;
636  }
637  }
638 
639  DOCA_LOG_INFO("Wait %u seconds for packets to arrive", WAITING_TIME);
640  sleep(WAITING_TIME);
641 
644  return result;
645 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
struct doca_flow_port * init_doca_flow(uint16_t port_id, uint8_t rxq_num)
Definition: flow.c:37
#define SET_MAC_ADDR(addr, a, b, c, d, e, f)
Definition: flow_common.h:60
static int nb_entries
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
DOCA_LOG_REGISTER(FLOW_IPV6_FLOW_LABEL)
static doca_error_t prepare_egress_pipeline(struct doca_flow_port *pair_port, int pair_port_id, struct entries_status *status)
static doca_error_t create_ingress_pipe(struct doca_flow_port *port, int port_id, struct entries_status *status, uint32_t *nb_entries)
static doca_error_t add_encap_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
static doca_error_t prepare_ingress_pipeline(struct doca_flow_port *port, int port_id, struct entries_status *status)
doca_error_t flow_ipv6_flow_label(int nb_queues)
#define TOTAL_ENTRIES
static doca_error_t add_modify_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
#define WAITING_TIME
static void fill_copy_to_outer_ipv6_fl_desc(const char *src_str, uint32_t src_bit_offset, struct doca_flow_action_desc *desc, struct doca_flow_action_descs *descs)
static doca_error_t create_modify_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_pipe **pipe, uint32_t *nb_entries)
static doca_error_t create_encap_pipe(struct doca_flow_port *port, struct doca_flow_pipe *next_pipe, struct entries_status *status, uint32_t *nb_entries)
static struct doca_flow_actions actions
Definition: flow_parser.c:107
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)
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_MPLS_DEFAULT_PORT
Definition: doca_flow_net.h:51
@ DOCA_FLOW_L4_TYPE_EXT_UDP
@ DOCA_FLOW_L4_TYPE_EXT_TRANSPORT
@ DOCA_FLOW_L3_TYPE_IP6
@ DOCA_FLOW_TUN_MPLS_O_UDP
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_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
doca_flow_flags_type
doca flow flags type
Definition: doca_flow.h:114
DOCA_EXPERIMENTAL doca_error_t doca_flow_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_mpls_label_encode(uint32_t label, uint8_t traffic_class, uint8_t ttl, bool bottom_of_stack, struct doca_flow_header_mpls *mpls)
Prepare an MPLS label header in big-endian.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_add_entry(uint16_t pipe_queue, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_actions *actions, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a pipe.
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_nr_entries(struct doca_flow_pipe_cfg *cfg, uint32_t nr_entries)
Set pipe's maximum number of flow rules.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_domain(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_domain domain)
Set pipe's domain.
@ DOCA_FLOW_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_NO_WAIT
Definition: doca_flow.h:115
@ DOCA_FLOW_WAIT_FOR_BATCH
Definition: doca_flow.h:117
@ DOCA_FLOW_ACTION_COPY
Definition: doca_flow.h:1012
@ 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_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
@ DOCA_FLOW_PIPE_DOMAIN_DEFAULT
Definition: doca_flow.h:241
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
uint32_t doca_be32_t
Definition: doca_types.h:121
#define htobe32
Definition: os_utils.hpp:40
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 NB_ACTIONS_ARR
Definition: flow_common.h:58
#define SHARED_RESOURCE_NUM_VALUES
Definition: flow_common.h:59
#define ACTIONS_MEM_SIZE(nr_queues, entries)
Definition: flow_common.h:66
#define SET_IPV6_ADDR(addr, a, b, c, d)
Definition: flow_common.h:40
#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
struct doca_flow_action_desc * desc_array
Definition: doca_flow.h:1036
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_resource_encap_cfg encap_cfg
Definition: doca_flow.h:710
enum doca_flow_resource_type encap_type
Definition: doca_flow.h:707
struct doca_flow_meta meta
Definition: doca_flow.h:699
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
uint8_t dst_mac[DOCA_FLOW_ETHER_ADDR_LEN]
uint8_t src_mac[DOCA_FLOW_ETHER_ADDR_LEN]
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_l4_port transport
Definition: doca_flow.h:463
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_ip6 ip6
Definition: doca_flow.h:451
doca_be32_t dst_ip[4]
doca_be32_t src_ip[4]
struct doca_flow_header_l4_port l4_port
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
struct doca_flow_header_format outer
Definition: doca_flow.h:498
struct doca_flow_meta meta
Definition: doca_flow.h:494
doca_be32_t pkt_meta
Definition: doca_flow.h:359
enum doca_flow_l3_meta inner_l3_type
Definition: doca_flow.h:385
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
struct doca_flow_encap_action encap
Definition: doca_flow.h:663
enum doca_flow_tun_type type
struct doca_flow_header_mpls mpls[DOCA_FLOW_MPLS_LABELS_MAX]
user context struct that will be used in entries process callback
Definition: flow_common.h:78
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