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.kula...@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(-) diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 55d71d9..e1e7564 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -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; diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c index a8d9780..73e1032 100644 --- a/drivers/net/bonding/rte_eth_bond_pmd.c +++ b/drivers/net/bonding/rte_eth_bond_pmd.c @@ -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 diff --git a/drivers/net/bonding/rte_eth_bond_private.h b/drivers/net/bonding/rte_eth_bond_private.h index 50d908d..e27ceb8 100644 --- a/drivers/net/bonding/rte_eth_bond_private.h +++ b/drivers/net/bonding/rte_eth_bond_private.h @@ -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); -- 1.9.1