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