NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
eth_rxq_common.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 <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 
30 #include <doca_bitfield.h>
31 #include <doca_log.h>
32 #include <doca_flow.h>
33 
34 #include "eth_rxq_common.h"
35 
36 DOCA_LOG_REGISTER(ETH::RXQ::COMMON);
37 
38 #define COUNTERS_NUM (1 << 19)
39 #define DEFAULT_METADATA 1234
40 #define DEFAULT_FLOW_TAG 5678
41 
42 static bool is_flow_initialized = false;
43 
44 /*
45  * Initialize DOCA Flow with the flags: VNF/Hardware Steering/Isolated
46  *
47  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
48  */
50 {
51  doca_error_t result, tmp_result;
52  struct doca_flow_cfg *rxq_flow_cfg;
53 
54  result = doca_flow_cfg_create(&rxq_flow_cfg);
55  if (result != DOCA_SUCCESS) {
56  DOCA_LOG_ERR("Failed to create doca_flow_cfg, err: %s", doca_error_get_name(result));
57  return result;
58  }
59  result = doca_flow_cfg_set_pipe_queues(rxq_flow_cfg, 1);
60  if (result != DOCA_SUCCESS) {
61  DOCA_LOG_ERR("Failed to set pipe_queues, err: %s", doca_error_get_name(result));
62  goto destroy_cfg;
63  }
64  result = doca_flow_cfg_set_mode_args(rxq_flow_cfg, "vnf,isolated");
65  if (result != DOCA_SUCCESS) {
66  DOCA_LOG_ERR("Failed to set mode_args, err: %s", doca_error_get_name(result));
67  goto destroy_cfg;
68  }
70  if (result != DOCA_SUCCESS) {
71  DOCA_LOG_ERR("Failed to set nr_counters, err: %s", doca_error_get_name(result));
72  goto destroy_cfg;
73  }
74 
75  result = doca_flow_init(rxq_flow_cfg);
76  if (result != DOCA_SUCCESS) {
77  DOCA_LOG_ERR("Failed to init doca flow, err: %s", doca_error_get_name(result));
78  goto destroy_cfg;
79  }
80 
81 destroy_cfg:
82  tmp_result = doca_flow_cfg_destroy(rxq_flow_cfg);
83  if (tmp_result != DOCA_SUCCESS) {
84  DOCA_LOG_ERR("Failed to destroy doca_flow_cfg, err: %s", doca_error_get_name(tmp_result));
85  DOCA_ERROR_PROPAGATE(result, tmp_result);
86  }
87  return result;
88 }
89 
90 /*
91  * Start DOCA Flow with desired port ID
92  *
93  * @dev [in]: The doca device
94  * @df_port [out]: DOCA Flow port to start
95  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
96  */
97 static doca_error_t start_doca_flow_port(struct doca_dev *dev, struct doca_flow_port **df_port)
98 {
99  doca_error_t status, tmp_result;
100  struct doca_flow_port_cfg *port_cfg;
101 
102  status = doca_flow_port_cfg_create(&port_cfg);
103  if (status != DOCA_SUCCESS) {
104  DOCA_LOG_ERR("Failed to create doca_flow_port_cfg, err: %s", doca_error_get_name(status));
105  return status;
106  }
107 
108  status = doca_flow_port_cfg_set_port_id(port_cfg, 0);
109  if (status != DOCA_SUCCESS) {
110  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg port ID, err: %s", doca_error_get_name(status));
111  goto destroy_port_cfg;
112  }
113 
114  status = doca_flow_port_cfg_set_dev(port_cfg, dev);
115  if (status != DOCA_SUCCESS) {
116  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg dev, err: %s", doca_error_get_name(status));
117  goto destroy_port_cfg;
118  }
119 
120  status = doca_flow_port_start(port_cfg, df_port);
121  if (status != DOCA_SUCCESS) {
122  DOCA_LOG_ERR("Failed to start doca flow, err: %s", doca_error_get_name(status));
123  goto destroy_port_cfg;
124  }
125 
126 destroy_port_cfg:
127  tmp_result = doca_flow_port_cfg_destroy(port_cfg);
128  if (tmp_result != DOCA_SUCCESS) {
129  DOCA_LOG_ERR("Failed to set start doca_flow port: %s", doca_error_get_descr(tmp_result));
130  DOCA_ERROR_PROPAGATE(status, tmp_result);
131  }
132  return status;
133 }
134 
135 /*
136  * Create root pipe and add an entry into desired RXQ queue
137  *
138  * @df_port [in]: DOCA Flow port to create root pipe in
139  * @rxq_flow_queue_ids [in]: Pointer to RXQ queue ID
140  * @nb_queues [in]: Number of flow queues supplied
141  * @root_pipe [out]: DOCA Flow pipe to create
142  * @root_entry [out]: DOCA Flow port entry to create
143  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
144  */
145 static doca_error_t create_root_pipe(struct doca_flow_port *df_port,
146  uint16_t *rxq_flow_queue_ids,
147  uint16_t nb_queues,
148  struct doca_flow_pipe **root_pipe,
149  struct doca_flow_pipe_entry **root_entry)
150 {
151  doca_error_t status;
152  struct doca_flow_actions actions, *actions_arr[1];
153  struct doca_flow_match all_match;
154  struct doca_flow_pipe_cfg *pipe_cfg;
155  const char *pipe_name = "ROOT_PIPE";
156  struct doca_flow_fwd all_fwd = {
159  .rss =
160  {
161  .queues_array = rxq_flow_queue_ids,
162  .nr_queues = nb_queues,
163  .outer_flags = DOCA_FLOW_RSS_IPV4 | DOCA_FLOW_RSS_UDP,
164  },
165  };
166  struct doca_flow_fwd fwd_miss = {
168  };
169 
170  memset(&all_match, 0, sizeof(all_match));
171  memset(&actions, 0, sizeof(actions));
174  actions_arr[0] = &actions;
175 
176  status = doca_flow_pipe_cfg_create(&pipe_cfg, df_port);
177  if (status != DOCA_SUCCESS) {
178  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg, err: %s", doca_error_get_name(status));
179  return status;
180  }
181 
182  status = doca_flow_pipe_cfg_set_name(pipe_cfg, pipe_name);
183  if (status != DOCA_SUCCESS) {
184  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name, err: %s", doca_error_get_name(status));
185  goto destroy_pipe_cfg;
186  }
188  if (status != DOCA_SUCCESS) {
189  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type, err: %s", doca_error_get_name(status));
190  goto destroy_pipe_cfg;
191  }
192  status = doca_flow_pipe_cfg_set_is_root(pipe_cfg, true);
193  if (status != DOCA_SUCCESS) {
194  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root, err: %s", doca_error_get_name(status));
195  goto destroy_pipe_cfg;
196  }
197  status = doca_flow_pipe_cfg_set_match(pipe_cfg, &all_match, NULL);
198  if (status != DOCA_SUCCESS) {
199  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match, err: %s", doca_error_get_name(status));
200  goto destroy_pipe_cfg;
201  }
202  status = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, 1);
203  if (status != DOCA_SUCCESS) {
204  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(status));
205  goto destroy_pipe_cfg;
206  }
207 
208  status = doca_flow_pipe_create(pipe_cfg, &all_fwd, &fwd_miss, root_pipe);
209  if (status != DOCA_SUCCESS) {
210  DOCA_LOG_ERR("Failed to create doca flow pipe, err: %s", doca_error_get_name(status));
211  goto destroy_pipe_cfg;
212  }
213  doca_flow_pipe_cfg_destroy(pipe_cfg);
214 
215  status = doca_flow_pipe_add_entry(0, *root_pipe, &all_match, &actions, NULL, NULL, 0, NULL, root_entry);
216  if (status != DOCA_SUCCESS) {
217  doca_flow_pipe_destroy(*root_pipe);
218  DOCA_LOG_ERR("Failed to add doca flow entry, err: %s", doca_error_get_name(status));
219  return status;
220  }
221 
222  status = doca_flow_entries_process(df_port, 0, 10000, 4);
223  if (status != DOCA_SUCCESS) {
224  doca_flow_pipe_destroy(*root_pipe);
225  DOCA_LOG_ERR("Failed to process doca flow entry, err: %s", doca_error_get_name(status));
226  return status;
227  }
228 
229  DOCA_LOG_INFO("Created Pipe %s", pipe_name);
230 
231  return DOCA_SUCCESS;
232 
234  doca_flow_pipe_cfg_destroy(pipe_cfg);
235  return status;
236 }
237 
239 {
240  doca_error_t status;
241 
242  if (dev == NULL)
244 
245  /* Check if init_doca_flow() was already called once since calling it more than once is illegal */
246  if (is_flow_initialized == false) {
247  status = init_doca_flow();
248  if (status != DOCA_SUCCESS) {
249  DOCA_LOG_ERR("Failed to allocate eth_rxq_flow_resources: failed to init DOCA flow, err: %s",
250  doca_error_get_name(status));
251  return status;
252  }
253 
254  is_flow_initialized = true;
255  }
256 
257  status = start_doca_flow_port(dev, &(resources->df_port));
258  if (status != DOCA_SUCCESS) {
259  DOCA_LOG_ERR("Failed to allocate eth_rxq_flow_resources: failed to init DOCA flow port, err: %s",
260  doca_error_get_name(status));
261  goto destroy_doca_flow;
262  }
263 
264  return DOCA_SUCCESS;
265 
266 destroy_doca_flow:
268 
269  return status;
270 }
271 
273 {
274  doca_error_t status, clean_status;
275 
276  status = create_root_pipe(resources->df_port,
277  cfg->rxq_flow_queue_ids,
278  cfg->nb_queues,
279  &(resources->root_pipe),
280  &(resources->root_entry));
281  if (status != DOCA_SUCCESS) {
282  DOCA_LOG_ERR("Failed to allocate eth_rxq_flow_resources: failed to create root pipe, err: %s",
283  doca_error_get_name(status));
284  goto destroy_doca_flow_port;
285  }
286 
287  return DOCA_SUCCESS;
288 
289 destroy_doca_flow_port:
290  clean_status = doca_flow_port_stop(resources->df_port);
291  if (clean_status != DOCA_SUCCESS)
292  DOCA_LOG_ERR("Failed to stop DOCA flow port, err: %s", doca_error_get_name(clean_status));
294 
295  return status;
296 }
297 
299 {
300  doca_error_t status;
301 
302  if (resources->root_pipe != NULL)
303  doca_flow_pipe_destroy(resources->root_pipe);
304 
305  if (resources->df_port != NULL) {
306  status = doca_flow_port_stop(resources->df_port);
307  if (status != DOCA_SUCCESS) {
308  DOCA_LOG_ERR("Failed to stop DOCA flow port, err: %s", doca_error_get_name(status));
309  return status;
310  }
311  }
312 
313  if (is_flow_initialized == true) {
315  is_flow_initialized = false;
316  }
317 
318  return DOCA_SUCCESS;
319 }
320 
321 doca_error_t get_pkt_headroom(struct doca_buf *pkt, uint16_t *headroom_size)
322 {
323  void *pkt_head, *pkt_data;
324  doca_error_t status;
325 
326  status = doca_buf_get_head(pkt, &pkt_head);
327  if (status != DOCA_SUCCESS) {
328  DOCA_LOG_ERR("Failed to get doca_buf head, err: %s", doca_error_get_name(status));
329  return status;
330  }
331  status = doca_buf_get_data(pkt, &pkt_data);
332  if (status != DOCA_SUCCESS) {
333  DOCA_LOG_ERR("Failed to get doca_buf data, err: %s", doca_error_get_name(status));
334  return status;
335  }
336  *headroom_size = (uint8_t *)(pkt_data) - (uint8_t *)(pkt_head);
337 
338  return DOCA_SUCCESS;
339 }
340 
341 doca_error_t get_pkt_tailroom(struct doca_buf *pkt, uint16_t *tailroom_size)
342 {
343  size_t pkt_len, pkt_data_len;
344  doca_error_t status;
345  uint16_t headroom_size;
346 
347  status = get_pkt_headroom(pkt, &headroom_size);
348  if (status != DOCA_SUCCESS) {
349  DOCA_LOG_ERR("Failed to get packet headroom size, err: %s", doca_error_get_name(status));
350  return status;
351  }
352  status = doca_buf_get_len(pkt, &pkt_len);
353  if (status != DOCA_SUCCESS) {
354  DOCA_LOG_ERR("Failed to get doca_buf length, err: %s", doca_error_get_name(status));
355  return status;
356  }
357  status = doca_buf_get_data_len(pkt, &pkt_data_len);
358  if (status != DOCA_SUCCESS) {
359  DOCA_LOG_ERR("Failed to get doca_buf data length, err: %s", doca_error_get_name(status));
360  return status;
361  }
362  *tailroom_size = pkt_len - pkt_data_len - headroom_size;
363 
364  return DOCA_SUCCESS;
365 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
static doca_error_t create_root_pipe(struct doca_flow_port *df_port, uint16_t *rxq_flow_queue_ids, uint16_t nb_queues, struct doca_flow_pipe **root_pipe, struct doca_flow_pipe_entry **root_entry)
static doca_error_t init_doca_flow(void)
doca_error_t destroy_eth_rxq_flow_resources(struct eth_rxq_flow_resources *resources)
static bool is_flow_initialized
#define DEFAULT_FLOW_TAG
doca_error_t get_pkt_tailroom(struct doca_buf *pkt, uint16_t *tailroom_size)
doca_error_t get_pkt_headroom(struct doca_buf *pkt, uint16_t *headroom_size)
doca_error_t allocate_eth_rxq_flow_resources(struct eth_rxq_flow_config *cfg, struct eth_rxq_flow_resources *resources)
#define DEFAULT_METADATA
doca_error_t rxq_common_init_doca_flow(struct doca_dev *dev, struct eth_rxq_flow_resources *resources)
#define COUNTERS_NUM
static doca_error_t start_doca_flow_port(struct doca_dev *dev, struct doca_flow_port **df_port)
DOCA_LOG_REGISTER(ETH::RXQ::COMMON)
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static struct doca_flow_fwd fwd_miss
Definition: flow_parser.c:110
static struct doca_flow_actions actions
Definition: flow_parser.c:107
static struct doca_flow_port * df_port
struct rdma_resources resources
#define DOCA_HTOBE32(_x)
DOCA_STABLE doca_error_t doca_buf_get_len(const struct doca_buf *buf, size_t *len)
Get the buffer's length.
DOCA_STABLE doca_error_t doca_buf_get_data(const struct doca_buf *buf, void **data)
Get the buffer's data.
DOCA_STABLE doca_error_t doca_buf_get_data_len(const struct doca_buf *buf, size_t *data_len)
Get buffer's data length.
DOCA_STABLE doca_error_t doca_buf_get_head(const struct doca_buf *buf, void **head)
Get the buffer's head.
#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_STABLE const char * doca_error_get_name(doca_error_t error)
Returns the string representation of an error code name.
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_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_cfg_set_mode_args(struct doca_flow_cfg *cfg, const char *mode_args)
Set DOCA mode args.
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_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_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_port_start(const struct doca_flow_port_cfg *cfg, struct doca_flow_port **port)
Start a doca port.
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_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_STABLE doca_error_t doca_flow_cfg_create(struct doca_flow_cfg **cfg)
Create DOCA Flow configuration struct.
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 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_STABLE doca_error_t doca_flow_port_stop(struct doca_flow_port *port)
Stop a doca port.
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_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_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.
DOCA_STABLE doca_error_t doca_flow_cfg_destroy(struct doca_flow_cfg *cfg)
Destroy DOCA Flow configuration struct.
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_UDP
Definition: doca_flow.h:768
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
Definition: doca_flow.h:615
@ DOCA_FLOW_FWD_DROP
Definition: doca_flow.h:748
@ DOCA_FLOW_FWD_RSS
Definition: doca_flow.h:742
#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
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_meta meta
Definition: doca_flow.h:699
forwarding configuration
Definition: doca_flow.h:779
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
doca flow matcher information
Definition: doca_flow.h:491
doca_be32_t pkt_meta
Definition: doca_flow.h:359
doca_be32_t mark
Definition: doca_flow.h:361