This patch removes restrictions in bonded device library which prevent a
bonded device to be added to another bonded device.
Added link speed calculation for a bonding with fallowed rules:
- BROADCAST - Minimal slaves link speed
- ACTIVE_BACKUP - Current primary slave
- ROUND_ROBIN, BALANCE, 8023AD, TLB, ALB - Sum of slaves link speeds
There's two limitations to create master bonding:
- Total depth of nesting is limited to two levels,
- 802.3ad mode is not supported if one or more slaves is a bond device,
---
v2 changes:
- added dynamic link speed recalculation for a bonding
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
drivers/net/bonding/rte_eth_bond_api.c | 63 ++++++++++++++++++++------
drivers/net/bonding/rte_eth_bond_pmd.c | 73 +++++++++++++++++++++++++++---
drivers/net/bonding/rte_eth_bond_private.h | 7 ++-
3 files changed, 123 insertions(+), 20 deletions(-)
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,13 +63,45 @@
}
int
-valid_slave_port_id(uint8_t port_id)
+check_for_master_bonded_ethdev(const struct rte_eth_dev *eth_dev) {
+ int i;
+ struct bond_dev_private *internals;
+
+ if (check_for_bonded_ethdev(eth_dev) != 0)
+ return 0;
+
+ internals = eth_dev->data->dev_private;
+
+ /* Check if any of slave devices is a bonded device */
+ for (i = 0; i < internals->slave_count; i++)
+ if (valid_bonded_port_id(internals->slaves[i].port_id) == 0)
+ return 1;
+
+ return 0;
+}
+
+int
+valid_slave_port_id(uint8_t port_id, uint8_t mode)
{
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -1);
/* Verify that port_id refers to a non bonded port */
- if (check_for_bonded_ethdev(&rte_eth_devices[port_id]) == 0)
- return -1;
+ if (check_for_bonded_ethdev(&rte_eth_devices[port_id]) == 0) {
+ if (mode == BONDING_MODE_8023AD) {
+ RTE_BOND_LOG(ERR, "One or more slaves is a bond device,"
+ " there 802.3ad mode can not be"
+ " supported on this bond device.");
+ return -1;
+ }
+
+ if (check_for_master_bonded_ethdev(&rte_eth_devices[port_id])) {
+ RTE_BOND_LOG(ERR, "Too many levels of bonding");
+ return -1;
+ }
+
+ /* Slave is in master bonding */
+ return 1;
+ }
return 0;
}
@@ -234,14 +266,19 @@
struct bond_dev_private *internals;
struct rte_eth_link link_props;
struct rte_eth_dev_info dev_info;
-
- if (valid_slave_port_id(slave_port_id) != 0)
- return -1;
+ int status;
bonded_eth_dev = &rte_eth_devices[bonded_port_id];
internals = bonded_eth_dev->data->dev_private;
+ status = valid_slave_port_id(slave_port_id, internals->mode);
+
+ /* Slave is invalid */
+ if (status < 0)
+ return -1;
+
slave_eth_dev = &rte_eth_devices[slave_port_id];
+
if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_BONDED_SLAVE) {
RTE_BOND_LOG(ERR, "Slave device is already a slave of a bonded device");
return -1;
@@ -386,12 +423,12 @@
struct rte_eth_dev *slave_eth_dev;
int i, slave_idx;
- if (valid_slave_port_id(slave_port_id) != 0)
- return -1;
-
bonded_eth_dev = &rte_eth_devices[bonded_port_id];
internals = bonded_eth_dev->data->dev_private;
+ if (valid_slave_port_id(slave_port_id, internals->mode) < 0)
+ return -1;
+
/* first remove from active slave list */
slave_idx = find_slave_by_id(internals->active_slaves,
internals->active_slave_count, slave_port_id);
@@ -512,11 +549,11 @@
if (valid_bonded_port_id(bonded_port_id) != 0)
return -1;
- if (valid_slave_port_id(slave_port_id) != 0)
- return -1;
-
internals = rte_eth_devices[bonded_port_id].data->dev_private;
+ if (valid_slave_port_id(slave_port_id, internals->mode) < 0)
+ return -1;
+
internals->user_defined_primary_port = 1;
internals->primary_port = slave_port_id;
@@ -79,6 +79,50 @@
return vlan_offset;
}
+static uint32_t
+get_link_speed(struct rte_eth_dev *bonded_eth_dev)
+{
+ struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
+ int i;
+
+ struct rte_eth_link link_status;
+ uint32_t link_speed;
+
+ if (internals->active_slave_count < 1)
+ return 0;
+
+ switch (internals->mode) {
+ case BONDING_MODE_BROADCAST:
+ /* Minimal slaves link speed */
+ rte_eth_link_get(internals->active_slaves[0], &link_status);
+ link_speed = link_status.link_speed;
+ for (i = 1; i < internals->active_slave_count; i++) {
+ rte_eth_link_get(internals->active_slaves[i], &link_status);
+ if (link_status.link_speed < link_speed)
+ link_speed = link_status.link_speed;
+ }
+ break;
+ case BONDING_MODE_ACTIVE_BACKUP:
+ /* Current primary slave */
+ rte_eth_link_get(internals->current_primary_port, &link_status);
+ link_speed = link_status.link_speed;
+ break;
+ case BONDING_MODE_ROUND_ROBIN:
+ case BONDING_MODE_BALANCE:
+ case BONDING_MODE_8023AD:
+ case BONDING_MODE_TLB:
+ case BONDING_MODE_ALB:
+ default:
+ /* Sum of slaves link speeds */
+ link_speed = 0;
+ for (i = 0; i < internals->active_slave_count; i++) {
+ rte_eth_link_get(internals->active_slaves[i], &link_status);
+ link_speed += link_status.link_speed;
+ }
+ }
+ return link_speed;
+}
+
static uint16_t
bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
{
@@ -1139,9 +1183,10 @@ struct bwg_slave {
if (slave_dev_link->link_status &&
bonded_eth_dev->data->dev_started) {
- bonded_dev_link->link_duplex = slave_dev_link->link_duplex;
- bonded_dev_link->link_speed = slave_dev_link->link_speed;
-
+ internals->slave_link.link_duplex = slave_dev_link->link_duplex;
+ internals->slave_link.link_speed = slave_dev_link->link_speed;
+ memcpy(bonded_dev_link, &internals->slave_link,
+ sizeof(struct rte_eth_link));
internals->link_props_set = 1;
}
}
@@ -1153,6 +1198,8 @@ struct bwg_slave {
memset(&(bonded_eth_dev->data->dev_link), 0,
sizeof(bonded_eth_dev->data->dev_link));
+ memset(&(internals->slave_link), 0,
+ sizeof(bonded_eth_dev->data->dev_link));
internals->link_props_set = 0;
}
@@ -1292,6 +1339,12 @@ struct bwg_slave {
eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
break;
case BONDING_MODE_8023AD:
+ if (check_for_master_bonded_ethdev(eth_dev) == 1) {
+ RTE_BOND_LOG(ERR, "One or more slaves is a bond device,"
+ " there 802.3ad mode can not be"
+ " supported on this bond device.");
+ return -1;
+ }
if (bond_mode_8023ad_enable(eth_dev) != 0)
return -1;
@@ -1887,6 +1940,8 @@ struct bwg_slave {
}
bonded_eth_dev->data->dev_link.link_status = link_up;
+ bonded_eth_dev->data->dev_link.link_speed = get_link_speed(
+ bonded_eth_dev);
}
return 0;
@@ -2009,6 +2064,7 @@ struct bwg_slave {
int i, valid_slave = 0;
uint8_t active_pos;
uint8_t lsc_flag = 0;
+ uint8_t master_bonding;
if (type != RTE_ETH_EVENT_INTR_LSC || param == NULL)
return;
@@ -2058,9 +2114,11 @@ struct bwg_slave {
link_properties_set(bonded_eth_dev,
&(slave_eth_dev->data->dev_link));
} else {
- if (link_properties_valid(
- &bonded_eth_dev->data->dev_link, &link) != 0) {
- slave_eth_dev->data->dev_flags &=
+ master_bonding = check_for_master_bonded_ethdev(
+ bonded_eth_dev);
+ if ((master_bonding == 0) && link_properties_valid(
+ &internals->slave_link, &link) != 0) {
+ slave_eth_dev->data->dev_flags &=
(~RTE_ETH_DEV_BONDED_SLAVE);
RTE_LOG(ERR, PMD,
"port %u invalid speed/duplex\n",
@@ -2128,6 +2186,9 @@ struct bwg_slave {
RTE_ETH_EVENT_INTR_LSC, NULL);
}
}
+
+ bonded_eth_dev->data->dev_link.link_speed = get_link_speed(
+ bonded_eth_dev);
}
static int
@@ -135,6 +135,8 @@ struct bond_dev_private {
uint8_t link_props_set;
/**< flag to denote if the link properties are set */
+ struct rte_eth_link slave_link;
+
uint8_t link_status_polling_enabled;
uint32_t link_status_polling_interval_ms;
@@ -184,6 +186,9 @@ struct bond_dev_private {
int
check_for_bonded_ethdev(const struct rte_eth_dev *eth_dev);
+int
+check_for_master_bonded_ethdev(const struct rte_eth_dev *eth_dev);
+
/* Search given slave array to find position of given id.
* Return slave pos or slaves_count if not found. */
static inline uint8_t
@@ -205,7 +210,7 @@ struct bond_dev_private {
valid_bonded_port_id(uint8_t port_id);
int
-valid_slave_port_id(uint8_t port_id);
+valid_slave_port_id(uint8_t port_id, uint8_t mode);
void
deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id);