NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_tcp_seq_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2025 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_bitfield.h>
30 #include <doca_log.h>
31 #include <doca_flow.h>
32 
33 #include "flow_common.h"
34 
35 /* Number of action descriptors */
36 #define NB_ACTION_DESC (1)
37 /* The number of seconds app waits for traffic to come */
38 #define WAITING_TIME (5)
39 
40 DOCA_LOG_REGISTER(FLOW_TCP_SEQ);
41 
50 static doca_error_t create_root_pipe(struct doca_flow_port *port,
51  struct doca_flow_pipe *next_pipe,
52  struct doca_flow_pipe **pipe)
53 {
54  struct doca_flow_match match = {0};
55  struct doca_flow_fwd fwd = {0};
56  struct doca_flow_pipe_cfg *pipe_cfg;
58 
61 
62  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
63  if (result != DOCA_SUCCESS) {
64  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
65  return result;
66  }
67 
68  result = set_flow_pipe_cfg(pipe_cfg, "TCP_SEQ_ROOT", DOCA_FLOW_PIPE_BASIC, true);
69  if (result != DOCA_SUCCESS) {
70  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
71  goto destroy_pipe_cfg;
72  }
73  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
74  if (result != DOCA_SUCCESS) {
75  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
76  goto destroy_pipe_cfg;
77  }
78 
80  fwd.next_pipe = next_pipe;
81 
82  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
83 
86  return result;
87 }
88 
96 static doca_error_t create_comparison_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
97 {
98  struct doca_flow_pipe_cfg *pipe_cfg;
100 
101  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
102  if (result != DOCA_SUCCESS) {
103  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
104  return result;
105  }
106 
107  result = set_flow_pipe_cfg(pipe_cfg, "TCP_SEQ_COMPARE", DOCA_FLOW_PIPE_CONTROL, false);
108  if (result != DOCA_SUCCESS) {
109  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
110  goto destroy_pipe_cfg;
111  }
112 
113  result = doca_flow_pipe_create(pipe_cfg, NULL, NULL, pipe);
114 
116  doca_flow_pipe_cfg_destroy(pipe_cfg);
117  return result;
118 }
119 
129 static doca_error_t add_comparison_pipe_entry(struct doca_flow_pipe *pipe,
130  struct doca_flow_pipe *next_pipe,
131  struct entries_status *status)
132 {
133  struct doca_flow_match match;
134  struct doca_flow_match_condition condition;
135  struct doca_flow_fwd fwd;
136 
137  condition.operation = DOCA_FLOW_COMPARE_LT;
138  condition.field_op.a.field_string = "outer.tcp.seq_num";
139  condition.field_op.a.bit_offset = 0;
140  condition.field_op.b.field_string = NULL;
141  condition.field_op.b.bit_offset = 0;
142  condition.field_op.width = 32;
143 
144  match.outer.tcp.seq_num = DOCA_HTOBE32(10);
145 
148 
149  return doca_flow_pipe_control_add_entry(0 /* queue */,
150  0 /* priority */,
151  pipe,
152  &match,
153  NULL /* match_mask */,
154  &condition,
155  NULL,
156  NULL,
157  NULL,
158  NULL,
159  &fwd,
160  status,
161  NULL);
162 }
163 
174 static doca_error_t create_action_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_pipe **pipe)
175 {
176  struct doca_flow_match match = {0};
177  struct doca_flow_actions actions = {0}, *actions_arr[NB_ACTIONS_ARR];
178  struct doca_flow_fwd fwd = {0};
179  struct doca_flow_pipe_cfg *pipe_cfg;
180  struct doca_flow_action_descs descs = {0}, *descs_arr[NB_ACTIONS_ARR];
181  struct doca_flow_action_desc desc_array[NB_ACTION_DESC] = {0};
183 
186 
187  actions_arr[0] = &actions;
188  descs_arr[0] = &descs;
190  descs.desc_array = desc_array;
191 
192  desc_array[0].type = DOCA_FLOW_ACTION_ADD;
193  desc_array[0].field_op.dst.field_string = "outer.tcp.ack_num";
194  desc_array[0].field_op.dst.bit_offset = 0;
195  desc_array[0].field_op.width = 32;
196 
198 
199  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
200  if (result != DOCA_SUCCESS) {
201  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
202  return result;
203  }
204 
205  result = set_flow_pipe_cfg(pipe_cfg, "TCP_SEQ_ACTION", DOCA_FLOW_PIPE_BASIC, false);
206  if (result != DOCA_SUCCESS) {
207  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
208  goto destroy_pipe_cfg;
209  }
210  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
211  if (result != DOCA_SUCCESS) {
212  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
213  goto destroy_pipe_cfg;
214  }
215  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, descs_arr, NB_ACTIONS_ARR);
216  if (result != DOCA_SUCCESS) {
217  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
218  goto destroy_pipe_cfg;
219  }
220 
221  /* forwarding traffic to other port */
223  fwd.port_id = port_id ^ 1;
224 
225  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
226 
228  doca_flow_pipe_cfg_destroy(pipe_cfg);
229  return result;
230 }
231 
232 /*
233  * Run flow_tcp_seq sample
234  *
235  * @nb_queues [in]: number of queues the sample will use
236  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
237  */
239 {
240  int nb_ports = 2;
241  struct flow_resources resource = {0};
242  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
243  struct doca_flow_port *ports[nb_ports];
244  struct doca_dev *dev_arr[nb_ports];
245  uint32_t actions_mem_size[nb_ports];
246  struct doca_flow_pipe *root_pipe, *action_pipe, *comparison_pipe;
247  uint32_t num_of_entries = 3;
249  int port_id;
250 
251  result = init_doca_flow(nb_queues, "vnf,hws", &resource, nr_shared_resources);
252  if (result != DOCA_SUCCESS) {
253  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
254  return result;
255  }
256 
257  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
258  ARRAY_INIT(actions_mem_size, ACTIONS_MEM_SIZE(nb_queues, num_of_entries));
260  if (result != DOCA_SUCCESS) {
261  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
263  return result;
264  }
265 
266  for (port_id = 0; port_id < nb_ports; port_id++) {
267  struct entries_status status = {0};
268 
269  result = create_action_pipe(ports[port_id], port_id, &action_pipe);
270  if (result != DOCA_SUCCESS) {
271  DOCA_LOG_ERR("Failed to create action pipe: %s", doca_error_get_descr(result));
274  return result;
275  }
276 
277  result = doca_flow_pipe_add_entry(0, action_pipe, NULL, NULL, NULL, NULL, 0, &status, NULL);
278  if (result != DOCA_SUCCESS) {
279  DOCA_LOG_ERR("Failed to add action pipe entry: %s", doca_error_get_descr(result));
282  return result;
283  }
284 
285  result = create_comparison_pipe(ports[port_id], &comparison_pipe);
286  if (result != DOCA_SUCCESS) {
287  DOCA_LOG_ERR("Failed to create comparison pipe: %s", doca_error_get_descr(result));
290  return result;
291  }
292 
293  result = add_comparison_pipe_entry(comparison_pipe, action_pipe, &status);
294  if (result != DOCA_SUCCESS) {
295  DOCA_LOG_ERR("Failed to add comparison pipe entry: %s", doca_error_get_descr(result));
298  return result;
299  }
300 
301  result = create_root_pipe(ports[port_id], comparison_pipe, &root_pipe);
302  if (result != DOCA_SUCCESS) {
303  DOCA_LOG_ERR("Failed to create root pipe: %s", doca_error_get_descr(result));
306  return result;
307  }
308 
309  result = doca_flow_pipe_add_entry(0, root_pipe, NULL, NULL, NULL, NULL, 0, &status, NULL);
310  if (result != DOCA_SUCCESS) {
311  DOCA_LOG_ERR("Failed to add root pipeentry: %s", doca_error_get_descr(result));
314  return result;
315  }
316 
317  result = flow_process_entries(ports[port_id], &status, num_of_entries);
318  if (result != DOCA_SUCCESS) {
319  DOCA_LOG_ERR("Failed to process entries: %s", doca_error_get_descr(result));
322  return result;
323  }
324  }
325 
326  DOCA_LOG_INFO("Wait %u seconds for packets to arrive", WAITING_TIME);
327  sleep(WAITING_TIME);
328 
331  return result;
332 }
#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_actions actions
Definition: flow_parser.c:107
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static doca_error_t add_comparison_pipe_entry(struct doca_flow_pipe *pipe, struct doca_flow_pipe *next_pipe, struct entries_status *status)
doca_error_t flow_tcp_seq(int nb_queues)
DOCA_LOG_REGISTER(FLOW_TCP_SEQ)
static doca_error_t create_action_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_pipe **pipe)
static doca_error_t create_root_pipe(struct doca_flow_port *port, struct doca_flow_pipe *next_pipe, struct doca_flow_pipe **pipe)
#define WAITING_TIME
static doca_error_t create_comparison_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
#define NB_ACTION_DESC
#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
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_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_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_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_ACTION_ADD
Definition: doca_flow.h:1010
@ DOCA_FLOW_COMPARE_LT
Definition: doca_flow.h:514
@ DOCA_FLOW_FWD_PORT
Definition: doca_flow.h:744
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ 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 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 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_header_format outer
Definition: doca_flow.h:703
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_tcp tcp
Definition: doca_flow.h:461
doca flow match condition information
Definition: doca_flow.h:548
enum doca_flow_compare_op operation
Definition: doca_flow.h:549
struct doca_flow_match_condition::@68::@70 field_op
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
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
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