NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_parser_meta_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <string.h>
27 #include <unistd.h>
28 
29 #include <doca_log.h>
30 #include <doca_flow.h>
31 
32 #include "flow_common.h"
33 
34 DOCA_LOG_REGISTER(FLOW_PARSER_META);
35 
36 /*
37  * Create DOCA Flow pipe with changeable match on parser meta type
38  *
39  * @port [in]: port of the pipe
40  * @port_id [in]: port ID of the pipe
41  * @pipe [out]: created pipe pointer
42  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
43  */
44 static doca_error_t create_match_parser_meta_type_pipe(struct doca_flow_port *port,
45  int port_id,
46  struct doca_flow_pipe **pipe)
47 {
48  struct doca_flow_match match;
50  struct doca_flow_fwd fwd;
51  struct doca_flow_pipe_cfg *pipe_cfg;
53 
54  memset(&match_mask, 0, sizeof(match_mask));
55  memset(&match, 0, sizeof(match));
56  memset(&fwd, 0, sizeof(fwd));
57 
58  /* set match_mask value */
61  match.parser_meta.inner_l4_type = UINT32_MAX;
62  match.parser_meta.outer_l3_type = UINT32_MAX;
63 
64  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
65  if (result != DOCA_SUCCESS) {
66  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
67  return result;
68  }
69 
70  result = set_flow_pipe_cfg(pipe_cfg, "MATCH_PARSER_META_TYPE_PIPE", DOCA_FLOW_PIPE_BASIC, false);
71  if (result != DOCA_SUCCESS) {
72  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
73  goto destroy_pipe_cfg;
74  }
75  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
76  if (result != DOCA_SUCCESS) {
77  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
78  goto destroy_pipe_cfg;
79  }
80 
81  /* forwarding traffic to other port */
83  fwd.port_id = port_id ^ 1;
84 
85  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
88  return result;
89 }
90 
91 /*
92  * Add DOCA Flow pipe entry with example of parser meta type value to match
93  *
94  * @pipe [in]: pipe of the entry
95  * @status [in]: user context for adding entry
96  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
97  */
98 static doca_error_t add_match_parser_meta_type_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
99 {
100  struct doca_flow_match match;
101  struct doca_flow_pipe_entry *entry;
103 
104  memset(&match, 0, sizeof(match));
105 
106  /* set match value */
109  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
110  if (result != DOCA_SUCCESS)
111  return result;
112 
113  /* set match value */
116  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
117  if (result != DOCA_SUCCESS)
118  return result;
119 
120  return DOCA_SUCCESS;
121 }
122 
123 /*
124  * Create DOCA Flow pipe with changeable match on parser meta ok
125  *
126  * @port [in]: port of the pipe
127  * @type_pipe [in]: next pipe
128  * @pipe [out]: created pipe pointer
129  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
130  */
131 static doca_error_t create_match_parser_meta_ok_pipe(struct doca_flow_port *port,
132  struct doca_flow_pipe *type_pipe,
133  struct doca_flow_pipe **pipe)
134 {
135  struct doca_flow_match match;
137  struct doca_flow_fwd fwd;
138  struct doca_flow_pipe_cfg *pipe_cfg;
140 
141  memset(&match, 0, sizeof(match));
142  memset(&match_mask, 0, sizeof(match_mask));
143  memset(&fwd, 0, sizeof(fwd));
144 
145  /* set match_mask value */
146  match_mask.parser_meta.inner_l3_ok = UINT8_MAX;
147  match.parser_meta.inner_l3_ok = UINT8_MAX;
149  match.parser_meta.outer_ip4_checksum_ok = UINT8_MAX;
150 
151  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
152  if (result != DOCA_SUCCESS) {
153  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
154  return result;
155  }
156 
157  result = set_flow_pipe_cfg(pipe_cfg, "MATCH_PARSER_META_OK_PIPE", DOCA_FLOW_PIPE_BASIC, false);
158  if (result != DOCA_SUCCESS) {
159  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
160  goto destroy_pipe_cfg;
161  }
162  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
163  if (result != DOCA_SUCCESS) {
164  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
165  goto destroy_pipe_cfg;
166  }
167 
168  /* forwarding traffic to other port */
170  fwd.next_pipe = type_pipe;
171 
172  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
174  doca_flow_pipe_cfg_destroy(pipe_cfg);
175  return result;
176 }
177 
178 /*
179  * Add DOCA Flow pipe entry with example of parser meta data integrity to match
180  *
181  * @pipe [in]: pipe of the entry
182  * @status [in]: user context for adding entry
183  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
184  */
185 static doca_error_t add_match_parser_meta_ok_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
186 {
187  struct doca_flow_match match;
188  struct doca_flow_pipe_entry *entry;
190 
191  memset(&match, 0, sizeof(match));
192 
193  /* set match value */
194  match.parser_meta.inner_l3_ok = 1;
196  result = doca_flow_pipe_add_entry(0, pipe, &match, NULL, NULL, NULL, 0, status, &entry);
197  if (result != DOCA_SUCCESS)
198  return result;
199 
200  return DOCA_SUCCESS;
201 }
202 
203 /*
204  * Create DOCA Flow control pipe
205  *
206  * @port [in]: port of the pipe
207  * @pipe [out]: created pipe pointer
208  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
209  */
210 static doca_error_t create_fragmented_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
211 {
212  struct doca_flow_pipe_cfg *pipe_cfg;
214 
215  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
216  if (result != DOCA_SUCCESS) {
217  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
218  return result;
219  }
220 
221  result = set_flow_pipe_cfg(pipe_cfg, "MATCH_PARSER_META_FRAGMENTED_PIPE", DOCA_FLOW_PIPE_CONTROL, true);
222  if (result != DOCA_SUCCESS) {
223  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
224  goto destroy_pipe_cfg;
225  }
226 
227  result = doca_flow_pipe_create(pipe_cfg, NULL, NULL, pipe);
229  doca_flow_pipe_cfg_destroy(pipe_cfg);
230  return result;
231 }
232 
233 /*
234  * Add DOCA Flow pipe entries to the control pipe:
235  * - entry with outer IP non fragmented match that forward the matched packet to ok_pipe
236  * - entry with outer IP fragmented match that forward to pair port
237  *
238  * @frag_pipe [in]: pipe of the entry
239  * @ok_pipe [in]: pipe to forward non fragmented traffic
240  * @port_id [in]: port ID of the pipe
241  * @status [in]: user context for adding entry
242  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
243  */
244 static doca_error_t add_fragmented_pipe_entries(struct doca_flow_pipe *frag_pipe,
245  struct doca_flow_pipe *ok_pipe,
246  int port_id,
247  struct entries_status *status)
248 {
249  struct doca_flow_match match;
251  struct doca_flow_fwd fwd;
252  uint8_t priority = 0;
254 
255  memset(&match, 0, sizeof(match));
256  memset(&match_mask, 0, sizeof(match_mask));
257  memset(&fwd, 0, sizeof(fwd));
258 
262  fwd.next_pipe = ok_pipe;
263 
265  priority,
266  frag_pipe,
267  &match,
268  &match_mask,
269  NULL,
270  NULL,
271  NULL,
272  NULL,
273  NULL,
274  &fwd,
275  status,
276  NULL);
277  if (result != DOCA_SUCCESS) {
278  DOCA_LOG_ERR("Failed to add control pipe entry: %s", doca_error_get_descr(result));
279  return result;
280  }
281 
282  memset(&match, 0, sizeof(match));
283  memset(&match_mask, 0, sizeof(match_mask));
284  memset(&fwd, 0, sizeof(fwd));
285 
289  fwd.port_id = port_id ^ 1;
290 
292  priority,
293  frag_pipe,
294  &match,
295  &match_mask,
296  NULL,
297  NULL,
298  NULL,
299  NULL,
300  NULL,
301  &fwd,
302  status,
303  NULL);
304  if (result != DOCA_SUCCESS) {
305  DOCA_LOG_ERR("Failed to add control pipe entry: %s", doca_error_get_descr(result));
306  return result;
307  }
308 
309  return DOCA_SUCCESS;
310 }
311 
312 /*
313  * Run flow_parser_meta sample
314  *
315  * @nb_queues [in]: number of queues the sample will use
316  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
317  */
319 {
320  const int nb_ports = 2;
321  struct flow_resources resource = {0};
322  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
323  struct doca_flow_port *ports[nb_ports];
324  struct doca_dev *dev_arr[nb_ports];
325  uint32_t actions_mem_size[nb_ports];
326  struct doca_flow_pipe *type_pipe, *ok_pipe, *frag_pipe;
327  struct entries_status status;
328  int num_of_entries = 5;
330  int port_id;
331 
332  result = init_doca_flow(nb_queues, "vnf,hws", &resource, nr_shared_resources);
333  if (result != DOCA_SUCCESS) {
334  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
335  return result;
336  }
337 
338  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
339  ARRAY_INIT(actions_mem_size, ACTIONS_MEM_SIZE(nb_queues, num_of_entries));
341  if (result != DOCA_SUCCESS) {
342  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
344  return result;
345  }
346 
347  for (port_id = 0; port_id < nb_ports; port_id++) {
348  memset(&status, 0, sizeof(status));
349 
350  result = create_match_parser_meta_type_pipe(ports[port_id], port_id, &type_pipe);
351  if (result != DOCA_SUCCESS) {
352  DOCA_LOG_ERR("Failed to create type pipe: %s", doca_error_get_descr(result));
355  return result;
356  }
357 
358  result = add_match_parser_meta_type_pipe_entries(type_pipe, &status);
359  if (result != DOCA_SUCCESS) {
360  DOCA_LOG_ERR("Failed to add type entry: %s", doca_error_get_descr(result));
363  return result;
364  }
365 
366  result = create_match_parser_meta_ok_pipe(ports[port_id], type_pipe, &ok_pipe);
367  if (result != DOCA_SUCCESS) {
368  DOCA_LOG_ERR("Failed to create ok pipe: %s", doca_error_get_descr(result));
371  return result;
372  }
373 
374  result = add_match_parser_meta_ok_pipe_entry(ok_pipe, &status);
375  if (result != DOCA_SUCCESS) {
376  DOCA_LOG_ERR("Failed to add ok entry: %s", doca_error_get_descr(result));
379  return result;
380  }
381 
382  result = create_fragmented_pipe(ports[port_id], &frag_pipe);
383  if (result != DOCA_SUCCESS) {
384  DOCA_LOG_ERR("Failed to create fragmented pipe: %s", doca_error_get_descr(result));
387  return result;
388  }
389 
390  result = add_fragmented_pipe_entries(frag_pipe, ok_pipe, port_id, &status);
391  if (result != DOCA_SUCCESS) {
392  DOCA_LOG_ERR("Failed to add fragmented entries: %s", doca_error_get_descr(result));
395  return result;
396  }
397 
398  result = doca_flow_entries_process(ports[port_id], 0, DEFAULT_TIMEOUT_US, num_of_entries);
399  if (result != DOCA_SUCCESS) {
400  DOCA_LOG_ERR("Failed to process entries: %s", doca_error_get_descr(result));
403  return result;
404  }
405 
406  if (status.nb_processed != num_of_entries || status.failure) {
407  DOCA_LOG_ERR("Failed to process entries");
410  return DOCA_ERROR_BAD_STATE;
411  }
412  }
413 
414  DOCA_LOG_INFO("Wait few seconds for packets to arrive");
415  sleep(5);
416 
419  return result;
420 }
#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 destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_match match_mask
Definition: flow_parser.c:106
static doca_error_t create_match_parser_meta_ok_pipe(struct doca_flow_port *port, struct doca_flow_pipe *type_pipe, struct doca_flow_pipe **pipe)
static doca_error_t add_match_parser_meta_ok_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
static doca_error_t add_fragmented_pipe_entries(struct doca_flow_pipe *frag_pipe, struct doca_flow_pipe *ok_pipe, int port_id, struct entries_status *status)
static doca_error_t create_match_parser_meta_type_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_pipe **pipe)
static doca_error_t add_match_parser_meta_type_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
static doca_error_t create_fragmented_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
DOCA_LOG_REGISTER(FLOW_PARSER_META)
doca_error_t flow_parser_meta(int nb_queues)
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
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_STABLE doca_error_t doca_flow_pipe_cfg_destroy(struct doca_flow_pipe_cfg *cfg)
Destroy DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_create(struct doca_flow_pipe_cfg **cfg, struct doca_flow_port *port)
Create DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
DOCA_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_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_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_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_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
#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
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
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
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
uint8_t outer_ip4_checksum_ok
Definition: doca_flow.h:390
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l4_meta inner_l4_type
Definition: doca_flow.h:386
uint8_t outer_ip_fragmented
Definition: doca_flow.h:387
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