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