net/bonding: include PCI header directly
[dpdk.git] / drivers / net / bonding / rte_eth_bond_args.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_devargs.h>
35 #include <rte_pci.h>
36 #include <rte_kvargs.h>
37
38 #include <cmdline_parse.h>
39 #include <cmdline_parse_etheraddr.h>
40
41 #include "rte_eth_bond.h"
42 #include "rte_eth_bond_private.h"
43
44 const char *pmd_bond_init_valid_arguments[] = {
45         PMD_BOND_SLAVE_PORT_KVARG,
46         PMD_BOND_PRIMARY_SLAVE_KVARG,
47         PMD_BOND_MODE_KVARG,
48         PMD_BOND_XMIT_POLICY_KVARG,
49         PMD_BOND_SOCKET_ID_KVARG,
50         PMD_BOND_MAC_ADDR_KVARG,
51         "driver",
52         NULL
53 };
54
55 static inline int
56 find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr)
57 {
58         struct rte_pci_device *pci_dev;
59         struct rte_pci_addr *eth_pci_addr;
60         unsigned i;
61
62         for (i = 0; i < rte_eth_dev_count(); i++) {
63
64                 /* Currently populated by rte_eth_copy_pci_info().
65                  *
66                  * TODO: Once the PCI bus has arrived we should have a better
67                  * way to test for being a PCI device or not.
68                  */
69                 if (rte_eth_devices[i].data->kdrv == RTE_KDRV_UNKNOWN ||
70                     rte_eth_devices[i].data->kdrv == RTE_KDRV_NONE)
71                         continue;
72
73                 pci_dev = RTE_ETH_DEV_TO_PCI(&rte_eth_devices[i]);
74                 eth_pci_addr = &pci_dev->addr;
75
76                 if (pci_addr->bus == eth_pci_addr->bus &&
77                         pci_addr->devid == eth_pci_addr->devid &&
78                         pci_addr->domain == eth_pci_addr->domain &&
79                         pci_addr->function == eth_pci_addr->function)
80                         return i;
81         }
82         return -1;
83 }
84
85 static inline int
86 find_port_id_by_dev_name(const char *name)
87 {
88         unsigned i;
89
90         for (i = 0; i < rte_eth_dev_count(); i++) {
91                 if (rte_eth_devices[i].data == NULL)
92                         continue;
93
94                 if (strcmp(rte_eth_devices[i].device->name, name) == 0)
95                         return i;
96         }
97         return -1;
98 }
99
100 /**
101  * Parses a port identifier string to a port id by pci address, then by name,
102  * and finally port id.
103  */
104 static inline int
105 parse_port_id(const char *port_str)
106 {
107         struct rte_pci_addr dev_addr;
108         int port_id;
109
110         /* try parsing as pci address, physical devices */
111         if (eal_parse_pci_DomBDF(port_str, &dev_addr) == 0) {
112                 port_id = find_port_id_by_pci_addr(&dev_addr);
113                 if (port_id < 0)
114                         return -1;
115         } else {
116                 /* try parsing as device name, virtual devices */
117                 port_id = find_port_id_by_dev_name(port_str);
118                 if (port_id < 0) {
119                         char *end;
120                         errno = 0;
121
122                         /* try parsing as port id */
123                         port_id = strtol(port_str, &end, 10);
124                         if (*end != 0 || errno != 0)
125                                 return -1;
126                 }
127         }
128
129         if (port_id < 0 || port_id > RTE_MAX_ETHPORTS) {
130                 RTE_BOND_LOG(ERR, "Slave port specified (%s) outside expected range",
131                                 port_str);
132                 return -1;
133         }
134         return port_id;
135 }
136
137 int
138 bond_ethdev_parse_slave_port_kvarg(const char *key,
139                 const char *value, void *extra_args)
140 {
141         struct bond_ethdev_slave_ports *slave_ports;
142
143         if (value == NULL || extra_args == NULL)
144                 return -1;
145
146         slave_ports = extra_args;
147
148         if (strcmp(key, PMD_BOND_SLAVE_PORT_KVARG) == 0) {
149                 int port_id = parse_port_id(value);
150                 if (port_id < 0) {
151                         RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified", value);
152                         return -1;
153                 } else
154                         slave_ports->slaves[slave_ports->slave_count++] =
155                                         (uint8_t)port_id;
156         }
157         return 0;
158 }
159
160 int
161 bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused,
162                 const char *value, void *extra_args)
163 {
164         uint8_t *mode;
165         char *endptr;
166
167         if (value == NULL || extra_args == NULL)
168                 return -1;
169
170         mode = extra_args;
171
172         errno = 0;
173         *mode = strtol(value, &endptr, 10);
174         if (*endptr != 0 || errno != 0)
175                 return -1;
176
177         /* validate mode value */
178         switch (*mode) {
179         case BONDING_MODE_ROUND_ROBIN:
180         case BONDING_MODE_ACTIVE_BACKUP:
181         case BONDING_MODE_BALANCE:
182         case BONDING_MODE_BROADCAST:
183         case BONDING_MODE_8023AD:
184         case BONDING_MODE_TLB:
185         case BONDING_MODE_ALB:
186                 return 0;
187         default:
188                 RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified", value);
189                 return -1;
190         }
191 }
192
193 int
194 bond_ethdev_parse_socket_id_kvarg(const char *key __rte_unused,
195                 const char *value, void *extra_args)
196 {
197         int socket_id;
198         char *endptr;
199
200         if (value == NULL || extra_args == NULL)
201                 return -1;
202
203         errno = 0;
204         socket_id = (uint8_t)strtol(value, &endptr, 10);
205         if (*endptr != 0 || errno != 0)
206                 return -1;
207
208         /* validate socket id value */
209         if (socket_id >= 0) {
210                 *(uint8_t *)extra_args = (uint8_t)socket_id;
211                 return 0;
212         }
213         return -1;
214 }
215
216 int
217 bond_ethdev_parse_primary_slave_port_id_kvarg(const char *key __rte_unused,
218                 const char *value, void *extra_args)
219 {
220         int primary_slave_port_id;
221
222         if (value == NULL || extra_args == NULL)
223                 return -1;
224
225         primary_slave_port_id = parse_port_id(value);
226         if (primary_slave_port_id < 0)
227                 return -1;
228
229         *(uint8_t *)extra_args = (uint8_t)primary_slave_port_id;
230
231         return 0;
232 }
233
234 int
235 bond_ethdev_parse_balance_xmit_policy_kvarg(const char *key __rte_unused,
236                 const char *value, void *extra_args)
237 {
238         uint8_t *xmit_policy;
239
240         if (value == NULL || extra_args == NULL)
241                 return -1;
242
243         xmit_policy = extra_args;
244
245         if (strcmp(PMD_BOND_XMIT_POLICY_LAYER2_KVARG, value) == 0)
246                 *xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
247         else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER23_KVARG, value) == 0)
248                 *xmit_policy = BALANCE_XMIT_POLICY_LAYER23;
249         else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER34_KVARG, value) == 0)
250                 *xmit_policy = BALANCE_XMIT_POLICY_LAYER34;
251         else
252                 return -1;
253
254         return 0;
255 }
256
257 int
258 bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused,
259                 const char *value, void *extra_args)
260 {
261         if (value == NULL || extra_args == NULL)
262                 return -1;
263
264         /* Parse MAC */
265         return cmdline_parse_etheraddr(NULL, value, extra_args,
266                 sizeof(struct ether_addr));
267 }
268
269 int
270 bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused,
271                 const char *value, void *extra_args)
272 {
273         uint32_t time_ms;
274         char *endptr;
275
276         if (value == NULL || extra_args == NULL)
277                 return -1;
278
279         errno = 0;
280         time_ms = (uint32_t)strtol(value, &endptr, 10);
281         if (*endptr != 0 || errno != 0)
282                 return -1;
283
284         *(uint32_t *)extra_args = time_ms;
285
286         return 0;
287 }