X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbonding%2Frte_eth_bond_api.c;h=f552d96953336871ff3106dc3a2bdc3dc739305b;hb=2d5036ab10d14496307b7351b354c700f1c89d49;hp=34adbde401623ccbf3d6781e5b6cbd1a9e03422d;hpb=8fb9e2bbf9958351cb8c2ed5bee6e68613dfaae2;p=dpdk.git diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 34adbde401..f552d96953 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-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ #include #include #include +#include #include "rte_eth_bond.h" #include "rte_eth_bond_private.h" @@ -44,37 +45,31 @@ #define DEFAULT_POLLING_INTERVAL_10_MS (10) -const char pmd_bond_driver_name[] = "rte_bond_pmd"; - int -valid_bonded_ethdev(const struct rte_eth_dev *eth_dev) +check_for_bonded_ethdev(const struct rte_eth_dev *eth_dev) { /* Check valid pointer */ - if (eth_dev->driver->pci_drv.name == NULL) + if (eth_dev->data->drv_name == NULL) return -1; /* return 0 if driver name matches */ - return eth_dev->driver->pci_drv.name != pmd_bond_driver_name; + return eth_dev->data->drv_name != pmd_bond_drv.driver.name; } int valid_bonded_port_id(uint8_t port_id) { - if (!rte_eth_dev_is_valid_port(port_id)) - return -1; - - return valid_bonded_ethdev(&rte_eth_devices[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) { - /* Verify that port id's are valid */ - if (!rte_eth_dev_is_valid_port(port_id)) - return -1; + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -1); /* Verify that port_id refers to a non bonded port */ - if (!valid_bonded_ethdev(&rte_eth_devices[port_id])) + if (check_for_bonded_ethdev(&rte_eth_devices[port_id]) == 0) return -1; return 0; @@ -95,7 +90,7 @@ activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) internals->tlb_slaves_order[active_count] = port_id; } - RTE_VERIFY(internals->active_slave_count < + RTE_ASSERT(internals->active_slave_count < (RTE_DIM(internals->active_slaves) - 1)); internals->active_slaves[internals->active_slave_count] = port_id; @@ -134,7 +129,7 @@ deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) sizeof(internals->active_slaves[0])); } - RTE_VERIFY(active_count < RTE_DIM(internals->active_slaves)); + RTE_ASSERT(active_count < RTE_DIM(internals->active_slaves)); internals->active_slave_count = active_count; if (eth_dev->data->dev_started) { @@ -165,28 +160,12 @@ number_of_sockets(void) return ++sockets; } -static struct rte_pci_id pci_id_table = { - .device_id = PCI_ANY_ID, - .subsystem_device_id = PCI_ANY_ID, - .vendor_id = PCI_ANY_ID, - .subsystem_vendor_id = PCI_ANY_ID, -}; - -static struct eth_driver rte_bond_pmd = { - .pci_drv = { - .name = pmd_bond_driver_name, - .drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_DETACHABLE, - .id_table = &pci_id_table, - }, -}; - int rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) { - struct rte_pci_device *pci_dev = NULL; struct bond_dev_private *internals = NULL; struct rte_eth_dev *eth_dev = NULL; - struct rte_pci_driver *pci_drv = NULL; + uint32_t vlan_filter_bmp_size; /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data @@ -203,14 +182,6 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) goto err; } - pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id); - if (pci_dev == NULL) { - RTE_BOND_LOG(ERR, "Unable to malloc pci dev on socket"); - goto err; - } - - pci_drv = &rte_bond_pmd.pci_drv; - internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id); if (internals == NULL) { RTE_BOND_LOG(ERR, "Unable to malloc internals on socket"); @@ -218,25 +189,16 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) } /* reserve an ethdev entry */ - eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); + eth_dev = rte_eth_dev_allocate(name); if (eth_dev == NULL) { RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev"); goto err; } - pci_dev->numa_node = socket_id; - pci_drv->name = pmd_bond_driver_name; - pci_dev->driver = pci_drv; - - eth_dev->driver = &rte_bond_pmd; eth_dev->data->dev_private = internals; eth_dev->data->nb_rx_queues = (uint16_t)1; eth_dev->data->nb_tx_queues = (uint16_t)1; - TAILQ_INIT(&(eth_dev->link_intr_cbs)); - - eth_dev->data->dev_link.link_status = 0; - eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0, socket_id); if (eth_dev->data->mac_addrs == NULL) { @@ -244,26 +206,19 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) goto err; } - eth_dev->data->dev_started = 0; - eth_dev->data->promiscuous = 0; - eth_dev->data->scattered_rx = 0; - eth_dev->data->all_multicast = 0; - eth_dev->dev_ops = &default_dev_ops; - eth_dev->pci_dev = pci_dev; - 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->drv_name = pmd_bond_drv.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 = 0; + 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; @@ -279,6 +234,8 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) 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; /* Initially allow to choose any offload type */ internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK; @@ -294,10 +251,30 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) 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; err: - rte_free(pci_dev); rte_free(internals); if (eth_dev != NULL) { rte_free(eth_dev->data->mac_addrs); @@ -310,6 +287,7 @@ 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 @@ -320,6 +298,10 @@ rte_eth_bond_free(const char *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); @@ -329,7 +311,9 @@ rte_eth_bond_free(const char *name) eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; - rte_free(eth_dev->pci_dev); + 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); @@ -338,46 +322,77 @@ rte_eth_bond_free(const char *name) return 0; } +static int +slave_vlan_filter_set(uint8_t bonded_port_id, uint8_t slave_port_id) +{ + struct rte_eth_dev *bonded_eth_dev; + struct bond_dev_private *internals; + int found; + int res = 0; + uint64_t slab = 0; + uint32_t pos = 0; + uint16_t first; + + bonded_eth_dev = &rte_eth_devices[bonded_port_id]; + if (bonded_eth_dev->data->dev_conf.rxmode.hw_vlan_filter == 0) + return 0; + + internals = bonded_eth_dev->data->dev_private; + found = rte_bitmap_scan(internals->vlan_filter_bmp, &pos, &slab); + first = pos; + + if (!found) + return 0; + + do { + uint32_t i; + uint64_t mask; + + for (i = 0, mask = 1; + i < RTE_BITMAP_SLAB_BIT_SIZE; + i ++, mask <<= 1) { + if (unlikely(slab & mask)) + res = rte_eth_dev_vlan_filter(slave_port_id, + (uint16_t)pos, 1); + } + found = rte_bitmap_scan(internals->vlan_filter_bmp, + &pos, &slab); + } while (found && first != pos && res == 0); + + return res; +} + static int __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev; struct bond_dev_private *internals; - struct bond_dev_private *temp_internals; struct rte_eth_link link_props; struct rte_eth_dev_info dev_info; - int i, j; - 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; - /* Verify that new slave device is not already a slave of another - * bonded device */ - for (i = rte_eth_dev_count()-1; i >= 0; i--) { - if (valid_bonded_ethdev(&rte_eth_devices[i]) == 0) { - temp_internals = rte_eth_devices[i].data->dev_private; - - for (j = 0; j < temp_internals->slave_count; j++) { - /* Device already a slave of a bonded device */ - if (temp_internals->slaves[j].port_id == slave_port_id) { - RTE_BOND_LOG(ERR, "Slave port %d is already a slave", - slave_port_id); - 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_add(internals, slave_eth_dev); + 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", + slave_port_id); + return -1; + } + + slave_add(internals, slave_eth_dev); /* We need to store slaves reta_size to be able to synchronize RETA for all * slave devices even if its sizes are different. @@ -396,6 +411,7 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) /* Make primary slave */ internals->primary_port = slave_port_id; + internals->current_primary_port = slave_port_id; /* Inherit queues settings from first slave */ internals->nb_rx_queues = slave_eth_dev->data->nb_rx_queues; @@ -408,21 +424,10 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) 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; + } else { - /* Check slave link properties are supported if props are set, - * all slaves must be the same */ - if (internals->link_props_set) { - if (link_properties_valid(&(bonded_eth_dev->data->dev_link), - &(slave_eth_dev->data->dev_link))) { - RTE_BOND_LOG(ERR, - "Slave port %d link speed/duplex not supported", - slave_port_id); - return -1; - } - } else { - link_properties_set(bonded_eth_dev, - &(slave_eth_dev->data->dev_link)); - } 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; @@ -433,6 +438,9 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) 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; } bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf &= @@ -445,6 +453,7 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) 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); RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d", slave_port_id); return -1; @@ -461,9 +470,21 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) if (bonded_eth_dev->data->dev_started) { rte_eth_link_get_nowait(slave_port_id, &link_props); - if (link_props.link_status == 1) - activate_slave(bonded_eth_dev, slave_port_id); + if (link_props.link_status == ETH_LINK_UP) { + if (internals->active_slave_count == 0 && + !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); + } } + + slave_vlan_filter_set(bonded_port_id, slave_port_id); + return 0; } @@ -497,7 +518,7 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; - + struct rte_eth_dev *slave_eth_dev; int i, slave_idx; if (valid_slave_port_id(slave_port_id) != 0) @@ -537,7 +558,9 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) mac_address_set(&rte_eth_devices[slave_port_id], &(internals->slaves[slave_idx].persisted_mac_addr)); - slave_remove(internals, &rte_eth_devices[slave_port_id]); + 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); /* first slave in the active list will be the primary by default, * otherwise use first device in list */ @@ -566,6 +589,8 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) internals->tx_offload_capa = 0; internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK; internals->reta_size = 0; + internals->candidate_max_rx_pktlen = 0; + internals->max_rx_pktlen = 0; } return 0; }