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