NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 #include <string.h>
26 
27 #include <rte_byteorder.h>
28 
29 #include <doca_log.h>
30 
31 #include "flow_common.h"
32 
33 DOCA_LOG_REGISTER(flow_common);
34 
35 /*
36  * Entry processing callback
37  *
38  * @entry [in]: DOCA Flow entry pointer
39  * @pipe_queue [in]: queue identifier
40  * @status [in]: DOCA Flow entry status
41  * @op [in]: DOCA Flow entry operation
42  * @user_ctx [out]: user context
43  */
44 void check_for_valid_entry(struct doca_flow_pipe_entry *entry,
45  uint16_t pipe_queue,
46  enum doca_flow_entry_status status,
47  enum doca_flow_entry_op op,
48  void *user_ctx)
49 {
50  (void)entry;
51  (void)op;
52  (void)pipe_queue;
53  struct entries_status *entry_status = (struct entries_status *)user_ctx;
54 
55  if (entry_status == NULL)
56  return;
57  if (status != DOCA_FLOW_ENTRY_STATUS_SUCCESS)
58  entry_status->failure = true; /* set failure to true if processing failed */
59  entry_status->nb_processed++;
60 }
61 
63  const char *mode,
64  struct flow_resources *resource,
65  uint32_t nr_shared_resources[])
66 {
67  return init_doca_flow_cb(nb_queues, mode, resource, nr_shared_resources, check_for_valid_entry, NULL, NULL);
68 }
69 
71  const char *mode,
72  struct flow_resources *resource,
73  uint32_t nr_shared_resources[],
74  struct doca_flow_definitions *defs)
75 {
76  return init_doca_flow_cb(nb_queues, mode, resource, nr_shared_resources, check_for_valid_entry, NULL, defs);
77 }
78 
80  const char *mode,
81  struct flow_resources *resource,
82  uint32_t nr_shared_resources[],
85  struct doca_flow_definitions *defs)
86 {
87  struct doca_flow_cfg *flow_cfg;
88  uint16_t qidx, rss_queues[nb_queues];
89  struct doca_flow_resource_rss_cfg rss = {0};
90  doca_error_t result, tmp_result;
91 
92  result = doca_flow_cfg_create(&flow_cfg);
93  if (result != DOCA_SUCCESS) {
94  DOCA_LOG_ERR("Failed to create doca_flow_cfg: %s", doca_error_get_descr(result));
95  return result;
96  }
97 
98  rss.nr_queues = nb_queues;
99  for (qidx = 0; qidx < nb_queues; qidx++)
100  rss_queues[qidx] = qidx;
101  rss.queues_array = rss_queues;
102  result = doca_flow_cfg_set_default_rss(flow_cfg, &rss);
103  if (result != DOCA_SUCCESS) {
104  DOCA_LOG_ERR("Failed to set doca_flow_cfg rss: %s", doca_error_get_descr(result));
105  goto destroy_cfg;
106  }
107 
108  result = doca_flow_cfg_set_pipe_queues(flow_cfg, nb_queues);
109  if (result != DOCA_SUCCESS) {
110  DOCA_LOG_ERR("Failed to set doca_flow_cfg pipe_queues: %s", doca_error_get_descr(result));
111  goto destroy_cfg;
112  }
113 
114  result = doca_flow_cfg_set_mode_args(flow_cfg, mode);
115  if (result != DOCA_SUCCESS) {
116  DOCA_LOG_ERR("Failed to set doca_flow_cfg mode_args: %s", doca_error_get_descr(result));
117  goto destroy_cfg;
118  }
119 
120  result = doca_flow_cfg_set_nr_counters(flow_cfg, resource->nr_counters);
121  if (result != DOCA_SUCCESS) {
122  DOCA_LOG_ERR("Failed to set doca_flow_cfg nr_counters: %s", doca_error_get_descr(result));
123  goto destroy_cfg;
124  }
125 
126  result = doca_flow_cfg_set_nr_meters(flow_cfg, resource->nr_meters);
127  if (result != DOCA_SUCCESS) {
128  DOCA_LOG_ERR("Failed to set doca_flow_cfg nr_meters: %s", doca_error_get_descr(result));
129  goto destroy_cfg;
130  }
131 
133  if (result != DOCA_SUCCESS) {
134  DOCA_LOG_ERR("Failed to set doca_flow_cfg doca_flow_entry_process_cb: %s",
136  goto destroy_cfg;
137  }
138 
140  if (result != DOCA_SUCCESS) {
141  DOCA_LOG_ERR("Failed to set doca_flow_cfg pipe_process_cb: %s", doca_error_get_descr(result));
142  goto destroy_cfg;
143  }
144 
145  for (int i = 0; i < SHARED_RESOURCE_NUM_VALUES; i++) {
146  result = doca_flow_cfg_set_nr_shared_resource(flow_cfg, nr_shared_resources[i], i);
147  if (result != DOCA_SUCCESS) {
148  DOCA_LOG_ERR("Failed to set doca_flow_cfg nr_shared_resources: %s",
150  goto destroy_cfg;
151  }
152  }
153 
154  if (defs) {
155  result = doca_flow_cfg_set_definitions(flow_cfg, defs);
156  if (result != DOCA_SUCCESS) {
157  DOCA_LOG_ERR("Failed to set doca_flow_cfg defs: %s", doca_error_get_descr(result));
158  goto destroy_cfg;
159  }
160  }
161 
162  /* creating doca flow with defs */
163  result = doca_flow_init(flow_cfg);
164  if (result != DOCA_SUCCESS)
165  DOCA_LOG_ERR("Failed to initialize DOCA Flow: %s", doca_error_get_descr(result));
166 destroy_cfg:
167  tmp_result = doca_flow_cfg_destroy(flow_cfg);
168  if (tmp_result != DOCA_SUCCESS) {
169  DOCA_LOG_ERR("Failed to destroy doca_flow_cfg: %s", doca_error_get_descr(tmp_result));
170  DOCA_ERROR_PROPAGATE(result, tmp_result);
171  }
172 
173  return result;
174 }
175 
176 /*
177  * Create DOCA Flow port by port id
178  *
179  * @port_id [in]: port ID
180  * @dev [in]: doca device to attach
181  * @state [in]: port operation initial state
182  * @port [out]: port handler on success
183  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
184  */
186  struct doca_dev *dev,
188  struct doca_flow_port **port,
189  uint32_t actions_mem_size)
190 {
191  struct doca_flow_port_cfg *port_cfg;
192  doca_error_t result, tmp_result;
193 
194  result = doca_flow_port_cfg_create(&port_cfg);
195  if (result != DOCA_SUCCESS) {
196  DOCA_LOG_ERR("Failed to create doca_flow_port_cfg: %s", doca_error_get_descr(result));
197  return result;
198  }
199 
200  result = doca_flow_port_cfg_set_dev(port_cfg, dev);
201  if (result != DOCA_SUCCESS) {
202  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg dev: %s", doca_error_get_descr(result));
203  goto destroy_port_cfg;
204  }
205 
206  result = doca_flow_port_cfg_set_port_id(port_cfg, port_id);
207  if (result != DOCA_SUCCESS) {
208  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg port_id: %s", doca_error_get_descr(result));
209  goto destroy_port_cfg;
210  }
211 
213  if (result != DOCA_SUCCESS) {
214  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg operation state: %s", doca_error_get_descr(result));
215  goto destroy_port_cfg;
216  }
217 
219  if (result != DOCA_SUCCESS) {
220  DOCA_LOG_ERR("Failed to set actions memory size: %s", doca_error_get_descr(result));
221  goto destroy_port_cfg;
222  }
223 
224  result = doca_flow_port_start(port_cfg, port);
225  if (result != DOCA_SUCCESS) {
226  DOCA_LOG_ERR("Failed to start doca_flow port: %s", doca_error_get_descr(result));
227  goto destroy_port_cfg;
228  }
229 
230 destroy_port_cfg:
231  tmp_result = doca_flow_port_cfg_destroy(port_cfg);
232  if (tmp_result != DOCA_SUCCESS) {
233  DOCA_LOG_ERR("Failed to destroy doca_flow port: %s", doca_error_get_descr(tmp_result));
234  DOCA_ERROR_PROPAGATE(result, tmp_result);
235  }
236 
237  return result;
238 }
239 
240 doca_error_t stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
241 {
242  int portid;
244 
245  /*
246  * Stop the ports in reverse order, since in switch mode port 0
247  * is proxy port, and proxy port should stop as last.
248  */
249  for (portid = nb_ports - 1; portid >= 0; portid--) {
250  if (ports[portid] != NULL) {
251  ret = doca_flow_port_stop(ports[portid]);
252  /* record first error */
253  if (ret != DOCA_SUCCESS && doca_error == DOCA_SUCCESS)
254  doca_error = ret;
255  }
256  }
257  return doca_error;
258 }
259 
261  struct doca_flow_port *ports[],
262  bool is_hairpin,
263  struct doca_dev *dev_arr[],
264  enum doca_flow_port_operation_state *states,
265  uint32_t actions_mem_size[])
266 {
267  int portid;
270 
271  for (portid = 0; portid < nb_ports; portid++) {
272  state = states ? states[portid] : DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE;
273  /* Create doca flow port */
274  result =
275  create_doca_flow_port(portid, dev_arr[portid], state, &ports[portid], actions_mem_size[portid]);
276  if (result != DOCA_SUCCESS) {
277  DOCA_LOG_ERR("Failed to start port: %s", doca_error_get_descr(result));
278  if (portid != 0)
279  stop_doca_flow_ports(portid, ports);
280  return result;
281  }
282  /* Pair ports should be done in the following order: port0 with port1, port2 with port3 etc */
283  if (!is_hairpin || !portid || !(portid % 2))
284  continue;
285  /* pair odd port with previous port */
286  result = doca_flow_port_pair(ports[portid], ports[portid ^ 1]);
287  if (result != DOCA_SUCCESS) {
288  DOCA_LOG_ERR("Failed to pair ports %u - %u", portid, portid ^ 1);
289  stop_doca_flow_ports(portid + 1, ports);
290  return result;
291  }
292  }
293  return DOCA_SUCCESS;
294 }
295 
297  struct doca_flow_port *ports[],
298  bool is_hairpin,
299  struct doca_dev *dev_arr[],
300  uint32_t actions_mem_size[])
301 {
303 }
304 
305 doca_error_t set_flow_pipe_cfg(struct doca_flow_pipe_cfg *cfg,
306  const char *name,
308  bool is_root)
309 {
311 
312  if (cfg == NULL) {
313  DOCA_LOG_ERR("Failed to set DOCA Flow pipe configurations, cfg=NULL");
315  }
316 
318  if (result != DOCA_SUCCESS) {
319  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
320  return result;
321  }
322 
324  if (result != DOCA_SUCCESS) {
325  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
326  return result;
327  }
328 
330  if (result != DOCA_SUCCESS) {
331  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
332  return result;
333  }
334 
335  return result;
336 }
337 
338 doca_error_t flow_process_entries(struct doca_flow_port *port, struct entries_status *status, uint32_t nr_entries)
339 {
341 
342  result = doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, nr_entries);
343  if (result != DOCA_SUCCESS) {
344  DOCA_LOG_ERR("Failed to process %u entries: %s", nr_entries, doca_error_get_descr(result));
345  return result;
346  }
347 
348  if (status->nb_processed != (int)nr_entries) {
349  DOCA_LOG_ERR("Failed to process %u entries, nb_processed=%d", nr_entries, status->nb_processed);
350  return DOCA_ERROR_BAD_STATE;
351  }
352 
353  if (status->failure) {
354  DOCA_LOG_ERR("Failed to process %u entries, status is failure", nr_entries);
355  return DOCA_ERROR_BAD_STATE;
356  }
357 
358  return DOCA_SUCCESS;
359 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
DOCA_LOG_REGISTER(IPSEC_SECURITY_GW::flow_common)
static uint16_t * rss_queues
Definition: flow_parser.c:114
static void pipe_process_cb(struct doca_flow_pipe *pipe, enum doca_flow_pipe_status status, enum doca_flow_pipe_op op, void *user_ctx)
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
#define DOCA_ERROR_PROPAGATE(r, t)
Save the first encountered doca_error_t.
Definition: doca_error.h:83
enum doca_error doca_error_t
DOCA API return codes.
doca_error
DOCA API return codes.
Definition: doca_error.h:37
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_ERROR_BAD_STATE
Definition: doca_error.h:56
@ DOCA_SUCCESS
Definition: doca_error.h:38
doca_flow_port_operation_state
Defines the operation states for a port instance.
Definition: doca_flow.h:1147
DOCA_STABLE doca_error_t doca_flow_cfg_set_mode_args(struct doca_flow_cfg *cfg, const char *mode_args)
Set DOCA mode args.
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_name(struct doca_flow_pipe_cfg *cfg, const char *name)
Set pipe's name.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_pair(struct doca_flow_port *port, struct doca_flow_port *pair_port)
pair two doca flow ports.
DOCA_STABLE doca_error_t doca_flow_cfg_set_nr_meters(struct doca_flow_cfg *cfg, uint32_t nr_meters)
Set number of traffic meters to configure.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_start(const struct doca_flow_port_cfg *cfg, struct doca_flow_port **port)
Start a doca port.
doca_flow_entry_op
doca flow entry operation
Definition: doca_flow.h:146
DOCA_STABLE doca_error_t doca_flow_cfg_set_cb_entry_process(struct doca_flow_cfg *cfg, doca_flow_entry_process_cb cb)
Set callback for entry create/destroy.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_is_root(struct doca_flow_pipe_cfg *cfg, bool is_root)
Set if pipe is root or not.
DOCA_STABLE doca_error_t doca_flow_cfg_create(struct doca_flow_cfg **cfg)
Create DOCA Flow configuration struct.
doca_flow_pipe_type
doca flow pipe type
Definition: doca_flow.h:220
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_type(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_type type)
Set pipe's type.
DOCA_EXPERIMENTAL doca_error_t doca_flow_init(struct doca_flow_cfg *cfg)
Initialize the doca flow.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_dev(struct doca_flow_port_cfg *cfg, struct doca_dev *dev)
Set port's device.
DOCA_STABLE doca_error_t doca_flow_cfg_set_nr_counters(struct doca_flow_cfg *cfg, uint32_t nr_counters)
Set number of counters to configure.
DOCA_STABLE doca_error_t doca_flow_cfg_set_cb_pipe_process(struct doca_flow_cfg *cfg, doca_flow_pipe_process_cb cb)
Set callback for pipe process completion.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_actions_mem_size(struct doca_flow_port_cfg *cfg, uint32_t size)
Set max memory size used by actions.
void(* doca_flow_pipe_process_cb)(struct doca_flow_pipe *pipe, enum doca_flow_pipe_status status, enum doca_flow_pipe_op op, void *user_ctx)
doca flow pipe process callback
Definition: doca_flow.h:196
DOCA_STABLE doca_error_t doca_flow_cfg_set_nr_shared_resource(struct doca_flow_cfg *cfg, uint32_t nr_shared_resource, enum doca_flow_shared_resource_type type)
Set number of shared resource.
DOCA_STABLE doca_error_t doca_flow_port_stop(struct doca_flow_port *port)
Stop a doca port.
DOCA_EXPERIMENTAL doca_error_t doca_flow_cfg_set_definitions(struct doca_flow_cfg *cfg, const struct doca_flow_definitions *defs)
Set the definition object.
doca_flow_entry_status
doca flow entry status
Definition: doca_flow.h:160
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_port_id(struct doca_flow_port_cfg *cfg, uint16_t port_id)
Set the logical port ID.
DOCA_EXPERIMENTAL doca_error_t doca_flow_cfg_set_default_rss(struct doca_flow_cfg *cfg, const struct doca_flow_resource_rss_cfg *rss)
Set RSS global configuration.
DOCA_STABLE doca_error_t doca_flow_port_cfg_create(struct doca_flow_port_cfg **cfg)
Create DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_port_cfg_destroy(struct doca_flow_port_cfg *cfg)
Destroy DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_cfg_set_pipe_queues(struct doca_flow_cfg *cfg, uint16_t pipe_queues)
Set pipe queues.
void(* doca_flow_entry_process_cb)(struct doca_flow_pipe_entry *entry, uint16_t pipe_queue, enum doca_flow_entry_status status, enum doca_flow_entry_op op, void *user_ctx)
doca flow entry process callback
Definition: doca_flow.h:204
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_operation_state(struct doca_flow_port_cfg *cfg, enum doca_flow_port_operation_state state)
Set default rules operation state.
DOCA_STABLE doca_error_t doca_flow_cfg_destroy(struct doca_flow_cfg *cfg)
Destroy DOCA Flow configuration struct.
@ DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
Definition: doca_flow.h:1148
@ DOCA_FLOW_ENTRY_STATUS_SUCCESS
Definition: doca_flow.h:163
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
uint8_t type
Definition: packets.h:0
static doca_error_t create_doca_flow_port(int port_id, struct doca_dev *dev, enum doca_flow_port_operation_state state, struct doca_flow_port **port, uint32_t actions_mem_size)
Definition: flow_common.c:185
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 init_doca_flow(int nb_queues, const char *mode, struct flow_resources *resource, uint32_t nr_shared_resources[])
Definition: flow_common.c:62
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_with_defs(int nb_queues, const char *mode, struct flow_resources *resource, uint32_t nr_shared_resources[], struct doca_flow_definitions *defs)
Definition: flow_common.c:70
void check_for_valid_entry(struct doca_flow_pipe_entry *entry, uint16_t pipe_queue, enum doca_flow_entry_status status, enum doca_flow_entry_op op, void *user_ctx)
Definition: flow_common.c:44
doca_error_t init_doca_flow_ports_with_op_state(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin, struct doca_dev *dev_arr[], enum doca_flow_port_operation_state *states, uint32_t actions_mem_size[])
Definition: flow_common.c:260
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
doca_error_t init_doca_flow_cb(int nb_queues, const char *mode, struct flow_resources *resource, uint32_t nr_shared_resources[], doca_flow_entry_process_cb cb, doca_flow_pipe_process_cb pipe_process_cb, struct doca_flow_definitions *defs)
Definition: flow_common.c:79
#define SHARED_RESOURCE_NUM_VALUES
Definition: flow_common.h:59
doca flow rss resource configuration
Definition: doca_flow.h:180
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
uint32_t nr_meters
Definition: flow_common.h:97
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