xref: /dpdk/drivers/net/bonding/rte_eth_bond_args.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include <rte_devargs.h>
6 #include <rte_pci.h>
7 #include <rte_bus_pci.h>
8 #include <rte_kvargs.h>
9 
10 #include "rte_eth_bond.h"
11 #include "eth_bond_private.h"
12 
13 const char *pmd_bond_init_valid_arguments[] = {
14 	PMD_BOND_SLAVE_PORT_KVARG,
15 	PMD_BOND_PRIMARY_SLAVE_KVARG,
16 	PMD_BOND_MODE_KVARG,
17 	PMD_BOND_XMIT_POLICY_KVARG,
18 	PMD_BOND_SOCKET_ID_KVARG,
19 	PMD_BOND_MAC_ADDR_KVARG,
20 	PMD_BOND_AGG_MODE_KVARG,
21 	"driver",
22 	NULL
23 };
24 
25 static inline int
26 bond_pci_addr_cmp(const struct rte_device *dev, const void *_pci_addr)
27 {
28 	const struct rte_pci_device *pdev = RTE_DEV_TO_PCI_CONST(dev);
29 	const struct rte_pci_addr *paddr = _pci_addr;
30 
31 	return rte_pci_addr_cmp(&pdev->addr, paddr);
32 }
33 
34 static inline int
35 find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr)
36 {
37 	struct rte_bus *pci_bus;
38 	struct rte_device *dev;
39 	unsigned i;
40 
41 	pci_bus = rte_bus_find_by_name("pci");
42 	if (pci_bus == NULL) {
43 		RTE_BOND_LOG(ERR, "No PCI bus found");
44 		return -1;
45 	}
46 
47 	dev = pci_bus->find_device(NULL, bond_pci_addr_cmp, pci_addr);
48 	if (dev == NULL) {
49 		RTE_BOND_LOG(ERR, "unable to find PCI device");
50 		return -1;
51 	}
52 
53 	RTE_ETH_FOREACH_DEV(i)
54 		if (rte_eth_devices[i].device == dev)
55 			return i;
56 	return -1;
57 }
58 
59 static inline int
60 find_port_id_by_dev_name(const char *name)
61 {
62 	unsigned i;
63 
64 	RTE_ETH_FOREACH_DEV(i) {
65 		if (rte_eth_devices[i].data == NULL)
66 			continue;
67 
68 		if (strcmp(rte_eth_devices[i].device->name, name) == 0)
69 			return i;
70 	}
71 	return -1;
72 }
73 
74 /**
75  * Parses a port identifier string to a port id by pci address, then by name,
76  * and finally port id.
77  */
78 static inline int
79 parse_port_id(const char *port_str)
80 {
81 	struct rte_pci_addr dev_addr;
82 	int port_id;
83 
84 	/* try parsing as pci address, physical devices */
85 	if (rte_pci_addr_parse(port_str, &dev_addr) == 0) {
86 		port_id = find_port_id_by_pci_addr(&dev_addr);
87 		if (port_id < 0)
88 			return -1;
89 	} else {
90 		/* try parsing as device name, virtual devices */
91 		port_id = find_port_id_by_dev_name(port_str);
92 		if (port_id < 0) {
93 			char *end;
94 			errno = 0;
95 
96 			/* try parsing as port id */
97 			port_id = strtol(port_str, &end, 10);
98 			if (*end != 0 || errno != 0)
99 				return -1;
100 		}
101 	}
102 
103 	if (!rte_eth_dev_is_valid_port(port_id)) {
104 		RTE_BOND_LOG(ERR, "Specified port (%s) is invalid", port_str);
105 		return -1;
106 	}
107 	return port_id;
108 }
109 
110 int
111 bond_ethdev_parse_slave_port_kvarg(const char *key,
112 		const char *value, void *extra_args)
113 {
114 	struct bond_ethdev_slave_ports *slave_ports;
115 
116 	if (value == NULL || extra_args == NULL)
117 		return -1;
118 
119 	slave_ports = extra_args;
120 
121 	if (strcmp(key, PMD_BOND_SLAVE_PORT_KVARG) == 0) {
122 		int port_id = parse_port_id(value);
123 		if (port_id < 0) {
124 			RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified",
125 				     value);
126 			return -1;
127 		} else
128 			slave_ports->slaves[slave_ports->slave_count++] =
129 					port_id;
130 	}
131 	return 0;
132 }
133 
134 int
135 bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused,
136 		const char *value, void *extra_args)
137 {
138 	uint8_t *mode;
139 	char *endptr;
140 
141 	if (value == NULL || extra_args == NULL)
142 		return -1;
143 
144 	mode = extra_args;
145 
146 	errno = 0;
147 	*mode = strtol(value, &endptr, 10);
148 	if (*endptr != 0 || errno != 0)
149 		return -1;
150 
151 	/* validate mode value */
152 	switch (*mode) {
153 	case BONDING_MODE_ROUND_ROBIN:
154 	case BONDING_MODE_ACTIVE_BACKUP:
155 	case BONDING_MODE_BALANCE:
156 	case BONDING_MODE_BROADCAST:
157 	case BONDING_MODE_8023AD:
158 	case BONDING_MODE_TLB:
159 	case BONDING_MODE_ALB:
160 		return 0;
161 	default:
162 		RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified", value);
163 		return -1;
164 	}
165 }
166 
167 int
168 bond_ethdev_parse_slave_agg_mode_kvarg(const char *key __rte_unused,
169 		const char *value, void *extra_args)
170 {
171 	uint8_t *agg_mode;
172 
173 	if (value == NULL || extra_args == NULL)
174 		return -1;
175 
176 	agg_mode = extra_args;
177 
178 	errno = 0;
179 	if (strncmp(value, "stable", 6) == 0)
180 		*agg_mode = AGG_STABLE;
181 
182 	if (strncmp(value, "bandwidth", 9) == 0)
183 		*agg_mode = AGG_BANDWIDTH;
184 
185 	if (strncmp(value, "count", 5) == 0)
186 		*agg_mode = AGG_COUNT;
187 
188 	switch (*agg_mode) {
189 	case AGG_STABLE:
190 	case AGG_BANDWIDTH:
191 	case AGG_COUNT:
192 		return 0;
193 	default:
194 		RTE_BOND_LOG(ERR, "Invalid agg mode value stable/bandwidth/count");
195 		return -1;
196 	}
197 }
198 
199 int
200 bond_ethdev_parse_socket_id_kvarg(const char *key __rte_unused,
201 		const char *value, void *extra_args)
202 {
203 	int socket_id;
204 	char *endptr;
205 
206 	if (value == NULL || extra_args == NULL)
207 		return -1;
208 
209 	errno = 0;
210 	socket_id = (uint8_t)strtol(value, &endptr, 10);
211 	if (*endptr != 0 || errno != 0)
212 		return -1;
213 
214 	/* validate socket id value */
215 	if (socket_id >= 0) {
216 		*(uint8_t *)extra_args = (uint8_t)socket_id;
217 		return 0;
218 	}
219 	return -1;
220 }
221 
222 int
223 bond_ethdev_parse_primary_slave_port_id_kvarg(const char *key __rte_unused,
224 		const char *value, void *extra_args)
225 {
226 	int primary_slave_port_id;
227 
228 	if (value == NULL || extra_args == NULL)
229 		return -1;
230 
231 	primary_slave_port_id = parse_port_id(value);
232 	if (primary_slave_port_id < 0)
233 		return -1;
234 
235 	*(uint16_t *)extra_args = (uint16_t)primary_slave_port_id;
236 
237 	return 0;
238 }
239 
240 int
241 bond_ethdev_parse_balance_xmit_policy_kvarg(const char *key __rte_unused,
242 		const char *value, void *extra_args)
243 {
244 	uint8_t *xmit_policy;
245 
246 	if (value == NULL || extra_args == NULL)
247 		return -1;
248 
249 	xmit_policy = extra_args;
250 
251 	if (strcmp(PMD_BOND_XMIT_POLICY_LAYER2_KVARG, value) == 0)
252 		*xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
253 	else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER23_KVARG, value) == 0)
254 		*xmit_policy = BALANCE_XMIT_POLICY_LAYER23;
255 	else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER34_KVARG, value) == 0)
256 		*xmit_policy = BALANCE_XMIT_POLICY_LAYER34;
257 	else
258 		return -1;
259 
260 	return 0;
261 }
262 
263 int
264 bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused,
265 		const char *value, void *extra_args)
266 {
267 	if (value == NULL || extra_args == NULL)
268 		return -1;
269 
270 	/* Parse MAC */
271 	return rte_ether_unformat_addr(value, extra_args);
272 }
273 
274 int
275 bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused,
276 		const char *value, void *extra_args)
277 {
278 	uint32_t time_ms;
279 	char *endptr;
280 
281 	if (value == NULL || extra_args == NULL)
282 		return -1;
283 
284 	errno = 0;
285 	time_ms = (uint32_t)strtol(value, &endptr, 10);
286 	if (*endptr != 0 || errno != 0)
287 		return -1;
288 
289 	*(uint32_t *)extra_args = time_ms;
290 
291 	return 0;
292 }
293