X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbonding%2Frte_eth_bond_api.c;h=206a5c797a1ba55e6c2b59fdd2c00d2c21ea2bbc;hb=f5f93e106e0e4f5051b309112bd38e1d42e42dbd;hp=19347d88eeff282ac844c42df7150b0dcd38c50e;hpb=75aca7997e57b017e1a4224c9be9dfb3b15623d9;p=dpdk.git diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 19347d88ee..206a5c797a 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1,83 +1,76 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2017 Intel Corporation */ #include #include #include -#include +#include #include +#include +#include #include "rte_eth_bond.h" #include "rte_eth_bond_private.h" #include "rte_eth_bond_8023ad_private.h" -#define DEFAULT_POLLING_INTERVAL_10_MS (10) - -const char pmd_bond_driver_name[] = "rte_bond_pmd"; - int check_for_bonded_ethdev(const struct rte_eth_dev *eth_dev) { /* Check valid pointer */ - if (eth_dev->data->drv_name == NULL) + if (eth_dev->device->driver->name == NULL) return -1; /* return 0 if driver name matches */ - return eth_dev->data->drv_name != pmd_bond_driver_name; + return eth_dev->device->driver->name != pmd_bond_drv.driver.name; } int -valid_bonded_port_id(uint8_t port_id) +valid_bonded_port_id(uint16_t port_id) { RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -1); return check_for_bonded_ethdev(&rte_eth_devices[port_id]); } 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(uint16_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) + if (check_for_bonded_ethdev(&rte_eth_devices[port_id]) == 0 && + mode == BONDING_MODE_8023AD) { + RTE_BOND_LOG(ERR, "Cannot add slave to bonded device in 802.3ad" + " mode as slave is also a bonded device, only " + "physical devices can be support in this mode."); return -1; + } return 0; } void -activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) +activate_slave(struct rte_eth_dev *eth_dev, uint16_t port_id) { struct bond_dev_private *internals = eth_dev->data->dev_private; uint8_t active_count = internals->active_slave_count; @@ -104,11 +97,11 @@ activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) } void -deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) +deactivate_slave(struct rte_eth_dev *eth_dev, uint16_t port_id) { - uint8_t slave_pos; + uint16_t slave_pos; struct bond_dev_private *internals = eth_dev->data->dev_private; - uint8_t active_count = internals->active_slave_count; + uint16_t active_count = internals->active_slave_count; if (internals->mode == BONDING_MODE_8023AD) { bond_mode_8023ad_stop(eth_dev); @@ -145,186 +138,52 @@ deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) } } -uint8_t -number_of_sockets(void) -{ - int sockets = 0; - int i; - const struct rte_memseg *ms = rte_eal_get_physmem_layout(); - - for (i = 0; ((i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL)); i++) { - if (sockets < ms[i].socket_id) - sockets = ms[i].socket_id; - } - - /* Number of sockets = maximum socket_id + 1 */ - return ++sockets; -} - int rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) { - struct bond_dev_private *internals = NULL; - struct rte_eth_dev *eth_dev = NULL; - uint32_t vlan_filter_bmp_size; - - /* now do all data allocation - for eth_dev structure, dummy pci driver - * and internal (private) data - */ + struct bond_dev_private *internals; + char devargs[52]; + uint16_t port_id; + int ret; if (name == NULL) { RTE_BOND_LOG(ERR, "Invalid name specified"); - goto err; - } - - if (socket_id >= number_of_sockets()) { - RTE_BOND_LOG(ERR, - "Invalid socket id specified to create bonded device on."); - goto err; - } - - internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id); - if (internals == NULL) { - RTE_BOND_LOG(ERR, "Unable to malloc internals on socket"); - goto err; - } - - /* reserve an ethdev entry */ - eth_dev = rte_eth_dev_allocate(name); - if (eth_dev == NULL) { - RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev"); - goto err; - } - - eth_dev->data->dev_private = internals; - eth_dev->data->nb_rx_queues = (uint16_t)1; - eth_dev->data->nb_tx_queues = (uint16_t)1; - - eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0, - socket_id); - if (eth_dev->data->mac_addrs == NULL) { - RTE_BOND_LOG(ERR, "Unable to malloc mac_addrs"); - goto err; + return -EINVAL; } - eth_dev->dev_ops = &default_dev_ops; - eth_dev->data->dev_flags = RTE_ETH_DEV_INTR_LSC | - RTE_ETH_DEV_DETACHABLE; - eth_dev->driver = NULL; - eth_dev->data->kdrv = RTE_KDRV_NONE; - eth_dev->data->drv_name = pmd_bond_driver_name; - eth_dev->data->numa_node = socket_id; - - rte_spinlock_init(&internals->lock); - - internals->port_id = eth_dev->data->port_id; - internals->mode = BONDING_MODE_INVALID; - internals->current_primary_port = RTE_MAX_ETHPORTS + 1; - internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2; - internals->xmit_hash = xmit_l2_hash; - internals->user_defined_mac = 0; - internals->link_props_set = 0; - - internals->link_status_polling_enabled = 0; - - internals->link_status_polling_interval_ms = DEFAULT_POLLING_INTERVAL_10_MS; - internals->link_down_delay_ms = 0; - internals->link_up_delay_ms = 0; - - internals->slave_count = 0; - internals->active_slave_count = 0; - internals->rx_offload_capa = 0; - internals->tx_offload_capa = 0; - internals->candidate_max_rx_pktlen = 0; - internals->max_rx_pktlen = 0; + ret = snprintf(devargs, sizeof(devargs), + "driver=net_bonding,mode=%d,socket_id=%d", mode, socket_id); + if (ret < 0 || ret >= (int)sizeof(devargs)) + return -ENOMEM; - /* Initially allow to choose any offload type */ - internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK; + ret = rte_vdev_init(name, devargs); + if (ret) + return -ENOMEM; - memset(internals->active_slaves, 0, sizeof(internals->active_slaves)); - memset(internals->slaves, 0, sizeof(internals->slaves)); + ret = rte_eth_dev_get_port_by_name(name, &port_id); + RTE_ASSERT(!ret); - /* Set mode 4 default configuration */ - bond_mode_8023ad_setup(eth_dev, NULL); - if (bond_ethdev_mode_set(eth_dev, mode)) { - RTE_BOND_LOG(ERR, "Failed to set bonded device %d mode too %d", - eth_dev->data->port_id, mode); - goto err; - } - - vlan_filter_bmp_size = - rte_bitmap_get_memory_footprint(ETHER_MAX_VLAN_ID + 1); - internals->vlan_filter_bmpmem = rte_malloc(name, vlan_filter_bmp_size, - RTE_CACHE_LINE_SIZE); - if (internals->vlan_filter_bmpmem == NULL) { - RTE_BOND_LOG(ERR, - "Failed to allocate vlan bitmap for bonded device %u\n", - eth_dev->data->port_id); - goto err; - } - - internals->vlan_filter_bmp = rte_bitmap_init(ETHER_MAX_VLAN_ID + 1, - internals->vlan_filter_bmpmem, vlan_filter_bmp_size); - if (internals->vlan_filter_bmp == NULL) { - RTE_BOND_LOG(ERR, - "Failed to init vlan bitmap for bonded device %u\n", - eth_dev->data->port_id); - rte_free(internals->vlan_filter_bmpmem); - goto err; - } - - return eth_dev->data->port_id; + /* + * To make bond_ethdev_configure() happy we need to free the + * internals->kvlist here. + * + * Also see comment in bond_ethdev_configure(). + */ + internals = rte_eth_devices[port_id].data->dev_private; + rte_kvargs_free(internals->kvlist); + internals->kvlist = NULL; -err: - rte_free(internals); - if (eth_dev != NULL) { - rte_free(eth_dev->data->mac_addrs); - rte_eth_dev_release_port(eth_dev); - } - return -1; + return port_id; } int rte_eth_bond_free(const char *name) { - struct rte_eth_dev *eth_dev = NULL; - struct bond_dev_private *internals; - - /* now free all data allocation - for eth_dev structure, - * dummy pci driver and internal (private) data - */ - - /* find an ethdev entry */ - eth_dev = rte_eth_dev_allocated(name); - if (eth_dev == NULL) - return -ENODEV; - - internals = eth_dev->data->dev_private; - if (internals->slave_count != 0) - return -EBUSY; - - if (eth_dev->data->dev_started == 1) { - bond_ethdev_stop(eth_dev); - bond_ethdev_close(eth_dev); - } - - eth_dev->dev_ops = NULL; - eth_dev->rx_pkt_burst = NULL; - eth_dev->tx_pkt_burst = NULL; - - internals = eth_dev->data->dev_private; - rte_bitmap_free(internals->vlan_filter_bmp); - rte_free(internals->vlan_filter_bmpmem); - rte_free(eth_dev->data->dev_private); - rte_free(eth_dev->data->mac_addrs); - - rte_eth_dev_release_port(eth_dev); - - return 0; + return rte_vdev_uninit(name); } static int -slave_vlan_filter_set(uint8_t bonded_port_id, uint8_t slave_port_id) +slave_vlan_filter_set(uint16_t bonded_port_id, uint16_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; @@ -335,7 +194,8 @@ slave_vlan_filter_set(uint8_t bonded_port_id, uint8_t slave_port_id) uint16_t first; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; - if (bonded_eth_dev->data->dev_conf.rxmode.hw_vlan_filter == 0) + if ((bonded_eth_dev->data->dev_conf.rxmode.offloads & + DEV_RX_OFFLOAD_VLAN_FILTER) == 0) return 0; internals = bonded_eth_dev->data->dev_private; @@ -352,9 +212,12 @@ slave_vlan_filter_set(uint8_t bonded_port_id, uint8_t slave_port_id) for (i = 0, mask = 1; i < RTE_BITMAP_SLAB_BIT_SIZE; i ++, mask <<= 1) { - if (unlikely(slab & mask)) + if (unlikely(slab & mask)) { + uint16_t vlan_id = pos + i; + res = rte_eth_dev_vlan_filter(slave_port_id, - (uint16_t)pos, 1); + vlan_id, 1); + } } found = rte_bitmap_scan(internals->vlan_filter_bmp, &pos, &slab); @@ -364,28 +227,198 @@ slave_vlan_filter_set(uint8_t bonded_port_id, uint8_t slave_port_id) } static int -__eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) +slave_rte_flow_prepare(uint16_t slave_id, struct bond_dev_private *internals) +{ + struct rte_flow *flow; + struct rte_flow_error ferror; + uint16_t slave_port_id = internals->slaves[slave_id].port_id; + + if (internals->flow_isolated_valid != 0) { + rte_eth_dev_stop(slave_port_id); + if (rte_flow_isolate(slave_port_id, internals->flow_isolated, + &ferror)) { + RTE_BOND_LOG(ERR, "rte_flow_isolate failed for slave" + " %d: %s", slave_id, ferror.message ? + ferror.message : "(no stated reason)"); + return -1; + } + } + TAILQ_FOREACH(flow, &internals->flow_list, next) { + flow->flows[slave_id] = rte_flow_create(slave_port_id, + &flow->fd->attr, + flow->fd->items, + flow->fd->actions, + &ferror); + if (flow->flows[slave_id] == NULL) { + RTE_BOND_LOG(ERR, "Cannot create flow for slave" + " %d: %s", slave_id, + ferror.message ? ferror.message : + "(no stated reason)"); + /* Destroy successful bond flows from the slave */ + TAILQ_FOREACH(flow, &internals->flow_list, next) { + if (flow->flows[slave_id] != NULL) { + rte_flow_destroy(slave_port_id, + flow->flows[slave_id], + &ferror); + flow->flows[slave_id] = NULL; + } + } + return -1; + } + } + return 0; +} + +static void +eth_bond_slave_inherit_dev_info_rx_first(struct bond_dev_private *internals, + const struct rte_eth_dev_info *di) +{ + struct rte_eth_rxconf *rxconf_i = &internals->default_rxconf; + + internals->reta_size = di->reta_size; + + /* Inherit Rx offload capabilities from the first slave device */ + internals->rx_offload_capa = di->rx_offload_capa; + internals->rx_queue_offload_capa = di->rx_queue_offload_capa; + internals->flow_type_rss_offloads = di->flow_type_rss_offloads; + + /* Inherit maximum Rx packet size from the first slave device */ + internals->candidate_max_rx_pktlen = di->max_rx_pktlen; + + /* Inherit default Rx queue settings from the first slave device */ + memcpy(rxconf_i, &di->default_rxconf, sizeof(*rxconf_i)); + + /* + * Turn off descriptor prefetch and writeback by default for all + * slave devices. Applications may tweak this setting if need be. + */ + rxconf_i->rx_thresh.pthresh = 0; + rxconf_i->rx_thresh.hthresh = 0; + rxconf_i->rx_thresh.wthresh = 0; + + /* Setting this to zero should effectively enable default values */ + rxconf_i->rx_free_thresh = 0; + + /* Disable deferred start by default for all slave devices */ + rxconf_i->rx_deferred_start = 0; +} + +static void +eth_bond_slave_inherit_dev_info_tx_first(struct bond_dev_private *internals, + const struct rte_eth_dev_info *di) +{ + struct rte_eth_txconf *txconf_i = &internals->default_txconf; + + /* Inherit Tx offload capabilities from the first slave device */ + internals->tx_offload_capa = di->tx_offload_capa; + internals->tx_queue_offload_capa = di->tx_queue_offload_capa; + + /* Inherit default Tx queue settings from the first slave device */ + memcpy(txconf_i, &di->default_txconf, sizeof(*txconf_i)); + + /* + * Turn off descriptor prefetch and writeback by default for all + * slave devices. Applications may tweak this setting if need be. + */ + txconf_i->tx_thresh.pthresh = 0; + txconf_i->tx_thresh.hthresh = 0; + txconf_i->tx_thresh.wthresh = 0; + + /* + * Setting these parameters to zero assumes that default + * values will be configured implicitly by slave devices. + */ + txconf_i->tx_free_thresh = 0; + txconf_i->tx_rs_thresh = 0; + + /* Disable deferred start by default for all slave devices */ + txconf_i->tx_deferred_start = 0; +} + +static void +eth_bond_slave_inherit_dev_info_rx_next(struct bond_dev_private *internals, + const struct rte_eth_dev_info *di) +{ + struct rte_eth_rxconf *rxconf_i = &internals->default_rxconf; + const struct rte_eth_rxconf *rxconf = &di->default_rxconf; + + internals->rx_offload_capa &= di->rx_offload_capa; + internals->rx_queue_offload_capa &= di->rx_queue_offload_capa; + internals->flow_type_rss_offloads &= di->flow_type_rss_offloads; + + /* + * If at least one slave device suggests enabling this + * setting by default, enable it for all slave devices + * since disabling it may not be necessarily supported. + */ + if (rxconf->rx_drop_en == 1) + rxconf_i->rx_drop_en = 1; + + /* + * Adding a new slave device may cause some of previously inherited + * offloads to be withdrawn from the internal rx_queue_offload_capa + * value. Thus, the new internal value of default Rx queue offloads + * has to be masked by rx_queue_offload_capa to make sure that only + * commonly supported offloads are preserved from both the previous + * value and the value being inhereted from the new slave device. + */ + rxconf_i->offloads = (rxconf_i->offloads | rxconf->offloads) & + internals->rx_queue_offload_capa; + + /* + * RETA size is GCD of all slaves RETA sizes, so, if all sizes will be + * the power of 2, the lower one is GCD + */ + if (internals->reta_size > di->reta_size) + internals->reta_size = di->reta_size; + + if (!internals->max_rx_pktlen && + di->max_rx_pktlen < internals->candidate_max_rx_pktlen) + internals->candidate_max_rx_pktlen = di->max_rx_pktlen; +} + +static void +eth_bond_slave_inherit_dev_info_tx_next(struct bond_dev_private *internals, + const struct rte_eth_dev_info *di) +{ + struct rte_eth_txconf *txconf_i = &internals->default_txconf; + const struct rte_eth_txconf *txconf = &di->default_txconf; + + internals->tx_offload_capa &= di->tx_offload_capa; + internals->tx_queue_offload_capa &= di->tx_queue_offload_capa; + + /* + * Adding a new slave device may cause some of previously inherited + * offloads to be withdrawn from the internal tx_queue_offload_capa + * value. Thus, the new internal value of default Tx queue offloads + * has to be masked by tx_queue_offload_capa to make sure that only + * commonly supported offloads are preserved from both the previous + * value and the value being inhereted from the new slave device. + */ + txconf_i->offloads = (txconf_i->offloads | txconf->offloads) & + internals->tx_queue_offload_capa; +} + +static int +__eth_bond_slave_add_lock_free(uint16_t bonded_port_id, uint16_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev; 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; - 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; + 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; } - /* Add slave details to bonded device */ - slave_eth_dev->data->dev_flags |= RTE_ETH_DEV_BONDED_SLAVE; - rte_eth_dev_info_get(slave_port_id, &dev_info); if (dev_info.max_rx_pktlen < internals->max_rx_pktlen) { RTE_BOND_LOG(ERR, "Slave (port %u) max_rx_pktlen too small", @@ -403,8 +436,13 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) if (internals->slave_count < 1) { /* if MAC is not user defined then use MAC of first slave add to * bonded device */ - if (!internals->user_defined_mac) - mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs); + if (!internals->user_defined_mac) { + if (mac_address_set(bonded_eth_dev, + slave_eth_dev->data->mac_addrs)) { + RTE_BOND_LOG(ERR, "Failed to set MAC address"); + return -1; + } + } /* Inherit eth dev link properties from first slave */ link_properties_set(bonded_eth_dev, @@ -418,49 +456,46 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) internals->nb_rx_queues = slave_eth_dev->data->nb_rx_queues; internals->nb_tx_queues = slave_eth_dev->data->nb_tx_queues; - internals->reta_size = dev_info.reta_size; - - /* Take the first dev's offload capabilities */ - internals->rx_offload_capa = dev_info.rx_offload_capa; - internals->tx_offload_capa = dev_info.tx_offload_capa; - internals->flow_type_rss_offloads = dev_info.flow_type_rss_offloads; - - /* Inherit first slave's max rx packet size */ - internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen; - + eth_bond_slave_inherit_dev_info_rx_first(internals, &dev_info); + eth_bond_slave_inherit_dev_info_tx_first(internals, &dev_info); } else { - internals->rx_offload_capa &= dev_info.rx_offload_capa; - internals->tx_offload_capa &= dev_info.tx_offload_capa; - internals->flow_type_rss_offloads &= dev_info.flow_type_rss_offloads; - - /* RETA size is GCD of all slaves RETA sizes, so, if all sizes will be - * the power of 2, the lower one is GCD - */ - if (internals->reta_size > dev_info.reta_size) - internals->reta_size = dev_info.reta_size; - - if (!internals->max_rx_pktlen && - dev_info.max_rx_pktlen < internals->candidate_max_rx_pktlen) - internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen; + eth_bond_slave_inherit_dev_info_rx_next(internals, &dev_info); + eth_bond_slave_inherit_dev_info_tx_next(internals, &dev_info); } bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf &= internals->flow_type_rss_offloads; - internals->slave_count++; + if (slave_rte_flow_prepare(internals->slave_count, internals) != 0) { + RTE_BOND_LOG(ERR, "Failed to prepare new slave flows: port=%d", + slave_port_id); + return -1; + } - /* Update all slave devices MACs*/ - mac_address_slaves_update(bonded_eth_dev); + /* Add additional MAC addresses to the slave */ + if (slave_add_mac_addresses(bonded_eth_dev, slave_port_id) != 0) { + RTE_BOND_LOG(ERR, "Failed to add mac address(es) to slave %hu", + slave_port_id); + return -1; + } + + internals->slave_count++; if (bonded_eth_dev->data->dev_started) { if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) { - slave_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDED_SLAVE); + internals->slave_count--; RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d", slave_port_id); return -1; } } + /* Add slave details to bonded device */ + slave_eth_dev->data->dev_flags |= RTE_ETH_DEV_BONDED_SLAVE; + + /* Update all slave devices MACs */ + mac_address_slaves_update(bonded_eth_dev); + /* Register link status change callback with bonded device pointer as * argument*/ rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC, @@ -476,11 +511,6 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) !internals->user_defined_primary_port) bond_ethdev_primary_set(internals, slave_port_id); - - if (find_slave_by_id(internals->active_slaves, - internals->active_slave_count, - slave_port_id) == internals->active_slave_count) - activate_slave(bonded_eth_dev, slave_port_id); } } @@ -491,7 +521,7 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) } int -rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id) +rte_eth_bond_slave_add(uint16_t bonded_port_id, uint16_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; @@ -515,19 +545,22 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id) } static int -__eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) +__eth_bond_slave_remove_lock_free(uint16_t bonded_port_id, + uint16_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; struct rte_eth_dev *slave_eth_dev; + struct rte_flow_error flow_error; + struct rte_flow *flow; 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); @@ -556,9 +589,24 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) &rte_eth_devices[bonded_port_id].data->port_id); /* Restore original MAC address of slave device */ - mac_address_set(&rte_eth_devices[slave_port_id], + rte_eth_dev_default_mac_addr_set(slave_port_id, &(internals->slaves[slave_idx].persisted_mac_addr)); + /* remove additional MAC addresses from the slave */ + slave_remove_mac_addresses(bonded_eth_dev, slave_port_id); + + /* + * Remove bond device flows from slave device. + * Note: don't restore flow isolate mode. + */ + TAILQ_FOREACH(flow, &internals->flow_list, next) { + if (flow->flows[slave_idx] != NULL) { + rte_flow_destroy(slave_port_id, flow->flows[slave_idx], + &flow_error); + flow->flows[slave_idx] = NULL; + } + } + slave_eth_dev = &rte_eth_devices[slave_port_id]; slave_remove(internals, slave_eth_dev); slave_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDED_SLAVE); @@ -575,9 +623,6 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) } if (internals->active_slave_count < 1) { - /* reset device link properties as no slaves are active */ - link_properties_reset(&rte_eth_devices[bonded_port_id]); - /* if no slaves are any longer attached to bonded device and MAC is not * user defined then clear MAC of bonded device as it will be reset * when a new slave is added */ @@ -588,6 +633,8 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) if (internals->slave_count == 0) { internals->rx_offload_capa = 0; internals->tx_offload_capa = 0; + internals->rx_queue_offload_capa = 0; + internals->tx_queue_offload_capa = 0; internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK; internals->reta_size = 0; internals->candidate_max_rx_pktlen = 0; @@ -597,7 +644,7 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) } int -rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id) +rte_eth_bond_slave_remove(uint16_t bonded_port_id, uint16_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; @@ -619,16 +666,24 @@ rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id) } int -rte_eth_bond_mode_set(uint8_t bonded_port_id, uint8_t mode) +rte_eth_bond_mode_set(uint16_t bonded_port_id, uint8_t mode) { + struct rte_eth_dev *bonded_eth_dev; + if (valid_bonded_port_id(bonded_port_id) != 0) return -1; - return bond_ethdev_mode_set(&rte_eth_devices[bonded_port_id], mode); + bonded_eth_dev = &rte_eth_devices[bonded_port_id]; + + if (check_for_master_bonded_ethdev(bonded_eth_dev) != 0 && + mode == BONDING_MODE_8023AD) + return -1; + + return bond_ethdev_mode_set(bonded_eth_dev, mode); } int -rte_eth_bond_mode_get(uint8_t bonded_port_id) +rte_eth_bond_mode_get(uint16_t bonded_port_id) { struct bond_dev_private *internals; @@ -641,17 +696,17 @@ rte_eth_bond_mode_get(uint8_t bonded_port_id) } int -rte_eth_bond_primary_set(uint8_t bonded_port_id, uint8_t slave_port_id) +rte_eth_bond_primary_set(uint16_t bonded_port_id, uint16_t slave_port_id) { struct bond_dev_private *internals; 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; - 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; @@ -662,7 +717,7 @@ rte_eth_bond_primary_set(uint8_t bonded_port_id, uint8_t slave_port_id) } int -rte_eth_bond_primary_get(uint8_t bonded_port_id) +rte_eth_bond_primary_get(uint16_t bonded_port_id) { struct bond_dev_private *internals; @@ -678,7 +733,8 @@ rte_eth_bond_primary_get(uint8_t bonded_port_id) } int -rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len) +rte_eth_bond_slaves_get(uint16_t bonded_port_id, uint16_t slaves[], + uint16_t len) { struct bond_dev_private *internals; uint8_t i; @@ -701,8 +757,8 @@ rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len) } int -rte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], - uint8_t len) +rte_eth_bond_active_slaves_get(uint16_t bonded_port_id, uint16_t slaves[], + uint16_t len) { struct bond_dev_private *internals; @@ -717,13 +773,14 @@ rte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], if (internals->active_slave_count > len) return -1; - memcpy(slaves, internals->active_slaves, internals->active_slave_count); + memcpy(slaves, internals->active_slaves, + internals->active_slave_count * sizeof(internals->active_slaves[0])); return internals->active_slave_count; } int -rte_eth_bond_mac_address_set(uint8_t bonded_port_id, +rte_eth_bond_mac_address_set(uint16_t bonded_port_id, struct ether_addr *mac_addr) { struct rte_eth_dev *bonded_eth_dev; @@ -749,7 +806,7 @@ rte_eth_bond_mac_address_set(uint8_t bonded_port_id, } int -rte_eth_bond_mac_address_reset(uint8_t bonded_port_id) +rte_eth_bond_mac_address_reset(uint16_t bonded_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; @@ -763,9 +820,21 @@ rte_eth_bond_mac_address_reset(uint8_t bonded_port_id) internals->user_defined_mac = 0; if (internals->slave_count > 0) { + int slave_port; + /* Get the primary slave location based on the primary port + * number as, while slave_add(), we will keep the primary + * slave based on slave_count,but not based on the primary port. + */ + for (slave_port = 0; slave_port < internals->slave_count; + slave_port++) { + if (internals->slaves[slave_port].port_id == + internals->primary_port) + break; + } + /* Set MAC Address of Bonded Device */ if (mac_address_set(bonded_eth_dev, - &internals->slaves[internals->primary_port].persisted_mac_addr) + &internals->slaves[slave_port].persisted_mac_addr) != 0) { RTE_BOND_LOG(ERR, "Failed to set MAC address on bonded device"); return -1; @@ -778,7 +847,7 @@ rte_eth_bond_mac_address_reset(uint8_t bonded_port_id) } int -rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy) +rte_eth_bond_xmit_policy_set(uint16_t bonded_port_id, uint8_t policy) { struct bond_dev_private *internals; @@ -790,15 +859,15 @@ rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy) switch (policy) { case BALANCE_XMIT_POLICY_LAYER2: internals->balance_xmit_policy = policy; - internals->xmit_hash = xmit_l2_hash; + internals->burst_xmit_hash = burst_xmit_l2_hash; break; case BALANCE_XMIT_POLICY_LAYER23: internals->balance_xmit_policy = policy; - internals->xmit_hash = xmit_l23_hash; + internals->burst_xmit_hash = burst_xmit_l23_hash; break; case BALANCE_XMIT_POLICY_LAYER34: internals->balance_xmit_policy = policy; - internals->xmit_hash = xmit_l34_hash; + internals->burst_xmit_hash = burst_xmit_l34_hash; break; default: @@ -808,7 +877,7 @@ rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy) } int -rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id) +rte_eth_bond_xmit_policy_get(uint16_t bonded_port_id) { struct bond_dev_private *internals; @@ -821,7 +890,7 @@ rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id) } int -rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms) +rte_eth_bond_link_monitoring_set(uint16_t bonded_port_id, uint32_t internal_ms) { struct bond_dev_private *internals; @@ -835,7 +904,7 @@ rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms) } int -rte_eth_bond_link_monitoring_get(uint8_t bonded_port_id) +rte_eth_bond_link_monitoring_get(uint16_t bonded_port_id) { struct bond_dev_private *internals; @@ -848,7 +917,8 @@ rte_eth_bond_link_monitoring_get(uint8_t bonded_port_id) } int -rte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms) +rte_eth_bond_link_down_prop_delay_set(uint16_t bonded_port_id, + uint32_t delay_ms) { struct bond_dev_private *internals; @@ -863,7 +933,7 @@ rte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms) } int -rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id) +rte_eth_bond_link_down_prop_delay_get(uint16_t bonded_port_id) { struct bond_dev_private *internals; @@ -876,7 +946,7 @@ rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id) } int -rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms) +rte_eth_bond_link_up_prop_delay_set(uint16_t bonded_port_id, uint32_t delay_ms) { struct bond_dev_private *internals; @@ -891,7 +961,7 @@ rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms) } int -rte_eth_bond_link_up_prop_delay_get(uint8_t bonded_port_id) +rte_eth_bond_link_up_prop_delay_get(uint16_t bonded_port_id) { struct bond_dev_private *internals;