1a551c94aSIdo Barnea/*-
2a551c94aSIdo Barnea *   BSD LICENSE
3a551c94aSIdo Barnea *
4a551c94aSIdo Barnea *   Copyright(c) 2010-2016 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 <string.h>
35a551c94aSIdo Barnea
36a551c94aSIdo Barnea#include <rte_mbuf.h>
37a551c94aSIdo Barnea#include <rte_malloc.h>
38a551c94aSIdo Barnea#include <rte_ethdev.h>
39a551c94aSIdo Barnea#include <rte_tcp.h>
409ca4a157SIdo Barnea#include <rte_vdev.h>
41a551c94aSIdo Barnea
42a551c94aSIdo Barnea#include "rte_eth_bond.h"
43a551c94aSIdo Barnea#include "rte_eth_bond_private.h"
44a551c94aSIdo Barnea#include "rte_eth_bond_8023ad_private.h"
45a551c94aSIdo Barnea
46a551c94aSIdo Barnea#define DEFAULT_POLLING_INTERVAL_10_MS (10)
47a551c94aSIdo Barnea
48a551c94aSIdo Barneaint
49a551c94aSIdo Barneacheck_for_bonded_ethdev(const struct rte_eth_dev *eth_dev)
50a551c94aSIdo Barnea{
51a551c94aSIdo Barnea	/* Check valid pointer */
52a551c94aSIdo Barnea	if (eth_dev->data->drv_name == NULL)
53a551c94aSIdo Barnea		return -1;
54a551c94aSIdo Barnea
55a551c94aSIdo Barnea	/* return 0 if driver name matches */
569ca4a157SIdo Barnea	return eth_dev->data->drv_name != pmd_bond_drv.driver.name;
57a551c94aSIdo Barnea}
58a551c94aSIdo Barnea
59a551c94aSIdo Barneaint
60a551c94aSIdo Barneavalid_bonded_port_id(uint8_t port_id)
61a551c94aSIdo Barnea{
62a551c94aSIdo Barnea	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -1);
63a551c94aSIdo Barnea	return check_for_bonded_ethdev(&rte_eth_devices[port_id]);
64a551c94aSIdo Barnea}
65a551c94aSIdo Barnea
66a551c94aSIdo Barneaint
67a551c94aSIdo Barneavalid_slave_port_id(uint8_t port_id)
68a551c94aSIdo Barnea{
69a551c94aSIdo Barnea	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -1);
70a551c94aSIdo Barnea
71a551c94aSIdo Barnea	/* Verify that port_id refers to a non bonded port */
72a551c94aSIdo Barnea	if (check_for_bonded_ethdev(&rte_eth_devices[port_id]) == 0)
73a551c94aSIdo Barnea		return -1;
74a551c94aSIdo Barnea
75a551c94aSIdo Barnea	return 0;
76a551c94aSIdo Barnea}
77a551c94aSIdo Barnea
78a551c94aSIdo Barneavoid
79a551c94aSIdo Barneaactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id)
80a551c94aSIdo Barnea{
81a551c94aSIdo Barnea	struct bond_dev_private *internals = eth_dev->data->dev_private;
82a551c94aSIdo Barnea	uint8_t active_count = internals->active_slave_count;
83a551c94aSIdo Barnea
84a551c94aSIdo Barnea	if (internals->mode == BONDING_MODE_8023AD)
85a551c94aSIdo Barnea		bond_mode_8023ad_activate_slave(eth_dev, port_id);
86a551c94aSIdo Barnea
87a551c94aSIdo Barnea	if (internals->mode == BONDING_MODE_TLB
88a551c94aSIdo Barnea			|| internals->mode == BONDING_MODE_ALB) {
89a551c94aSIdo Barnea
90a551c94aSIdo Barnea		internals->tlb_slaves_order[active_count] = port_id;
91a551c94aSIdo Barnea	}
92a551c94aSIdo Barnea
93a551c94aSIdo Barnea	RTE_ASSERT(internals->active_slave_count <
94a551c94aSIdo Barnea			(RTE_DIM(internals->active_slaves) - 1));
95a551c94aSIdo Barnea
96a551c94aSIdo Barnea	internals->active_slaves[internals->active_slave_count] = port_id;
97a551c94aSIdo Barnea	internals->active_slave_count++;
98a551c94aSIdo Barnea
99a551c94aSIdo Barnea	if (internals->mode == BONDING_MODE_TLB)
100a551c94aSIdo Barnea		bond_tlb_activate_slave(internals);
101a551c94aSIdo Barnea	if (internals->mode == BONDING_MODE_ALB)
102a551c94aSIdo Barnea		bond_mode_alb_client_list_upd(eth_dev);
103a551c94aSIdo Barnea}
104a551c94aSIdo Barnea
105a551c94aSIdo Barneavoid
106a551c94aSIdo Barneadeactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id)
107a551c94aSIdo Barnea{
108a551c94aSIdo Barnea	uint8_t slave_pos;
109a551c94aSIdo Barnea	struct bond_dev_private *internals = eth_dev->data->dev_private;
110a551c94aSIdo Barnea	uint8_t active_count = internals->active_slave_count;
111a551c94aSIdo Barnea
112a551c94aSIdo Barnea	if (internals->mode == BONDING_MODE_8023AD) {
113a551c94aSIdo Barnea		bond_mode_8023ad_stop(eth_dev);
114a551c94aSIdo Barnea		bond_mode_8023ad_deactivate_slave(eth_dev, port_id);
115a551c94aSIdo Barnea	} else if (internals->mode == BONDING_MODE_TLB
116a551c94aSIdo Barnea			|| internals->mode == BONDING_MODE_ALB)
117a551c94aSIdo Barnea		bond_tlb_disable(internals);
118a551c94aSIdo Barnea
119a551c94aSIdo Barnea	slave_pos = find_slave_by_id(internals->active_slaves, active_count,
120a551c94aSIdo Barnea			port_id);
121a551c94aSIdo Barnea
122a551c94aSIdo Barnea	/* If slave was not at the end of the list
123a551c94aSIdo Barnea	 * shift active slaves up active array list */
124a551c94aSIdo Barnea	if (slave_pos < active_count) {
125a551c94aSIdo Barnea		active_count--;
126a551c94aSIdo Barnea		memmove(internals->active_slaves + slave_pos,
127a551c94aSIdo Barnea				internals->active_slaves + slave_pos + 1,
128a551c94aSIdo Barnea				(active_count - slave_pos) *
129a551c94aSIdo Barnea					sizeof(internals->active_slaves[0]));
130a551c94aSIdo Barnea	}
131a551c94aSIdo Barnea
132a551c94aSIdo Barnea	RTE_ASSERT(active_count < RTE_DIM(internals->active_slaves));
133a551c94aSIdo Barnea	internals->active_slave_count = active_count;
134a551c94aSIdo Barnea
135a551c94aSIdo Barnea	if (eth_dev->data->dev_started) {
136a551c94aSIdo Barnea		if (internals->mode == BONDING_MODE_8023AD) {
137a551c94aSIdo Barnea			bond_mode_8023ad_start(eth_dev);
138a551c94aSIdo Barnea		} else if (internals->mode == BONDING_MODE_TLB) {
139a551c94aSIdo Barnea			bond_tlb_enable(internals);
140a551c94aSIdo Barnea		} else if (internals->mode == BONDING_MODE_ALB) {
141a551c94aSIdo Barnea			bond_tlb_enable(internals);
142a551c94aSIdo Barnea			bond_mode_alb_client_list_upd(eth_dev);
143a551c94aSIdo Barnea		}
144a551c94aSIdo Barnea	}
145a551c94aSIdo Barnea}
146a551c94aSIdo Barnea
147a551c94aSIdo Barneauint8_t
148a551c94aSIdo Barneanumber_of_sockets(void)
149a551c94aSIdo Barnea{
150a551c94aSIdo Barnea	int sockets = 0;
151a551c94aSIdo Barnea	int i;
152a551c94aSIdo Barnea	const struct rte_memseg *ms = rte_eal_get_physmem_layout();
153a551c94aSIdo Barnea
154a551c94aSIdo Barnea	for (i = 0; ((i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL)); i++) {
155a551c94aSIdo Barnea		if (sockets < ms[i].socket_id)
156a551c94aSIdo Barnea			sockets = ms[i].socket_id;
157a551c94aSIdo Barnea	}
158a551c94aSIdo Barnea
159a551c94aSIdo Barnea	/* Number of sockets = maximum socket_id + 1 */
160a551c94aSIdo Barnea	return ++sockets;
161a551c94aSIdo Barnea}
162a551c94aSIdo Barnea
163a551c94aSIdo Barneaint
164a551c94aSIdo Barnearte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
165a551c94aSIdo Barnea{
166a551c94aSIdo Barnea	struct bond_dev_private *internals = NULL;
167a551c94aSIdo Barnea	struct rte_eth_dev *eth_dev = NULL;
1689ca4a157SIdo Barnea	uint32_t vlan_filter_bmp_size;
169a551c94aSIdo Barnea
170a551c94aSIdo Barnea	/* now do all data allocation - for eth_dev structure, dummy pci driver
171a551c94aSIdo Barnea	 * and internal (private) data
172a551c94aSIdo Barnea	 */
173a551c94aSIdo Barnea
174a551c94aSIdo Barnea	if (name == NULL) {
175a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Invalid name specified");
176a551c94aSIdo Barnea		goto err;
177a551c94aSIdo Barnea	}
178a551c94aSIdo Barnea
179a551c94aSIdo Barnea	if (socket_id >= number_of_sockets()) {
180a551c94aSIdo Barnea		RTE_BOND_LOG(ERR,
181a551c94aSIdo Barnea				"Invalid socket id specified to create bonded device on.");
182a551c94aSIdo Barnea		goto err;
183a551c94aSIdo Barnea	}
184a551c94aSIdo Barnea
185a551c94aSIdo Barnea	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id);
186a551c94aSIdo Barnea	if (internals == NULL) {
187a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Unable to malloc internals on socket");
188a551c94aSIdo Barnea		goto err;
189a551c94aSIdo Barnea	}
190a551c94aSIdo Barnea
191a551c94aSIdo Barnea	/* reserve an ethdev entry */
1929ca4a157SIdo Barnea	eth_dev = rte_eth_dev_allocate(name);
193a551c94aSIdo Barnea	if (eth_dev == NULL) {
194a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev");
195a551c94aSIdo Barnea		goto err;
196a551c94aSIdo Barnea	}
197a551c94aSIdo Barnea
198a551c94aSIdo Barnea	eth_dev->data->dev_private = internals;
199a551c94aSIdo Barnea	eth_dev->data->nb_rx_queues = (uint16_t)1;
200a551c94aSIdo Barnea	eth_dev->data->nb_tx_queues = (uint16_t)1;
201a551c94aSIdo Barnea
202a551c94aSIdo Barnea	eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0,
203a551c94aSIdo Barnea			socket_id);
204a551c94aSIdo Barnea	if (eth_dev->data->mac_addrs == NULL) {
205a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Unable to malloc mac_addrs");
206a551c94aSIdo Barnea		goto err;
207a551c94aSIdo Barnea	}
208a551c94aSIdo Barnea
209a551c94aSIdo Barnea	eth_dev->dev_ops = &default_dev_ops;
210a551c94aSIdo Barnea	eth_dev->data->dev_flags = RTE_ETH_DEV_INTR_LSC |
211a551c94aSIdo Barnea		RTE_ETH_DEV_DETACHABLE;
212a551c94aSIdo Barnea	eth_dev->driver = NULL;
213a551c94aSIdo Barnea	eth_dev->data->kdrv = RTE_KDRV_NONE;
2149ca4a157SIdo Barnea	eth_dev->data->drv_name = pmd_bond_drv.driver.name;
215a551c94aSIdo Barnea	eth_dev->data->numa_node =  socket_id;
216a551c94aSIdo Barnea
217a551c94aSIdo Barnea	rte_spinlock_init(&internals->lock);
218a551c94aSIdo Barnea
219a551c94aSIdo Barnea	internals->port_id = eth_dev->data->port_id;
220a551c94aSIdo Barnea	internals->mode = BONDING_MODE_INVALID;
221a551c94aSIdo Barnea	internals->current_primary_port = RTE_MAX_ETHPORTS + 1;
222a551c94aSIdo Barnea	internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
223a551c94aSIdo Barnea	internals->xmit_hash = xmit_l2_hash;
224a551c94aSIdo Barnea	internals->user_defined_mac = 0;
225a551c94aSIdo Barnea	internals->link_props_set = 0;
226a551c94aSIdo Barnea
227a551c94aSIdo Barnea	internals->link_status_polling_enabled = 0;
228a551c94aSIdo Barnea
229a551c94aSIdo Barnea	internals->link_status_polling_interval_ms = DEFAULT_POLLING_INTERVAL_10_MS;
230a551c94aSIdo Barnea	internals->link_down_delay_ms = 0;
231a551c94aSIdo Barnea	internals->link_up_delay_ms = 0;
232a551c94aSIdo Barnea
233a551c94aSIdo Barnea	internals->slave_count = 0;
234a551c94aSIdo Barnea	internals->active_slave_count = 0;
235a551c94aSIdo Barnea	internals->rx_offload_capa = 0;
236a551c94aSIdo Barnea	internals->tx_offload_capa = 0;
237a551c94aSIdo Barnea	internals->candidate_max_rx_pktlen = 0;
238a551c94aSIdo Barnea	internals->max_rx_pktlen = 0;
239a551c94aSIdo Barnea
240a551c94aSIdo Barnea	/* Initially allow to choose any offload type */
241a551c94aSIdo Barnea	internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK;
242a551c94aSIdo Barnea
243a551c94aSIdo Barnea	memset(internals->active_slaves, 0, sizeof(internals->active_slaves));
244a551c94aSIdo Barnea	memset(internals->slaves, 0, sizeof(internals->slaves));
245a551c94aSIdo Barnea
246a551c94aSIdo Barnea	/* Set mode 4 default configuration */
247a551c94aSIdo Barnea	bond_mode_8023ad_setup(eth_dev, NULL);
248a551c94aSIdo Barnea	if (bond_ethdev_mode_set(eth_dev, mode)) {
249a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Failed to set bonded device %d mode too %d",
250a551c94aSIdo Barnea				 eth_dev->data->port_id, mode);
251a551c94aSIdo Barnea		goto err;
252a551c94aSIdo Barnea	}
253a551c94aSIdo Barnea
2549ca4a157SIdo Barnea	vlan_filter_bmp_size =
2559ca4a157SIdo Barnea		rte_bitmap_get_memory_footprint(ETHER_MAX_VLAN_ID + 1);
2569ca4a157SIdo Barnea	internals->vlan_filter_bmpmem = rte_malloc(name, vlan_filter_bmp_size,
2579ca4a157SIdo Barnea						   RTE_CACHE_LINE_SIZE);
2589ca4a157SIdo Barnea	if (internals->vlan_filter_bmpmem == NULL) {
2599ca4a157SIdo Barnea		RTE_BOND_LOG(ERR,
2609ca4a157SIdo Barnea			     "Failed to allocate vlan bitmap for bonded device %u\n",
2619ca4a157SIdo Barnea			     eth_dev->data->port_id);
2629ca4a157SIdo Barnea		goto err;
2639ca4a157SIdo Barnea	}
2649ca4a157SIdo Barnea
2659ca4a157SIdo Barnea	internals->vlan_filter_bmp = rte_bitmap_init(ETHER_MAX_VLAN_ID + 1,
2669ca4a157SIdo Barnea			internals->vlan_filter_bmpmem, vlan_filter_bmp_size);
2679ca4a157SIdo Barnea	if (internals->vlan_filter_bmp == NULL) {
2689ca4a157SIdo Barnea		RTE_BOND_LOG(ERR,
2699ca4a157SIdo Barnea			     "Failed to init vlan bitmap for bonded device %u\n",
2709ca4a157SIdo Barnea			     eth_dev->data->port_id);
2719ca4a157SIdo Barnea		rte_free(internals->vlan_filter_bmpmem);
2729ca4a157SIdo Barnea		goto err;
2739ca4a157SIdo Barnea	}
2749ca4a157SIdo Barnea
275a551c94aSIdo Barnea	return eth_dev->data->port_id;
276a551c94aSIdo Barnea
277a551c94aSIdo Barneaerr:
278a551c94aSIdo Barnea	rte_free(internals);
279a551c94aSIdo Barnea	if (eth_dev != NULL) {
280a551c94aSIdo Barnea		rte_free(eth_dev->data->mac_addrs);
281a551c94aSIdo Barnea		rte_eth_dev_release_port(eth_dev);
282a551c94aSIdo Barnea	}
283a551c94aSIdo Barnea	return -1;
284a551c94aSIdo Barnea}
285a551c94aSIdo Barnea
286a551c94aSIdo Barneaint
287a551c94aSIdo Barnearte_eth_bond_free(const char *name)
288a551c94aSIdo Barnea{
289a551c94aSIdo Barnea	struct rte_eth_dev *eth_dev = NULL;
290a551c94aSIdo Barnea	struct bond_dev_private *internals;
291a551c94aSIdo Barnea
292a551c94aSIdo Barnea	/* now free all data allocation - for eth_dev structure,
293a551c94aSIdo Barnea	 * dummy pci driver and internal (private) data
294a551c94aSIdo Barnea	 */
295a551c94aSIdo Barnea
296a551c94aSIdo Barnea	/* find an ethdev entry */
297a551c94aSIdo Barnea	eth_dev = rte_eth_dev_allocated(name);
298a551c94aSIdo Barnea	if (eth_dev == NULL)
299a551c94aSIdo Barnea		return -ENODEV;
300a551c94aSIdo Barnea
301a551c94aSIdo Barnea	internals = eth_dev->data->dev_private;
302a551c94aSIdo Barnea	if (internals->slave_count != 0)
303a551c94aSIdo Barnea		return -EBUSY;
304a551c94aSIdo Barnea
305a551c94aSIdo Barnea	if (eth_dev->data->dev_started == 1) {
306a551c94aSIdo Barnea		bond_ethdev_stop(eth_dev);
307a551c94aSIdo Barnea		bond_ethdev_close(eth_dev);
308a551c94aSIdo Barnea	}
309a551c94aSIdo Barnea
310a551c94aSIdo Barnea	eth_dev->dev_ops = NULL;
311a551c94aSIdo Barnea	eth_dev->rx_pkt_burst = NULL;
312a551c94aSIdo Barnea	eth_dev->tx_pkt_burst = NULL;
313a551c94aSIdo Barnea
3149ca4a157SIdo Barnea	internals = eth_dev->data->dev_private;
3159ca4a157SIdo Barnea	rte_bitmap_free(internals->vlan_filter_bmp);
3169ca4a157SIdo Barnea	rte_free(internals->vlan_filter_bmpmem);
317a551c94aSIdo Barnea	rte_free(eth_dev->data->dev_private);
318a551c94aSIdo Barnea	rte_free(eth_dev->data->mac_addrs);
319a551c94aSIdo Barnea
320a551c94aSIdo Barnea	rte_eth_dev_release_port(eth_dev);
321a551c94aSIdo Barnea
322a551c94aSIdo Barnea	return 0;
323a551c94aSIdo Barnea}
324a551c94aSIdo Barnea
3259ca4a157SIdo Barneastatic int
3269ca4a157SIdo Barneaslave_vlan_filter_set(uint8_t bonded_port_id, uint8_t slave_port_id)
3279ca4a157SIdo Barnea{
3289ca4a157SIdo Barnea	struct rte_eth_dev *bonded_eth_dev;
3299ca4a157SIdo Barnea	struct bond_dev_private *internals;
3309ca4a157SIdo Barnea	int found;
3319ca4a157SIdo Barnea	int res = 0;
3329ca4a157SIdo Barnea	uint64_t slab = 0;
3339ca4a157SIdo Barnea	uint32_t pos = 0;
3349ca4a157SIdo Barnea	uint16_t first;
3359ca4a157SIdo Barnea
3369ca4a157SIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
3379ca4a157SIdo Barnea	if (bonded_eth_dev->data->dev_conf.rxmode.hw_vlan_filter == 0)
3389ca4a157SIdo Barnea		return 0;
3399ca4a157SIdo Barnea
3409ca4a157SIdo Barnea	internals = bonded_eth_dev->data->dev_private;
3419ca4a157SIdo Barnea	found = rte_bitmap_scan(internals->vlan_filter_bmp, &pos, &slab);
3429ca4a157SIdo Barnea	first = pos;
3439ca4a157SIdo Barnea
3449ca4a157SIdo Barnea	if (!found)
3459ca4a157SIdo Barnea		return 0;
3469ca4a157SIdo Barnea
3479ca4a157SIdo Barnea	do {
3489ca4a157SIdo Barnea		uint32_t i;
3499ca4a157SIdo Barnea		uint64_t mask;
3509ca4a157SIdo Barnea
3519ca4a157SIdo Barnea		for (i = 0, mask = 1;
3529ca4a157SIdo Barnea		     i < RTE_BITMAP_SLAB_BIT_SIZE;
3539ca4a157SIdo Barnea		     i ++, mask <<= 1) {
3549ca4a157SIdo Barnea			if (unlikely(slab & mask))
3559ca4a157SIdo Barnea				res = rte_eth_dev_vlan_filter(slave_port_id,
3569ca4a157SIdo Barnea							      (uint16_t)pos, 1);
3579ca4a157SIdo Barnea		}
3589ca4a157SIdo Barnea		found = rte_bitmap_scan(internals->vlan_filter_bmp,
3599ca4a157SIdo Barnea					&pos, &slab);
3609ca4a157SIdo Barnea	} while (found && first != pos && res == 0);
3619ca4a157SIdo Barnea
3629ca4a157SIdo Barnea	return res;
3639ca4a157SIdo Barnea}
3649ca4a157SIdo Barnea
365a551c94aSIdo Barneastatic int
366a551c94aSIdo Barnea__eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
367a551c94aSIdo Barnea{
368a551c94aSIdo Barnea	struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
369a551c94aSIdo Barnea	struct bond_dev_private *internals;
370a551c94aSIdo Barnea	struct rte_eth_link link_props;
371a551c94aSIdo Barnea	struct rte_eth_dev_info dev_info;
372a551c94aSIdo Barnea
373a551c94aSIdo Barnea	if (valid_slave_port_id(slave_port_id) != 0)
374a551c94aSIdo Barnea		return -1;
375a551c94aSIdo Barnea
376a551c94aSIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
377a551c94aSIdo Barnea	internals = bonded_eth_dev->data->dev_private;
378a551c94aSIdo Barnea
379a551c94aSIdo Barnea	slave_eth_dev = &rte_eth_devices[slave_port_id];
380a551c94aSIdo Barnea	if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_BONDED_SLAVE) {
381a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Slave device is already a slave of a bonded device");
382a551c94aSIdo Barnea		return -1;
383a551c94aSIdo Barnea	}
384a551c94aSIdo Barnea
385a551c94aSIdo Barnea	/* Add slave details to bonded device */
386a551c94aSIdo Barnea	slave_eth_dev->data->dev_flags |= RTE_ETH_DEV_BONDED_SLAVE;
387a551c94aSIdo Barnea
388a551c94aSIdo Barnea	rte_eth_dev_info_get(slave_port_id, &dev_info);
389a551c94aSIdo Barnea	if (dev_info.max_rx_pktlen < internals->max_rx_pktlen) {
390a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Slave (port %u) max_rx_pktlen too small",
391a551c94aSIdo Barnea			     slave_port_id);
392a551c94aSIdo Barnea		return -1;
393a551c94aSIdo Barnea	}
394a551c94aSIdo Barnea
395a551c94aSIdo Barnea	slave_add(internals, slave_eth_dev);
396a551c94aSIdo Barnea
397a551c94aSIdo Barnea	/* We need to store slaves reta_size to be able to synchronize RETA for all
398a551c94aSIdo Barnea	 * slave devices even if its sizes are different.
399a551c94aSIdo Barnea	 */
400a551c94aSIdo Barnea	internals->slaves[internals->slave_count].reta_size = dev_info.reta_size;
401a551c94aSIdo Barnea
402a551c94aSIdo Barnea	if (internals->slave_count < 1) {
403a551c94aSIdo Barnea		/* if MAC is not user defined then use MAC of first slave add to
404a551c94aSIdo Barnea		 * bonded device */
405a551c94aSIdo Barnea		if (!internals->user_defined_mac)
406a551c94aSIdo Barnea			mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs);
407a551c94aSIdo Barnea
408a551c94aSIdo Barnea		/* Inherit eth dev link properties from first slave */
409a551c94aSIdo Barnea		link_properties_set(bonded_eth_dev,
410a551c94aSIdo Barnea				&(slave_eth_dev->data->dev_link));
411a551c94aSIdo Barnea
412a551c94aSIdo Barnea		/* Make primary slave */
413a551c94aSIdo Barnea		internals->primary_port = slave_port_id;
414a551c94aSIdo Barnea		internals->current_primary_port = slave_port_id;
415a551c94aSIdo Barnea
416a551c94aSIdo Barnea		/* Inherit queues settings from first slave */
417a551c94aSIdo Barnea		internals->nb_rx_queues = slave_eth_dev->data->nb_rx_queues;
418a551c94aSIdo Barnea		internals->nb_tx_queues = slave_eth_dev->data->nb_tx_queues;
419a551c94aSIdo Barnea
420a551c94aSIdo Barnea		internals->reta_size = dev_info.reta_size;
421a551c94aSIdo Barnea
422a551c94aSIdo Barnea		/* Take the first dev's offload capabilities */
423a551c94aSIdo Barnea		internals->rx_offload_capa = dev_info.rx_offload_capa;
424a551c94aSIdo Barnea		internals->tx_offload_capa = dev_info.tx_offload_capa;
425a551c94aSIdo Barnea		internals->flow_type_rss_offloads = dev_info.flow_type_rss_offloads;
426a551c94aSIdo Barnea
427a551c94aSIdo Barnea		/* Inherit first slave's max rx packet size */
428a551c94aSIdo Barnea		internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen;
429a551c94aSIdo Barnea
430a551c94aSIdo Barnea	} else {
431a551c94aSIdo Barnea		internals->rx_offload_capa &= dev_info.rx_offload_capa;
432a551c94aSIdo Barnea		internals->tx_offload_capa &= dev_info.tx_offload_capa;
433a551c94aSIdo Barnea		internals->flow_type_rss_offloads &= dev_info.flow_type_rss_offloads;
434a551c94aSIdo Barnea
435a551c94aSIdo Barnea		/* RETA size is GCD of all slaves RETA sizes, so, if all sizes will be
436a551c94aSIdo Barnea		 * the power of 2, the lower one is GCD
437a551c94aSIdo Barnea		 */
438a551c94aSIdo Barnea		if (internals->reta_size > dev_info.reta_size)
439a551c94aSIdo Barnea			internals->reta_size = dev_info.reta_size;
440a551c94aSIdo Barnea
441a551c94aSIdo Barnea		if (!internals->max_rx_pktlen &&
442a551c94aSIdo Barnea		    dev_info.max_rx_pktlen < internals->candidate_max_rx_pktlen)
443a551c94aSIdo Barnea			internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen;
444a551c94aSIdo Barnea	}
445a551c94aSIdo Barnea
446a551c94aSIdo Barnea	bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf &=
447a551c94aSIdo Barnea			internals->flow_type_rss_offloads;
448a551c94aSIdo Barnea
449a551c94aSIdo Barnea	internals->slave_count++;
450a551c94aSIdo Barnea
451a551c94aSIdo Barnea	/* Update all slave devices MACs*/
452a551c94aSIdo Barnea	mac_address_slaves_update(bonded_eth_dev);
453a551c94aSIdo Barnea
454a551c94aSIdo Barnea	if (bonded_eth_dev->data->dev_started) {
455a551c94aSIdo Barnea		if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) {
456a551c94aSIdo Barnea			slave_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDED_SLAVE);
457a551c94aSIdo Barnea			RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d",
458a551c94aSIdo Barnea					slave_port_id);
459a551c94aSIdo Barnea			return -1;
460a551c94aSIdo Barnea		}
461a551c94aSIdo Barnea	}
462a551c94aSIdo Barnea
463a551c94aSIdo Barnea	/* Register link status change callback with bonded device pointer as
464a551c94aSIdo Barnea	 * argument*/
465a551c94aSIdo Barnea	rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
466a551c94aSIdo Barnea			bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id);
467a551c94aSIdo Barnea
468a551c94aSIdo Barnea	/* If bonded device is started then we can add the slave to our active
469a551c94aSIdo Barnea	 * slave array */
470a551c94aSIdo Barnea	if (bonded_eth_dev->data->dev_started) {
471a551c94aSIdo Barnea		rte_eth_link_get_nowait(slave_port_id, &link_props);
472a551c94aSIdo Barnea
473a551c94aSIdo Barnea		 if (link_props.link_status == ETH_LINK_UP) {
474a551c94aSIdo Barnea			if (internals->active_slave_count == 0 &&
475a551c94aSIdo Barnea			    !internals->user_defined_primary_port)
476a551c94aSIdo Barnea				bond_ethdev_primary_set(internals,
477a551c94aSIdo Barnea							slave_port_id);
478a551c94aSIdo Barnea
479a551c94aSIdo Barnea			if (find_slave_by_id(internals->active_slaves,
480a551c94aSIdo Barnea					     internals->active_slave_count,
481a551c94aSIdo Barnea					     slave_port_id) == internals->active_slave_count)
482a551c94aSIdo Barnea				activate_slave(bonded_eth_dev, slave_port_id);
483a551c94aSIdo Barnea		}
484a551c94aSIdo Barnea	}
4859ca4a157SIdo Barnea
4869ca4a157SIdo Barnea	slave_vlan_filter_set(bonded_port_id, slave_port_id);
4879ca4a157SIdo Barnea
488a551c94aSIdo Barnea	return 0;
489a551c94aSIdo Barnea
490a551c94aSIdo Barnea}
491a551c94aSIdo Barnea
492a551c94aSIdo Barneaint
493a551c94aSIdo Barnearte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
494a551c94aSIdo Barnea{
495a551c94aSIdo Barnea	struct rte_eth_dev *bonded_eth_dev;
496a551c94aSIdo Barnea	struct bond_dev_private *internals;
497a551c94aSIdo Barnea
498a551c94aSIdo Barnea	int retval;
499a551c94aSIdo Barnea
500a551c94aSIdo Barnea	/* Verify that port id's are valid bonded and slave ports */
501a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
502a551c94aSIdo Barnea		return -1;
503a551c94aSIdo Barnea
504a551c94aSIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
505a551c94aSIdo Barnea	internals = bonded_eth_dev->data->dev_private;
506a551c94aSIdo Barnea
507a551c94aSIdo Barnea	rte_spinlock_lock(&internals->lock);
508a551c94aSIdo Barnea
509a551c94aSIdo Barnea	retval = __eth_bond_slave_add_lock_free(bonded_port_id, slave_port_id);
510a551c94aSIdo Barnea
511a551c94aSIdo Barnea	rte_spinlock_unlock(&internals->lock);
512a551c94aSIdo Barnea
513a551c94aSIdo Barnea	return retval;
514a551c94aSIdo Barnea}
515a551c94aSIdo Barnea
516a551c94aSIdo Barneastatic int
517a551c94aSIdo Barnea__eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
518a551c94aSIdo Barnea{
519a551c94aSIdo Barnea	struct rte_eth_dev *bonded_eth_dev;
520a551c94aSIdo Barnea	struct bond_dev_private *internals;
521a551c94aSIdo Barnea	struct rte_eth_dev *slave_eth_dev;
522a551c94aSIdo Barnea	int i, slave_idx;
523a551c94aSIdo Barnea
524a551c94aSIdo Barnea	if (valid_slave_port_id(slave_port_id) != 0)
525a551c94aSIdo Barnea		return -1;
526a551c94aSIdo Barnea
527a551c94aSIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
528a551c94aSIdo Barnea	internals = bonded_eth_dev->data->dev_private;
529a551c94aSIdo Barnea
530a551c94aSIdo Barnea	/* first remove from active slave list */
531a551c94aSIdo Barnea	slave_idx = find_slave_by_id(internals->active_slaves,
532a551c94aSIdo Barnea		internals->active_slave_count, slave_port_id);
533a551c94aSIdo Barnea
534a551c94aSIdo Barnea	if (slave_idx < internals->active_slave_count)
535a551c94aSIdo Barnea		deactivate_slave(bonded_eth_dev, slave_port_id);
536a551c94aSIdo Barnea
537a551c94aSIdo Barnea	slave_idx = -1;
538a551c94aSIdo Barnea	/* now find in slave list */
539a551c94aSIdo Barnea	for (i = 0; i < internals->slave_count; i++)
540a551c94aSIdo Barnea		if (internals->slaves[i].port_id == slave_port_id) {
541a551c94aSIdo Barnea			slave_idx = i;
542a551c94aSIdo Barnea			break;
543a551c94aSIdo Barnea		}
544a551c94aSIdo Barnea
545a551c94aSIdo Barnea	if (slave_idx < 0) {
546a551c94aSIdo Barnea		RTE_BOND_LOG(ERR, "Couldn't find slave in port list, slave count %d",
547a551c94aSIdo Barnea				internals->slave_count);
548a551c94aSIdo Barnea		return -1;
549a551c94aSIdo Barnea	}
550a551c94aSIdo Barnea
551a551c94aSIdo Barnea	/* Un-register link status change callback with bonded device pointer as
552a551c94aSIdo Barnea	 * argument*/
553a551c94aSIdo Barnea	rte_eth_dev_callback_unregister(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
554a551c94aSIdo Barnea			bond_ethdev_lsc_event_callback,
555a551c94aSIdo Barnea			&rte_eth_devices[bonded_port_id].data->port_id);
556a551c94aSIdo Barnea
557a551c94aSIdo Barnea	/* Restore original MAC address of slave device */
558a551c94aSIdo Barnea	mac_address_set(&rte_eth_devices[slave_port_id],
559a551c94aSIdo Barnea			&(internals->slaves[slave_idx].persisted_mac_addr));
560a551c94aSIdo Barnea
561a551c94aSIdo Barnea	slave_eth_dev = &rte_eth_devices[slave_port_id];
562a551c94aSIdo Barnea	slave_remove(internals, slave_eth_dev);
563a551c94aSIdo Barnea	slave_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDED_SLAVE);
564a551c94aSIdo Barnea
565a551c94aSIdo Barnea	/*  first slave in the active list will be the primary by default,
566a551c94aSIdo Barnea	 *  otherwise use first device in list */
567a551c94aSIdo Barnea	if (internals->current_primary_port == slave_port_id) {
568a551c94aSIdo Barnea		if (internals->active_slave_count > 0)
569a551c94aSIdo Barnea			internals->current_primary_port = internals->active_slaves[0];
570a551c94aSIdo Barnea		else if (internals->slave_count > 0)
571a551c94aSIdo Barnea			internals->current_primary_port = internals->slaves[0].port_id;
572a551c94aSIdo Barnea		else
573a551c94aSIdo Barnea			internals->primary_port = 0;
574a551c94aSIdo Barnea	}
575a551c94aSIdo Barnea
576a551c94aSIdo Barnea	if (internals->active_slave_count < 1) {
577a551c94aSIdo Barnea		/* reset device link properties as no slaves are active */
578a551c94aSIdo Barnea		link_properties_reset(&rte_eth_devices[bonded_port_id]);
579a551c94aSIdo Barnea
580a551c94aSIdo Barnea		/* if no slaves are any longer attached to bonded device and MAC is not
581a551c94aSIdo Barnea		 * user defined then clear MAC of bonded device as it will be reset
582a551c94aSIdo Barnea		 * when a new slave is added */
583a551c94aSIdo Barnea		if (internals->slave_count < 1 && !internals->user_defined_mac)
584a551c94aSIdo Barnea			memset(rte_eth_devices[bonded_port_id].data->mac_addrs, 0,
585a551c94aSIdo Barnea					sizeof(*(rte_eth_devices[bonded_port_id].data->mac_addrs)));
586a551c94aSIdo Barnea	}
587a551c94aSIdo Barnea	if (internals->slave_count == 0) {
588a551c94aSIdo Barnea		internals->rx_offload_capa = 0;
589a551c94aSIdo Barnea		internals->tx_offload_capa = 0;
590a551c94aSIdo Barnea		internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK;
591a551c94aSIdo Barnea		internals->reta_size = 0;
592a551c94aSIdo Barnea		internals->candidate_max_rx_pktlen = 0;
593a551c94aSIdo Barnea		internals->max_rx_pktlen = 0;
594a551c94aSIdo Barnea	}
595a551c94aSIdo Barnea	return 0;
596a551c94aSIdo Barnea}
597a551c94aSIdo Barnea
598a551c94aSIdo Barneaint
599a551c94aSIdo Barnearte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
600a551c94aSIdo Barnea{
601a551c94aSIdo Barnea	struct rte_eth_dev *bonded_eth_dev;
602a551c94aSIdo Barnea	struct bond_dev_private *internals;
603a551c94aSIdo Barnea	int retval;
604a551c94aSIdo Barnea
605a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
606a551c94aSIdo Barnea		return -1;
607a551c94aSIdo Barnea
608a551c94aSIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
609a551c94aSIdo Barnea	internals = bonded_eth_dev->data->dev_private;
610a551c94aSIdo Barnea
611a551c94aSIdo Barnea	rte_spinlock_lock(&internals->lock);
612a551c94aSIdo Barnea
613a551c94aSIdo Barnea	retval = __eth_bond_slave_remove_lock_free(bonded_port_id, slave_port_id);
614a551c94aSIdo Barnea
615a551c94aSIdo Barnea	rte_spinlock_unlock(&internals->lock);
616a551c94aSIdo Barnea
617a551c94aSIdo Barnea	return retval;
618a551c94aSIdo Barnea}
619a551c94aSIdo Barnea
620a551c94aSIdo Barneaint
621a551c94aSIdo Barnearte_eth_bond_mode_set(uint8_t bonded_port_id, uint8_t mode)
622a551c94aSIdo Barnea{
623a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
624a551c94aSIdo Barnea		return -1;
625a551c94aSIdo Barnea
626a551c94aSIdo Barnea	return bond_ethdev_mode_set(&rte_eth_devices[bonded_port_id], mode);
627a551c94aSIdo Barnea}
628a551c94aSIdo Barnea
629a551c94aSIdo Barneaint
630a551c94aSIdo Barnearte_eth_bond_mode_get(uint8_t bonded_port_id)
631a551c94aSIdo Barnea{
632a551c94aSIdo Barnea	struct bond_dev_private *internals;
633a551c94aSIdo Barnea
634a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
635a551c94aSIdo Barnea		return -1;
636a551c94aSIdo Barnea
637a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
638a551c94aSIdo Barnea
639a551c94aSIdo Barnea	return internals->mode;
640a551c94aSIdo Barnea}
641a551c94aSIdo Barnea
642a551c94aSIdo Barneaint
643a551c94aSIdo Barnearte_eth_bond_primary_set(uint8_t bonded_port_id, uint8_t slave_port_id)
644a551c94aSIdo Barnea{
645a551c94aSIdo Barnea	struct bond_dev_private *internals;
646a551c94aSIdo Barnea
647a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
648a551c94aSIdo Barnea		return -1;
649a551c94aSIdo Barnea
650a551c94aSIdo Barnea	if (valid_slave_port_id(slave_port_id) != 0)
651a551c94aSIdo Barnea		return -1;
652a551c94aSIdo Barnea
653a551c94aSIdo Barnea	internals =  rte_eth_devices[bonded_port_id].data->dev_private;
654a551c94aSIdo Barnea
655a551c94aSIdo Barnea	internals->user_defined_primary_port = 1;
656a551c94aSIdo Barnea	internals->primary_port = slave_port_id;
657a551c94aSIdo Barnea
658a551c94aSIdo Barnea	bond_ethdev_primary_set(internals, slave_port_id);
659a551c94aSIdo Barnea
660a551c94aSIdo Barnea	return 0;
661a551c94aSIdo Barnea}
662a551c94aSIdo Barnea
663a551c94aSIdo Barneaint
664a551c94aSIdo Barnearte_eth_bond_primary_get(uint8_t bonded_port_id)
665a551c94aSIdo Barnea{
666a551c94aSIdo Barnea	struct bond_dev_private *internals;
667a551c94aSIdo Barnea
668a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
669a551c94aSIdo Barnea		return -1;
670a551c94aSIdo Barnea
671a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
672a551c94aSIdo Barnea
673a551c94aSIdo Barnea	if (internals->slave_count < 1)
674a551c94aSIdo Barnea		return -1;
675a551c94aSIdo Barnea
676a551c94aSIdo Barnea	return internals->current_primary_port;
677a551c94aSIdo Barnea}
678a551c94aSIdo Barnea
679a551c94aSIdo Barneaint
680a551c94aSIdo Barnearte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len)
681a551c94aSIdo Barnea{
682a551c94aSIdo Barnea	struct bond_dev_private *internals;
683a551c94aSIdo Barnea	uint8_t i;
684a551c94aSIdo Barnea
685a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
686a551c94aSIdo Barnea		return -1;
687a551c94aSIdo Barnea
688a551c94aSIdo Barnea	if (slaves == NULL)
689a551c94aSIdo Barnea		return -1;
690a551c94aSIdo Barnea
691a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
692a551c94aSIdo Barnea
693a551c94aSIdo Barnea	if (internals->slave_count > len)
694a551c94aSIdo Barnea		return -1;
695a551c94aSIdo Barnea
696a551c94aSIdo Barnea	for (i = 0; i < internals->slave_count; i++)
697a551c94aSIdo Barnea		slaves[i] = internals->slaves[i].port_id;
698a551c94aSIdo Barnea
699a551c94aSIdo Barnea	return internals->slave_count;
700a551c94aSIdo Barnea}
701a551c94aSIdo Barnea
702a551c94aSIdo Barneaint
703a551c94aSIdo Barnearte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[],
704a551c94aSIdo Barnea		uint8_t len)
705a551c94aSIdo Barnea{
706a551c94aSIdo Barnea	struct bond_dev_private *internals;
707a551c94aSIdo Barnea
708a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
709a551c94aSIdo Barnea		return -1;
710a551c94aSIdo Barnea
711a551c94aSIdo Barnea	if (slaves == NULL)
712a551c94aSIdo Barnea		return -1;
713a551c94aSIdo Barnea
714a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
715a551c94aSIdo Barnea
716a551c94aSIdo Barnea	if (internals->active_slave_count > len)
717a551c94aSIdo Barnea		return -1;
718a551c94aSIdo Barnea
719a551c94aSIdo Barnea	memcpy(slaves, internals->active_slaves, internals->active_slave_count);
720a551c94aSIdo Barnea
721a551c94aSIdo Barnea	return internals->active_slave_count;
722a551c94aSIdo Barnea}
723a551c94aSIdo Barnea
724a551c94aSIdo Barneaint
725a551c94aSIdo Barnearte_eth_bond_mac_address_set(uint8_t bonded_port_id,
726a551c94aSIdo Barnea		struct ether_addr *mac_addr)
727a551c94aSIdo Barnea{
728a551c94aSIdo Barnea	struct rte_eth_dev *bonded_eth_dev;
729a551c94aSIdo Barnea	struct bond_dev_private *internals;
730a551c94aSIdo Barnea
731a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
732a551c94aSIdo Barnea		return -1;
733a551c94aSIdo Barnea
734a551c94aSIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
735a551c94aSIdo Barnea	internals = bonded_eth_dev->data->dev_private;
736a551c94aSIdo Barnea
737a551c94aSIdo Barnea	/* Set MAC Address of Bonded Device */
738a551c94aSIdo Barnea	if (mac_address_set(bonded_eth_dev, mac_addr))
739a551c94aSIdo Barnea		return -1;
740a551c94aSIdo Barnea
741a551c94aSIdo Barnea	internals->user_defined_mac = 1;
742a551c94aSIdo Barnea
743a551c94aSIdo Barnea	/* Update all slave devices MACs*/
744a551c94aSIdo Barnea	if (internals->slave_count > 0)
745a551c94aSIdo Barnea		return mac_address_slaves_update(bonded_eth_dev);
746a551c94aSIdo Barnea
747a551c94aSIdo Barnea	return 0;
748a551c94aSIdo Barnea}
749a551c94aSIdo Barnea
750a551c94aSIdo Barneaint
751a551c94aSIdo Barnearte_eth_bond_mac_address_reset(uint8_t bonded_port_id)
752a551c94aSIdo Barnea{
753a551c94aSIdo Barnea	struct rte_eth_dev *bonded_eth_dev;
754a551c94aSIdo Barnea	struct bond_dev_private *internals;
755a551c94aSIdo Barnea
756a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
757a551c94aSIdo Barnea		return -1;
758a551c94aSIdo Barnea
759a551c94aSIdo Barnea	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
760a551c94aSIdo Barnea	internals = bonded_eth_dev->data->dev_private;
761a551c94aSIdo Barnea
762a551c94aSIdo Barnea	internals->user_defined_mac = 0;
763a551c94aSIdo Barnea
764a551c94aSIdo Barnea	if (internals->slave_count > 0) {
765a551c94aSIdo Barnea		/* Set MAC Address of Bonded Device */
766a551c94aSIdo Barnea		if (mac_address_set(bonded_eth_dev,
767a551c94aSIdo Barnea				&internals->slaves[internals->primary_port].persisted_mac_addr)
768a551c94aSIdo Barnea				!= 0) {
769a551c94aSIdo Barnea			RTE_BOND_LOG(ERR, "Failed to set MAC address on bonded device");
770a551c94aSIdo Barnea			return -1;
771a551c94aSIdo Barnea		}
772a551c94aSIdo Barnea		/* Update all slave devices MAC addresses */
773a551c94aSIdo Barnea		return mac_address_slaves_update(bonded_eth_dev);
774a551c94aSIdo Barnea	}
775a551c94aSIdo Barnea	/* No need to update anything as no slaves present */
776a551c94aSIdo Barnea	return 0;
777a551c94aSIdo Barnea}
778a551c94aSIdo Barnea
779a551c94aSIdo Barneaint
780a551c94aSIdo Barnearte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy)
781a551c94aSIdo Barnea{
782a551c94aSIdo Barnea	struct bond_dev_private *internals;
783a551c94aSIdo Barnea
784a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
785a551c94aSIdo Barnea		return -1;
786a551c94aSIdo Barnea
787a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
788a551c94aSIdo Barnea
789a551c94aSIdo Barnea	switch (policy) {
790a551c94aSIdo Barnea	case BALANCE_XMIT_POLICY_LAYER2:
791a551c94aSIdo Barnea		internals->balance_xmit_policy = policy;
792a551c94aSIdo Barnea		internals->xmit_hash = xmit_l2_hash;
793a551c94aSIdo Barnea		break;
794a551c94aSIdo Barnea	case BALANCE_XMIT_POLICY_LAYER23:
795a551c94aSIdo Barnea		internals->balance_xmit_policy = policy;
796a551c94aSIdo Barnea		internals->xmit_hash = xmit_l23_hash;
797a551c94aSIdo Barnea		break;
798a551c94aSIdo Barnea	case BALANCE_XMIT_POLICY_LAYER34:
799a551c94aSIdo Barnea		internals->balance_xmit_policy = policy;
800a551c94aSIdo Barnea		internals->xmit_hash = xmit_l34_hash;
801a551c94aSIdo Barnea		break;
802a551c94aSIdo Barnea
803a551c94aSIdo Barnea	default:
804a551c94aSIdo Barnea		return -1;
805a551c94aSIdo Barnea	}
806a551c94aSIdo Barnea	return 0;
807a551c94aSIdo Barnea}
808a551c94aSIdo Barnea
809a551c94aSIdo Barneaint
810a551c94aSIdo Barnearte_eth_bond_xmit_policy_get(uint8_t bonded_port_id)
811a551c94aSIdo Barnea{
812a551c94aSIdo Barnea	struct bond_dev_private *internals;
813a551c94aSIdo Barnea
814a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
815a551c94aSIdo Barnea		return -1;
816a551c94aSIdo Barnea
817a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
818a551c94aSIdo Barnea
819a551c94aSIdo Barnea	return internals->balance_xmit_policy;
820a551c94aSIdo Barnea}
821a551c94aSIdo Barnea
822a551c94aSIdo Barneaint
823a551c94aSIdo Barnearte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms)
824a551c94aSIdo Barnea{
825a551c94aSIdo Barnea	struct bond_dev_private *internals;
826a551c94aSIdo Barnea
827a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
828a551c94aSIdo Barnea		return -1;
829a551c94aSIdo Barnea
830a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
831a551c94aSIdo Barnea	internals->link_status_polling_interval_ms = internal_ms;
832a551c94aSIdo Barnea
833a551c94aSIdo Barnea	return 0;
834a551c94aSIdo Barnea}
835a551c94aSIdo Barnea
836a551c94aSIdo Barneaint
837a551c94aSIdo Barnearte_eth_bond_link_monitoring_get(uint8_t bonded_port_id)
838a551c94aSIdo Barnea{
839a551c94aSIdo Barnea	struct bond_dev_private *internals;
840a551c94aSIdo Barnea
841a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
842a551c94aSIdo Barnea		return -1;
843a551c94aSIdo Barnea
844a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
845a551c94aSIdo Barnea
846a551c94aSIdo Barnea	return internals->link_status_polling_interval_ms;
847a551c94aSIdo Barnea}
848a551c94aSIdo Barnea
849a551c94aSIdo Barneaint
850a551c94aSIdo Barnearte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms)
851a551c94aSIdo Barnea
852a551c94aSIdo Barnea{
853a551c94aSIdo Barnea	struct bond_dev_private *internals;
854a551c94aSIdo Barnea
855a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
856a551c94aSIdo Barnea		return -1;
857a551c94aSIdo Barnea
858a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
859a551c94aSIdo Barnea	internals->link_down_delay_ms = delay_ms;
860a551c94aSIdo Barnea
861a551c94aSIdo Barnea	return 0;
862a551c94aSIdo Barnea}
863a551c94aSIdo Barnea
864a551c94aSIdo Barneaint
865a551c94aSIdo Barnearte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id)
866a551c94aSIdo Barnea{
867a551c94aSIdo Barnea	struct bond_dev_private *internals;
868a551c94aSIdo Barnea
869a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
870a551c94aSIdo Barnea		return -1;
871a551c94aSIdo Barnea
872a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
873a551c94aSIdo Barnea
874a551c94aSIdo Barnea	return internals->link_down_delay_ms;
875a551c94aSIdo Barnea}
876a551c94aSIdo Barnea
877a551c94aSIdo Barneaint
878a551c94aSIdo Barnearte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms)
879a551c94aSIdo Barnea
880a551c94aSIdo Barnea{
881a551c94aSIdo Barnea	struct bond_dev_private *internals;
882a551c94aSIdo Barnea
883a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
884a551c94aSIdo Barnea		return -1;
885a551c94aSIdo Barnea
886a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
887a551c94aSIdo Barnea	internals->link_up_delay_ms = delay_ms;
888a551c94aSIdo Barnea
889a551c94aSIdo Barnea	return 0;
890a551c94aSIdo Barnea}
891a551c94aSIdo Barnea
892a551c94aSIdo Barneaint
893a551c94aSIdo Barnearte_eth_bond_link_up_prop_delay_get(uint8_t bonded_port_id)
894a551c94aSIdo Barnea{
895a551c94aSIdo Barnea	struct bond_dev_private *internals;
896a551c94aSIdo Barnea
897a551c94aSIdo Barnea	if (valid_bonded_port_id(bonded_port_id) != 0)
898a551c94aSIdo Barnea		return -1;
899a551c94aSIdo Barnea
900a551c94aSIdo Barnea	internals = rte_eth_devices[bonded_port_id].data->dev_private;
901a551c94aSIdo Barnea
902a551c94aSIdo Barnea	return internals->link_up_delay_ms;
903a551c94aSIdo Barnea}
904