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