bond: fix vlan flag interpretation
[dpdk.git] / lib / librte_pmd_bond / rte_eth_bond_api.c
index f146bda..4ab3267 100644 (file)
@@ -31,6 +31,8 @@
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <string.h>
+
 #include <rte_mbuf.h>
 #include <rte_malloc.h>
 #include <rte_ethdev.h>
@@ -38,6 +40,7 @@
 
 #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)
 
@@ -104,6 +107,53 @@ valid_slave_port_id(uint8_t port_id)
        return 0;
 }
 
+void
+activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id)
+{
+       struct bond_dev_private *internals = eth_dev->data->dev_private;
+
+       if (internals->mode == BONDING_MODE_8023AD)
+               bond_mode_8023ad_activate_slave(eth_dev, port_id);
+
+       RTE_VERIFY(internals->active_slave_count <
+                       (RTE_DIM(internals->active_slaves) - 1));
+
+       internals->active_slaves[internals->active_slave_count] = port_id;
+       internals->active_slave_count++;
+}
+
+void
+deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id)
+{
+       uint8_t slave_pos;
+       struct bond_dev_private *internals = eth_dev->data->dev_private;
+       uint8_t active_count = internals->active_slave_count;
+
+       if (internals->mode == BONDING_MODE_8023AD) {
+               bond_mode_8023ad_stop(eth_dev);
+               bond_mode_8023ad_deactivate_slave(eth_dev, port_id);
+       }
+
+       slave_pos = find_slave_by_id(internals->active_slaves, active_count,
+                       port_id);
+
+       /* If slave was not at the end of the list
+        * shift active slaves up active array list */
+       if (slave_pos < active_count) {
+               active_count--;
+               memmove(internals->active_slaves + slave_pos,
+                               internals->active_slaves + slave_pos + 1,
+                               (active_count - slave_pos) *
+                                       sizeof(internals->active_slaves[0]));
+       }
+
+       RTE_VERIFY(active_count < RTE_DIM(internals->active_slaves));
+       internals->active_slave_count = active_count;
+
+       if (eth_dev->data->dev_started && internals->mode == BONDING_MODE_8023AD)
+               bond_mode_8023ad_start(eth_dev);
+}
+
 uint8_t
 number_of_sockets(void)
 {
@@ -164,7 +214,7 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
                goto err;
        }
        pci_id_table = rte_zmalloc_socket(name, sizeof(*pci_id_table), 0, socket_id);
-       if (pci_drv == NULL) {
+       if (pci_id_table == NULL) {
                RTE_BOND_LOG(ERR, "Unable to malloc pci_id_table on socket");
                goto err;
        }
@@ -216,17 +266,13 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
        eth_dev->dev_ops = &default_dev_ops;
        eth_dev->pci_dev = pci_dev;
 
-       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;
-       }
-
        rte_spinlock_init(&internals->lock);
 
        internals->port_id = eth_dev->data->port_id;
+       internals->mode = BONDING_MODE_INVALID;
        internals->current_primary_port = 0;
        internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
+       internals->xmit_hash = xmit_l2_hash;
        internals->user_defined_mac = 0;
        internals->link_props_set = 0;
 
@@ -238,10 +284,20 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
 
        internals->slave_count = 0;
        internals->active_slave_count = 0;
+       internals->rx_offload_capa = 0;
+       internals->tx_offload_capa = 0;
 
        memset(internals->active_slaves, 0, sizeof(internals->active_slaves));
        memset(internals->slaves, 0, sizeof(internals->slaves));
 
+       /* 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;
+       }
+
        return eth_dev->data->port_id;
 
 err:
@@ -265,6 +321,7 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
        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;
 
@@ -296,6 +353,9 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
        /* Add slave details to bonded device */
        slave_add(internals, slave_eth_dev);
 
+       memset(&dev_info, 0, sizeof(dev_info));
+       rte_eth_dev_info_get(slave_port_id, &dev_info);
+
        if (internals->slave_count < 1) {
                /* if MAC is not user defined then use MAC of first slave add to
                 * bonded device */
@@ -308,6 +368,11 @@ __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;
+
+               /* 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;
+
        } else {
                /* Check slave link properties are supported if props are set,
                 * all slaves must be the same */
@@ -323,6 +388,8 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
                        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->slave_count++;
@@ -349,14 +416,12 @@ __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
                rte_eth_link_get_nowait(slave_port_id, &link_props);
 
                 if (link_props.link_status == 1)
-                       internals->active_slaves[internals->active_slave_count++] =
-                                       slave_port_id;
+                       activate_slave(bonded_eth_dev, slave_port_id);
        }
        return 0;
 
 }
 
-
 int
 rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
 {
@@ -381,31 +446,26 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
        return retval;
 }
 
-
 static int
 __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;
 
-       int i, slave_idx = -1;
+       int i, slave_idx;
 
        if (valid_slave_port_id(slave_port_id) != 0)
                return -1;
 
-       internals = rte_eth_devices[bonded_port_id].data->dev_private;
+       bonded_eth_dev = &rte_eth_devices[bonded_port_id];
+       internals = bonded_eth_dev->data->dev_private;
 
        /* first remove from active slave list */
-       for (i = 0; i < internals->active_slave_count; i++) {
-               if (internals->active_slaves[i] == slave_port_id)
-                       slave_idx = i;
+       slave_idx = find_slave_by_id(internals->active_slaves,
+               internals->active_slave_count, slave_port_id);
 
-               /* shift active slaves up active array list */
-               if (slave_idx >= 0 && i < (internals->active_slave_count - 1))
-                       internals->active_slaves[i] = internals->active_slaves[i+1];
-       }
-
-       if (slave_idx >= 0)
-               internals->active_slave_count--;
+       if (slave_idx < internals->active_slave_count)
+               deactivate_slave(bonded_eth_dev, slave_port_id);
 
        slave_idx = -1;
        /* now find in slave list */
@@ -455,7 +515,10 @@ __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
                        memset(rte_eth_devices[bonded_port_id].data->mac_addrs, 0,
                                        sizeof(*(rte_eth_devices[bonded_port_id].data->mac_addrs)));
        }
-
+       if (internals->slave_count == 0) {
+               internals->rx_offload_capa = 0;
+               internals->tx_offload_capa = 0;
+       }
        return 0;
 }
 
@@ -539,11 +602,12 @@ rte_eth_bond_primary_get(uint8_t bonded_port_id)
 
        return internals->current_primary_port;
 }
+
 int
 rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len)
 {
        struct bond_dev_private *internals;
-       int i;
+       uint8_t i;
 
        if (valid_bonded_port_id(bonded_port_id) != 0)
                return -1;
@@ -651,9 +715,16 @@ 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;
+               break;
        case BALANCE_XMIT_POLICY_LAYER23:
+               internals->balance_xmit_policy = policy;
+               internals->xmit_hash = xmit_l23_hash;
+               break;
        case BALANCE_XMIT_POLICY_LAYER34:
                internals->balance_xmit_policy = policy;
+               internals->xmit_hash = xmit_l34_hash;
                break;
 
        default:
@@ -675,7 +746,6 @@ rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id)
        return internals->balance_xmit_policy;
 }
 
-
 int
 rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms)
 {
@@ -731,7 +801,6 @@ rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id)
        return internals->link_down_delay_ms;
 }
 
-
 int
 rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms)