NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_switch_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022-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 #include <string.h>
26 
27 #include <rte_byteorder.h>
28 #include <rte_ethdev.h>
29 
30 #include <doca_argp.h>
31 #include <doca_log.h>
32 #include <doca_dpdk.h>
33 
34 #include <dpdk_utils.h>
35 
36 #include "flow_switch_common.h"
37 
38 #define FLOW_SWITCH_DEV_ARGS "dv_flow_en=2,fdb_def_rule_en=0,vport_match=1,repr_matching_en=0,dv_xmeta_en=4"
39 #define FLOW_SWITCH_REP_ARG ",representor="
40 
41 DOCA_LOG_REGISTER(flow_switch_common);
42 
43 doca_error_t init_flow_switch_dpdk(int argc, char **dpdk_argv)
44 {
45  char *argv[argc + 2];
46 
47  memcpy(argv, dpdk_argv, sizeof(argv[0]) * argc);
48  argv[argc++] = "-a";
49  argv[argc++] = "pci:00:00.0";
50 
51  return dpdk_init(argc, argv);
52 }
53 
54 /*
55  * Get DOCA Flow switch device PCI
56  *
57  * @param [in]: input parameter
58  * @config [out]: configuration context
59  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
60  */
61 static doca_error_t param_flow_switch_pci_callback(void *param, void *config)
62 {
63  struct flow_switch_ctx *ctx = (struct flow_switch_ctx *)config;
64  char *n = (char *)param;
65 
66  if (FLOW_SWITCH_PORTS_MAX <= ctx->nb_ports) {
67  DOCA_LOG_ERR("Encountered too many PCI devices, maximal amount is: %d", FLOW_SWITCH_PORTS_MAX);
69  }
70 
71  ctx->dev_arg[ctx->nb_ports++] = n;
72 
73  return DOCA_SUCCESS;
74 }
75 
76 /*
77  * Get DOCA Flow switch device representor
78  *
79  * @param [in]: input parameter
80  * @config [out]: configuration context
81  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
82  */
83 static doca_error_t param_flow_switch_rep_callback(void *param, void *config)
84 {
85  struct flow_switch_ctx *ctx = (struct flow_switch_ctx *)config;
86  char *n = (char *)param;
87 
88  if (FLOW_SWITCH_PORTS_MAX <= ctx->nb_reps) {
89  DOCA_LOG_ERR("Encountered too many PCI devices representors, maximal amount is: %d",
92  }
93 
94  ctx->rep_arg[ctx->nb_reps++] = n;
95 
96  return DOCA_SUCCESS;
97 }
98 
99 /*
100  * Get DOCA Flow switch mode
101  *
102  * @param [in]: input parameter
103  * @config [out]: configuration context
104  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
105  */
106 static doca_error_t param_flow_switch_exp_callback(void *param, void *config)
107 {
108  struct flow_switch_ctx *ctx = (struct flow_switch_ctx *)config;
109 
110  ctx->is_expert = *(bool *)param;
111 
112  return DOCA_SUCCESS;
113 }
114 
116 {
118  struct doca_argp_param *pci_param;
119  struct doca_argp_param *rep_param;
120  struct doca_argp_param *exp_param;
121 
122  result = doca_argp_param_create(&pci_param);
123  if (result != DOCA_SUCCESS) {
124  DOCA_LOG_ERR("Failed to create flow switch ARGP param: %s", doca_error_get_descr(result));
125  return result;
126  }
127  doca_argp_param_set_short_name(pci_param, "p");
128  doca_argp_param_set_long_name(pci_param, "pci");
129  doca_argp_param_set_description(pci_param, "device PCI address");
133  result = doca_argp_register_param(pci_param);
134  if (result != DOCA_SUCCESS) {
135  DOCA_LOG_ERR("Failed to register flow switch ARGP param: %s", doca_error_get_descr(result));
136  return result;
137  }
138 
139  result = doca_argp_param_create(&rep_param);
140  if (result != DOCA_SUCCESS) {
141  DOCA_LOG_ERR("Failed to create flow switch ARGP param: %s", doca_error_get_descr(result));
142  return result;
143  }
144  doca_argp_param_set_short_name(rep_param, "r");
145  doca_argp_param_set_long_name(rep_param, "rep");
146  doca_argp_param_set_description(rep_param, "device representor");
150  result = doca_argp_register_param(rep_param);
151  if (result != DOCA_SUCCESS) {
152  DOCA_LOG_ERR("Failed to register flow switch ARGP param: %s", doca_error_get_descr(result));
153  return result;
154  }
155 
156  result = doca_argp_param_create(&exp_param);
157  if (result != DOCA_SUCCESS) {
158  DOCA_LOG_ERR("Failed to create flow switch ARGP param: %s", doca_error_get_descr(result));
159  return result;
160  }
161  doca_argp_param_set_short_name(exp_param, "exp");
162  doca_argp_param_set_long_name(exp_param, "expert-mode");
163  doca_argp_param_set_description(exp_param, "set expert mode");
166  result = doca_argp_register_param(exp_param);
167  if (result != DOCA_SUCCESS) {
168  DOCA_LOG_ERR("Failed to register flow switch ARGP param: %s", doca_error_get_descr(result));
169  return result;
170  }
171 
172  return DOCA_SUCCESS;
173 }
174 
176 {
177  char *port_args[FLOW_SWITCH_PORTS_MAX] = {0};
178  char *dpdk_arg;
180  int i;
181 
182  for (i = 0; i < ctx->nb_ports; i++) {
183  /* Probe dpdk dev by doca_dev */
184  result = open_doca_device_with_pci(ctx->dev_arg[i], ctx->port_cap, &ctx->doca_dev[i]);
185  if (result != DOCA_SUCCESS) {
186  DOCA_LOG_ERR("Failed to open DOCA device: %s", doca_error_get_descr(result));
187  goto quit;
188  }
189 
190  if (ctx->rep_arg[i]) {
191  port_args[i] = calloc(1,
192  strlen(FLOW_SWITCH_DEV_ARGS) + strlen(FLOW_SWITCH_REP_ARG) +
193  strlen(ctx->rep_arg[i]) + 1);
194  if (!port_args[i]) {
195  DOCA_LOG_ERR("Failed to allocate dpdk args port: %d", i);
197  goto quit;
198  }
199  strcpy(port_args[i], FLOW_SWITCH_DEV_ARGS);
200  strcat(port_args[i], FLOW_SWITCH_REP_ARG);
201  strcat(port_args[i], ctx->rep_arg[i]);
202  dpdk_arg = port_args[i];
203  } else {
204  dpdk_arg = FLOW_SWITCH_DEV_ARGS;
205  }
206  result = doca_dpdk_port_probe(ctx->doca_dev[i], dpdk_arg);
207  if (result != DOCA_SUCCESS) {
208  DOCA_LOG_ERR("Failed to probe DOCA device: %s", doca_error_get_descr(result));
209  goto quit;
210  }
211  }
212 
213 quit:
214  for (i = 0; i < ctx->nb_ports; i++)
215  free(port_args[i]);
216  if (result != DOCA_SUCCESS)
218  return result;
219 }
220 
222 {
223  int i;
224 
225  for (i = 0; i < ctx->nb_ports; i++) {
226  if (ctx->doca_dev[i]) {
227  doca_dev_close(ctx->doca_dev[i]);
228  ctx->doca_dev[i] = NULL;
229  }
230  }
231 }
232 
233 uint8_t get_dpdk_nb_ports(void)
234 {
235  uint8_t nb_ports = 0;
236  uint16_t port_id;
237 
238  for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
239  if (!rte_eth_dev_is_valid_port(port_id))
240  continue;
241 
242  nb_ports++;
243  DOCA_LOG_INFO("Port ID %u is valid DPDK port", port_id);
244  }
245 
246  return nb_ports;
247 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
doca_error_t dpdk_init(int argc, char **argv)
Definition: dpdk_utils.c:907
#define FLOW_SWITCH_REP_ARG
doca_error_t init_doca_flow_switch_common(struct flow_switch_ctx *ctx)
static doca_error_t param_flow_switch_rep_callback(void *param, void *config)
uint8_t get_dpdk_nb_ports(void)
DOCA_LOG_REGISTER(flow_switch_common)
void destroy_doca_flow_switch_common(struct flow_switch_ctx *ctx)
doca_error_t register_doca_flow_switch_param(void)
static doca_error_t param_flow_switch_pci_callback(void *param, void *config)
static doca_error_t param_flow_switch_exp_callback(void *param, void *config)
#define FLOW_SWITCH_DEV_ARGS
doca_error_t init_flow_switch_dpdk(int argc, char **dpdk_argv)
#define FLOW_SWITCH_PORTS_MAX
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
DOCA_EXPERIMENTAL void doca_argp_param_set_multiplicity(struct doca_argp_param *param)
Mark the program param as supporting multiple appearances.
@ DOCA_ARGP_TYPE_STRING
Definition: doca_argp.h:56
@ DOCA_ARGP_TYPE_BOOLEAN
Definition: doca_argp.h:58
DOCA_STABLE doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
DOCA_EXPERIMENTAL doca_error_t doca_dpdk_port_probe(struct doca_dev *dev, const char *devargs)
Attach a DPDK port specified by DOCA device.
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_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
#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
static int nb_ports
Definition: switch_core.c:44
struct upf_accel_ctx * ctx