net/bonding: fix RSS key config with extended key length
[dpdk.git] / drivers / net / bonding / rte_eth_bond_pmd.c
index 9bbe129..5cbe890 100644 (file)
@@ -1318,7 +1318,7 @@ bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,
 
        /* Increment reference count on mbufs */
        for (i = 0; i < nb_pkts; i++)
-               rte_mbuf_refcnt_update(bufs[i], num_of_slaves - 1);
+               rte_pktmbuf_refcnt_update(bufs[i], num_of_slaves - 1);
 
        /* Transmit burst on each active slave */
        for (i = 0; i < num_of_slaves; i++) {
@@ -1554,7 +1554,7 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
 }
 
 int
-bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode)
+bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, uint8_t mode)
 {
        struct bond_dev_private *internals;
 
@@ -1678,14 +1678,10 @@ int
 slave_configure(struct rte_eth_dev *bonded_eth_dev,
                struct rte_eth_dev *slave_eth_dev)
 {
-       struct bond_rx_queue *bd_rx_q;
-       struct bond_tx_queue *bd_tx_q;
        uint16_t nb_rx_queues;
        uint16_t nb_tx_queues;
 
        int errval;
-       uint16_t q_id;
-       struct rte_flow_error flow_error;
 
        struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
 
@@ -1713,17 +1709,24 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
                                bonded_eth_dev->data->dev_conf.rxmode.mq_mode;
        }
 
-       if (bonded_eth_dev->data->dev_conf.rxmode.offloads &
-                       RTE_ETH_RX_OFFLOAD_VLAN_FILTER)
-               slave_eth_dev->data->dev_conf.rxmode.offloads |=
-                               RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
-       else
-               slave_eth_dev->data->dev_conf.rxmode.offloads &=
-                               ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
-
        slave_eth_dev->data->dev_conf.rxmode.mtu =
                        bonded_eth_dev->data->dev_conf.rxmode.mtu;
 
+       slave_eth_dev->data->dev_conf.txmode.offloads |=
+               bonded_eth_dev->data->dev_conf.txmode.offloads;
+
+       slave_eth_dev->data->dev_conf.txmode.offloads &=
+               (bonded_eth_dev->data->dev_conf.txmode.offloads |
+               ~internals->tx_offload_capa);
+
+       slave_eth_dev->data->dev_conf.rxmode.offloads |=
+               bonded_eth_dev->data->dev_conf.rxmode.offloads;
+
+       slave_eth_dev->data->dev_conf.rxmode.offloads &=
+               (bonded_eth_dev->data->dev_conf.rxmode.offloads |
+               ~internals->rx_offload_capa);
+
+
        nb_rx_queues = bonded_eth_dev->data->nb_rx_queues;
        nb_tx_queues = bonded_eth_dev->data->nb_tx_queues;
 
@@ -1734,14 +1737,6 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
                }
        }
 
-       errval = rte_eth_dev_set_mtu(slave_eth_dev->data->port_id,
-                                    bonded_eth_dev->data->mtu);
-       if (errval != 0 && errval != -ENOTSUP) {
-               RTE_BOND_LOG(ERR, "rte_eth_dev_set_mtu: port %u, err (%d)",
-                               slave_eth_dev->data->port_id, errval);
-               return errval;
-       }
-
        /* Configure device */
        errval = rte_eth_dev_configure(slave_eth_dev->data->port_id,
                        nb_rx_queues, nb_tx_queues,
@@ -1752,6 +1747,27 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
                return errval;
        }
 
+       errval = rte_eth_dev_set_mtu(slave_eth_dev->data->port_id,
+                                    bonded_eth_dev->data->mtu);
+       if (errval != 0 && errval != -ENOTSUP) {
+               RTE_BOND_LOG(ERR, "rte_eth_dev_set_mtu: port %u, err (%d)",
+                               slave_eth_dev->data->port_id, errval);
+               return errval;
+       }
+       return 0;
+}
+
+int
+slave_start(struct rte_eth_dev *bonded_eth_dev,
+               struct rte_eth_dev *slave_eth_dev)
+{
+       int errval = 0;
+       struct bond_rx_queue *bd_rx_q;
+       struct bond_tx_queue *bd_tx_q;
+       uint16_t q_id;
+       struct rte_flow_error flow_error;
+       struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
+
        /* Setup Rx Queues */
        for (q_id = 0; q_id < bonded_eth_dev->data->nb_rx_queues; q_id++) {
                bd_rx_q = (struct bond_rx_queue *)bonded_eth_dev->data->rx_queues[q_id];
@@ -1799,10 +1815,13 @@ slave_configure(struct rte_eth_dev *bonded_eth_dev,
                        return errval;
                }
 
-               if (internals->mode4.dedicated_queues.flow[slave_eth_dev->data->port_id] != NULL)
-                       rte_flow_destroy(slave_eth_dev->data->port_id,
+               if (internals->mode4.dedicated_queues.flow[slave_eth_dev->data->port_id] != NULL) {
+                       errval = rte_flow_destroy(slave_eth_dev->data->port_id,
                                        internals->mode4.dedicated_queues.flow[slave_eth_dev->data->port_id],
                                        &flow_error);
+                       RTE_BOND_LOG(ERR, "bond_ethdev_8023ad_flow_destroy: port=%d, err (%d)",
+                               slave_eth_dev->data->port_id, errval);
+               }
 
                errval = bond_ethdev_8023ad_flow_set(bonded_eth_dev,
                                slave_eth_dev->data->port_id);
@@ -1994,6 +2013,13 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                                internals->slaves[i].port_id);
                        goto out_err;
                }
+               if (slave_start(eth_dev, slave_ethdev) != 0) {
+                       RTE_BOND_LOG(ERR,
+                               "bonded port (%d) failed to start slave device (%d)",
+                               eth_dev->data->port_id,
+                               internals->slaves[i].port_id);
+                       goto out_err;
+               }
                /* We will need to poll for link status if any slave doesn't
                 * support interrupts
                 */
@@ -2148,8 +2174,7 @@ bond_ethdev_close(struct rte_eth_dev *dev)
         */
        rte_mempool_free(internals->mode6.mempool);
 
-       if (internals->kvlist != NULL)
-               rte_kvargs_free(internals->kvlist);
+       rte_kvargs_free(internals->kvlist);
 
        return 0;
 }
@@ -2684,6 +2709,39 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
        return ret;
 }
 
+static int
+bond_ethdev_promiscuous_update(struct rte_eth_dev *dev)
+{
+       struct bond_dev_private *internals = dev->data->dev_private;
+       uint16_t port_id = internals->current_primary_port;
+
+       switch (internals->mode) {
+       case BONDING_MODE_ROUND_ROBIN:
+       case BONDING_MODE_BALANCE:
+       case BONDING_MODE_BROADCAST:
+       case BONDING_MODE_8023AD:
+               /* As promiscuous mode is propagated to all slaves for these
+                * mode, no need to update for bonding device.
+                */
+               break;
+       case BONDING_MODE_ACTIVE_BACKUP:
+       case BONDING_MODE_TLB:
+       case BONDING_MODE_ALB:
+       default:
+               /* As promiscuous mode is propagated only to primary slave
+                * for these mode. When active/standby switchover, promiscuous
+                * mode should be set to new primary slave according to bonding
+                * device.
+                */
+               if (rte_eth_promiscuous_get(internals->port_id) == 1)
+                       rte_eth_promiscuous_enable(port_id);
+               else
+                       rte_eth_promiscuous_disable(port_id);
+       }
+
+       return 0;
+}
+
 static int
 bond_ethdev_allmulticast_enable(struct rte_eth_dev *eth_dev)
 {
@@ -2797,6 +2855,39 @@ bond_ethdev_allmulticast_disable(struct rte_eth_dev *eth_dev)
        return ret;
 }
 
+static int
+bond_ethdev_allmulticast_update(struct rte_eth_dev *dev)
+{
+       struct bond_dev_private *internals = dev->data->dev_private;
+       uint16_t port_id = internals->current_primary_port;
+
+       switch (internals->mode) {
+       case BONDING_MODE_ROUND_ROBIN:
+       case BONDING_MODE_BALANCE:
+       case BONDING_MODE_BROADCAST:
+       case BONDING_MODE_8023AD:
+               /* As allmulticast mode is propagated to all slaves for these
+                * mode, no need to update for bonding device.
+                */
+               break;
+       case BONDING_MODE_ACTIVE_BACKUP:
+       case BONDING_MODE_TLB:
+       case BONDING_MODE_ALB:
+       default:
+               /* As allmulticast mode is propagated only to primary slave
+                * for these mode. When active/standby switchover, allmulticast
+                * mode should be set to new primary slave according to bonding
+                * device.
+                */
+               if (rte_eth_allmulticast_get(internals->port_id) == 1)
+                       rte_eth_allmulticast_enable(port_id);
+               else
+                       rte_eth_allmulticast_disable(port_id);
+       }
+
+       return 0;
+}
+
 static void
 bond_ethdev_delayed_lsc_propagation(void *arg)
 {
@@ -2886,6 +2977,8 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
                        lsc_flag = 1;
 
                        mac_address_slaves_update(bonded_eth_dev);
+                       bond_ethdev_promiscuous_update(bonded_eth_dev);
+                       bond_ethdev_allmulticast_update(bonded_eth_dev);
                }
 
                activate_slave(bonded_eth_dev, port_id);
@@ -2915,6 +3008,8 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
                        else
                                internals->current_primary_port = internals->primary_port;
                        mac_address_slaves_update(bonded_eth_dev);
+                       bond_ethdev_promiscuous_update(bonded_eth_dev);
+                       bond_ethdev_allmulticast_update(bonded_eth_dev);
                }
        }
 
@@ -3293,7 +3388,7 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
        /* 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 to %d",
+               RTE_BOND_LOG(ERR, "Failed to set bonded device %u mode to %u",
                                 eth_dev->data->port_id, mode);
                goto err;
        }
@@ -3362,8 +3457,10 @@ bond_probe(struct rte_vdev_device *dev)
 
        kvlist = rte_kvargs_parse(rte_vdev_device_args(dev),
                pmd_bond_init_valid_arguments);
-       if (kvlist == NULL)
+       if (kvlist == NULL) {
+               RTE_BOND_LOG(ERR, "Invalid args in %s", rte_vdev_device_args(dev));
                return -1;
+       }
 
        /* Parse link bonding mode */
        if (rte_kvargs_count(kvlist, PMD_BOND_MODE_KVARG) == 1) {
@@ -3498,12 +3595,17 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
 
        /*
         * If RSS is enabled, fill table with default values and
-        * set key to the the value specified in port RSS configuration.
+        * set key to the value specified in port RSS configuration.
         * Fall back to default RSS key if the key is not specified
         */
        if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) {
                struct rte_eth_rss_conf *rss_conf =
                        &dev->data->dev_conf.rx_adv_conf.rss_conf;
+
+               if (internals->rss_key_len == 0) {
+                       internals->rss_key_len = sizeof(default_rss_key);
+               }
+
                if (rss_conf->rss_key != NULL) {
                        if (internals->rss_key_len > rss_conf->rss_key_len) {
                                RTE_BOND_LOG(ERR, "Invalid rss key length(%u)",
@@ -3515,13 +3617,18 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
                               internals->rss_key_len);
                } else {
                        if (internals->rss_key_len > sizeof(default_rss_key)) {
-                               RTE_BOND_LOG(ERR,
-                                      "There is no suitable default hash key");
-                               return -EINVAL;
+                               /*
+                                * If the rss_key includes standard_rss_key and
+                                * extended_hash_key, the rss key length will be
+                                * larger than default rss key length, so it should
+                                * re-calculate the hash key.
+                                */
+                               for (i = 0; i < internals->rss_key_len; i++)
+                                       internals->rss_key[i] = (uint8_t)rte_rand();
+                       } else {
+                               memcpy(internals->rss_key, default_rss_key,
+                                       internals->rss_key_len);
                        }
-
-                       memcpy(internals->rss_key, default_rss_key,
-                              internals->rss_key_len);
                }
 
                for (i = 0; i < RTE_DIM(internals->reta_conf); i++) {
@@ -3765,6 +3872,18 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
                return -1;
        }
 
+       /* configure slaves so we can pass mtu setting */
+       for (i = 0; i < internals->slave_count; i++) {
+               struct rte_eth_dev *slave_ethdev =
+                               &(rte_eth_devices[internals->slaves[i].port_id]);
+               if (slave_configure(dev, slave_ethdev) != 0) {
+                       RTE_BOND_LOG(ERR,
+                               "bonded port (%d) failed to configure slave device (%d)",
+                               dev->data->port_id,
+                               internals->slaves[i].port_id);
+                       return -1;
+               }
+       }
        return 0;
 }