replace alignment attributes
[dpdk.git] / drivers / net / bonding / rte_eth_bond_pmd.c
index 49e38f6..707a0f3 100644 (file)
@@ -21,8 +21,8 @@
 #include <rte_string_fns.h>
 
 #include "rte_eth_bond.h"
-#include "rte_eth_bond_private.h"
-#include "rte_eth_bond_8023ad_private.h"
+#include "eth_bond_private.h"
+#include "eth_bond_8023ad_private.h"
 
 #define REORDER_PERIOD_MS 10
 #define DEFAULT_POLLING_INTERVAL_10_MS (10)
@@ -186,7 +186,15 @@ bond_ethdev_8023ad_flow_verify(struct rte_eth_dev *bond_dev,
                return -1;
        }
 
-       rte_eth_dev_info_get(slave_port, &slave_info);
+       ret = rte_eth_dev_info_get(slave_port, &slave_info);
+       if (ret != 0) {
+               RTE_BOND_LOG(ERR,
+                       "%s: Error during getting device (port %u) info: %s\n",
+                       __func__, slave_port, strerror(-ret));
+
+               return ret;
+       }
+
        if (slave_info.max_rx_queues < bond_dev->data->nb_rx_queues ||
                        slave_info.max_tx_queues < bond_dev->data->nb_tx_queues) {
                RTE_BOND_LOG(ERR,
@@ -204,10 +212,19 @@ bond_8023ad_slow_pkt_hw_filter_supported(uint16_t port_id) {
        struct bond_dev_private *internals = bond_dev->data->dev_private;
        struct rte_eth_dev_info bond_info;
        uint16_t idx;
+       int ret;
 
        /* Verify if all slaves in bonding supports flow director and */
        if (internals->slave_count > 0) {
-               rte_eth_dev_info_get(bond_dev->data->port_id, &bond_info);
+               ret = rte_eth_dev_info_get(bond_dev->data->port_id, &bond_info);
+               if (ret != 0) {
+                       RTE_BOND_LOG(ERR,
+                               "%s: Error during getting device (port %u) info: %s\n",
+                               __func__, bond_dev->data->port_id,
+                               strerror(-ret));
+
+                       return ret;
+               }
 
                internals->mode4.dedicated_queues.rx_qid = bond_info.nb_rx_queues;
                internals->mode4.dedicated_queues.tx_qid = bond_info.nb_tx_queues;
@@ -273,7 +290,8 @@ rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts,
        uint16_t slave_count, idx;
 
        uint8_t collecting;  /* current slave collecting status */
-       const uint8_t promisc = internals->promiscuous_en;
+       const uint8_t promisc = rte_eth_promiscuous_get(internals->port_id);
+       const uint8_t allmulti = rte_eth_allmulticast_get(internals->port_id);
        uint8_t subtype;
        uint16_t i;
        uint16_t j;
@@ -313,8 +331,10 @@ rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts,
                        /* Remove packet from array if:
                         * - it is slow packet but no dedicated rxq is present,
                         * - slave is not in collecting state,
-                        * - bonding interface is not in promiscuous mode and
-                        *   packet is not multicast and address does not match,
+                        * - bonding interface is not in promiscuous mode:
+                        *   - packet is unicast and address does not match,
+                        *   - packet is multicast and bonding interface
+                        *     is not in allmulti,
                         */
                        if (unlikely(
                                (!dedicated_rxq &&
@@ -322,9 +342,11 @@ rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts,
                                                 bufs[j])) ||
                                !collecting ||
                                (!promisc &&
-                                !rte_is_multicast_ether_addr(&hdr->d_addr) &&
-                                !rte_is_same_ether_addr(bond_mac,
-                                                    &hdr->d_addr)))) {
+                                ((rte_is_unicast_ether_addr(&hdr->d_addr) &&
+                                  !rte_is_same_ether_addr(bond_mac,
+                                                      &hdr->d_addr)) ||
+                                 (!allmulti &&
+                                  rte_is_multicast_ether_addr(&hdr->d_addr)))))) {
 
                                if (hdr->ether_type == ether_type_slow_be) {
                                        bond_mode_8023ad_handle_slow_pkt(
@@ -824,8 +846,14 @@ bandwidth_left(uint16_t port_id, uint64_t load, uint8_t update_idx,
                struct bwg_slave *bwg_slave)
 {
        struct rte_eth_link link_status;
+       int ret;
 
-       rte_eth_link_get_nowait(port_id, &link_status);
+       ret = rte_eth_link_get_nowait(port_id, &link_status);
+       if (ret < 0) {
+               RTE_BOND_LOG(ERR, "Slave (port %u) link get failed: %s",
+                            port_id, rte_strerror(-ret));
+               return;
+       }
        uint64_t link_bwg = link_status.link_speed * 1000000ULL / 8;
        if (link_bwg == 0)
                return;
@@ -1893,7 +1921,7 @@ bond_ethdev_primary_set(struct bond_dev_private *internals,
                }
 }
 
-static void
+static int
 bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev);
 
 static int
@@ -1936,10 +1964,6 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                }
        }
 
-       /* If bonded device is configure in promiscuous mode then re-apply config */
-       if (internals->promiscuous_en)
-               bond_ethdev_promiscuous_enable(eth_dev);
-
        if (internals->mode == BONDING_MODE_8023AD) {
                if (internals->mode4.dedicated_queues.enabled == 1) {
                        internals->mode4.dedicated_queues.rx_qid =
@@ -2097,10 +2121,12 @@ bond_ethdev_close(struct rte_eth_dev *dev)
 /* forward declaration */
 static int bond_ethdev_configure(struct rte_eth_dev *dev);
 
-static void
+static int
 bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct bond_dev_private *internals = dev->data->dev_private;
+       struct bond_slave_details slave;
+       int ret;
 
        uint16_t max_nb_rx_queues = UINT16_MAX;
        uint16_t max_nb_tx_queues = UINT16_MAX;
@@ -2122,8 +2148,17 @@ bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                uint16_t idx;
 
                for (idx = 0; idx < internals->slave_count; idx++) {
-                       rte_eth_dev_info_get(internals->slaves[idx].port_id,
-                                       &slave_info);
+                       slave = internals->slaves[idx];
+                       ret = rte_eth_dev_info_get(slave.port_id, &slave_info);
+                       if (ret != 0) {
+                               RTE_BOND_LOG(ERR,
+                                       "%s: Error during getting device (port %u) info: %s\n",
+                                       __func__,
+                                       slave.port_id,
+                                       strerror(-ret));
+
+                               return ret;
+                       }
 
                        if (slave_info.max_rx_queues < max_nb_rx_queues)
                                max_nb_rx_queues = slave_info.max_rx_queues;
@@ -2169,6 +2204,8 @@ bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
 
        dev_info->reta_size = internals->reta_size;
+
+       return 0;
 }
 
 static int
@@ -2327,12 +2364,14 @@ bond_ethdev_slave_link_status_change_monitor(void *cb_arg)
 static int
 bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 {
-       void (*link_update)(uint16_t port_id, struct rte_eth_link *eth_link);
+       int (*link_update)(uint16_t port_id, struct rte_eth_link *eth_link);
 
        struct bond_dev_private *bond_ctx;
        struct rte_eth_link slave_link;
 
+       bool one_link_update_succeeded;
        uint32_t idx;
+       int ret;
 
        bond_ctx = ethdev->data->dev_private;
 
@@ -2364,8 +2403,18 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
                 * packet loss will occur on this slave if transmission at rates
                 * greater than this are attempted
                 */
-               for (idx = 1; idx < bond_ctx->active_slave_count; idx++) {
-                       link_update(bond_ctx->active_slaves[0], &slave_link);
+               for (idx = 0; idx < bond_ctx->active_slave_count; idx++) {
+                       ret = link_update(bond_ctx->active_slaves[idx],
+                                         &slave_link);
+                       if (ret < 0) {
+                               ethdev->data->dev_link.link_speed =
+                                       ETH_SPEED_NUM_NONE;
+                               RTE_BOND_LOG(ERR,
+                                       "Slave (port %u) link get failed: %s",
+                                       bond_ctx->active_slaves[idx],
+                                       rte_strerror(-ret));
+                               return 0;
+                       }
 
                        if (slave_link.link_speed <
                                        ethdev->data->dev_link.link_speed)
@@ -2375,7 +2424,13 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
                break;
        case BONDING_MODE_ACTIVE_BACKUP:
                /* Current primary slave */
-               link_update(bond_ctx->current_primary_port, &slave_link);
+               ret = link_update(bond_ctx->current_primary_port, &slave_link);
+               if (ret < 0) {
+                       RTE_BOND_LOG(ERR, "Slave (port %u) link get failed: %s",
+                               bond_ctx->current_primary_port,
+                               rte_strerror(-ret));
+                       return 0;
+               }
 
                ethdev->data->dev_link.link_speed = slave_link.link_speed;
                break;
@@ -2384,7 +2439,8 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
                                bond_ctx->mode4.slave_link.link_autoneg;
                ethdev->data->dev_link.link_duplex =
                                bond_ctx->mode4.slave_link.link_duplex;
-               /* fall through to update link speed */
+               /* fall through */
+               /* to update link speed */
        case BONDING_MODE_ROUND_ROBIN:
        case BONDING_MODE_BALANCE:
        case BONDING_MODE_TLB:
@@ -2395,13 +2451,28 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
                 * of all the slaves
                 */
                ethdev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+               one_link_update_succeeded = false;
 
                for (idx = 0; idx < bond_ctx->active_slave_count; idx++) {
-                       link_update(bond_ctx->active_slaves[idx], &slave_link);
+                       ret = link_update(bond_ctx->active_slaves[idx],
+                                       &slave_link);
+                       if (ret < 0) {
+                               RTE_BOND_LOG(ERR,
+                                       "Slave (port %u) link get failed: %s",
+                                       bond_ctx->active_slaves[idx],
+                                       rte_strerror(-ret));
+                               continue;
+                       }
 
+                       one_link_update_succeeded = true;
                        ethdev->data->dev_link.link_speed +=
                                        slave_link.link_speed;
                }
+
+               if (!one_link_update_succeeded) {
+                       RTE_BOND_LOG(ERR, "All slaves link get failed");
+                       return 0;
+               }
        }
 
 
@@ -2441,35 +2512,58 @@ bond_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        return 0;
 }
 
-static void
+static int
 bond_ethdev_stats_reset(struct rte_eth_dev *dev)
 {
        struct bond_dev_private *internals = dev->data->dev_private;
        int i;
+       int err;
+       int ret;
 
-       for (i = 0; i < internals->slave_count; i++)
-               rte_eth_stats_reset(internals->slaves[i].port_id);
+       for (i = 0, err = 0; i < internals->slave_count; i++) {
+               ret = rte_eth_stats_reset(internals->slaves[i].port_id);
+               if (ret != 0)
+                       err = ret;
+       }
+
+       return err;
 }
 
-static void
+static int
 bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
 {
        struct bond_dev_private *internals = eth_dev->data->dev_private;
        int i;
-
-       internals->promiscuous_en = 1;
+       int ret = 0;
+       uint16_t port_id;
 
        switch (internals->mode) {
        /* Promiscuous mode is propagated to all slaves */
        case BONDING_MODE_ROUND_ROBIN:
        case BONDING_MODE_BALANCE:
        case BONDING_MODE_BROADCAST:
-               for (i = 0; i < internals->slave_count; i++)
-                       rte_eth_promiscuous_enable(internals->slaves[i].port_id);
-               break;
-       /* In mode4 promiscus mode is managed when slave is added/removed */
-       case BONDING_MODE_8023AD:
+       case BONDING_MODE_8023AD: {
+               unsigned int slave_ok = 0;
+
+               for (i = 0; i < internals->slave_count; i++) {
+                       port_id = internals->slaves[i].port_id;
+
+                       ret = rte_eth_promiscuous_enable(port_id);
+                       if (ret != 0)
+                               RTE_BOND_LOG(ERR,
+                                       "Failed to enable promiscuous mode for port %u: %s",
+                                       port_id, rte_strerror(-ret));
+                       else
+                               slave_ok++;
+               }
+               /*
+                * Report success if operation is successful on at least
+                * on one slave. Otherwise return last error code.
+                */
+               if (slave_ok > 0)
+                       ret = 0;
                break;
+       }
        /* Promiscuous mode is propagated only to primary slave */
        case BONDING_MODE_ACTIVE_BACKUP:
        case BONDING_MODE_TLB:
@@ -2478,29 +2572,58 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
                /* Do not touch promisc when there cannot be primary ports */
                if (internals->slave_count == 0)
                        break;
-               rte_eth_promiscuous_enable(internals->current_primary_port);
+               port_id = internals->current_primary_port;
+               ret = rte_eth_promiscuous_enable(port_id);
+               if (ret != 0)
+                       RTE_BOND_LOG(ERR,
+                               "Failed to enable promiscuous mode for port %u: %s",
+                               port_id, rte_strerror(-ret));
        }
+
+       return ret;
 }
 
-static void
+static int
 bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
 {
        struct bond_dev_private *internals = dev->data->dev_private;
        int i;
-
-       internals->promiscuous_en = 0;
+       int ret = 0;
+       uint16_t port_id;
 
        switch (internals->mode) {
        /* Promiscuous mode is propagated to all slaves */
        case BONDING_MODE_ROUND_ROBIN:
        case BONDING_MODE_BALANCE:
        case BONDING_MODE_BROADCAST:
-               for (i = 0; i < internals->slave_count; i++)
-                       rte_eth_promiscuous_disable(internals->slaves[i].port_id);
-               break;
-       /* In mode4 promiscus mode is set managed when slave is added/removed */
-       case BONDING_MODE_8023AD:
+       case BONDING_MODE_8023AD: {
+               unsigned int slave_ok = 0;
+
+               for (i = 0; i < internals->slave_count; i++) {
+                       port_id = internals->slaves[i].port_id;
+
+                       if (internals->mode == BONDING_MODE_8023AD &&
+                           bond_mode_8023ad_ports[port_id].forced_rx_flags ==
+                                       BOND_8023AD_FORCED_PROMISC) {
+                               slave_ok++;
+                               continue;
+                       }
+                       ret = rte_eth_promiscuous_disable(port_id);
+                       if (ret != 0)
+                               RTE_BOND_LOG(ERR,
+                                       "Failed to disable promiscuous mode for port %u: %s",
+                                       port_id, rte_strerror(-ret));
+                       else
+                               slave_ok++;
+               }
+               /*
+                * Report success if operation is successful on at least
+                * on one slave. Otherwise return last error code.
+                */
+               if (slave_ok > 0)
+                       ret = 0;
                break;
+       }
        /* Promiscuous mode is propagated only to primary slave */
        case BONDING_MODE_ACTIVE_BACKUP:
        case BONDING_MODE_TLB:
@@ -2509,8 +2632,128 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
                /* Do not touch promisc when there cannot be primary ports */
                if (internals->slave_count == 0)
                        break;
-               rte_eth_promiscuous_disable(internals->current_primary_port);
+               port_id = internals->current_primary_port;
+               ret = rte_eth_promiscuous_disable(port_id);
+               if (ret != 0)
+                       RTE_BOND_LOG(ERR,
+                               "Failed to disable promiscuous mode for port %u: %s",
+                               port_id, rte_strerror(-ret));
        }
+
+       return ret;
+}
+
+static int
+bond_ethdev_allmulticast_enable(struct rte_eth_dev *eth_dev)
+{
+       struct bond_dev_private *internals = eth_dev->data->dev_private;
+       int i;
+       int ret = 0;
+       uint16_t port_id;
+
+       switch (internals->mode) {
+       /* allmulti mode is propagated to all slaves */
+       case BONDING_MODE_ROUND_ROBIN:
+       case BONDING_MODE_BALANCE:
+       case BONDING_MODE_BROADCAST:
+       case BONDING_MODE_8023AD: {
+               unsigned int slave_ok = 0;
+
+               for (i = 0; i < internals->slave_count; i++) {
+                       port_id = internals->slaves[i].port_id;
+
+                       ret = rte_eth_allmulticast_enable(port_id);
+                       if (ret != 0)
+                               RTE_BOND_LOG(ERR,
+                                       "Failed to enable allmulti mode for port %u: %s",
+                                       port_id, rte_strerror(-ret));
+                       else
+                               slave_ok++;
+               }
+               /*
+                * Report success if operation is successful on at least
+                * on one slave. Otherwise return last error code.
+                */
+               if (slave_ok > 0)
+                       ret = 0;
+               break;
+       }
+       /* allmulti mode is propagated only to primary slave */
+       case BONDING_MODE_ACTIVE_BACKUP:
+       case BONDING_MODE_TLB:
+       case BONDING_MODE_ALB:
+       default:
+               /* Do not touch allmulti when there cannot be primary ports */
+               if (internals->slave_count == 0)
+                       break;
+               port_id = internals->current_primary_port;
+               ret = rte_eth_allmulticast_enable(port_id);
+               if (ret != 0)
+                       RTE_BOND_LOG(ERR,
+                               "Failed to enable allmulti mode for port %u: %s",
+                               port_id, rte_strerror(-ret));
+       }
+
+       return ret;
+}
+
+static int
+bond_ethdev_allmulticast_disable(struct rte_eth_dev *eth_dev)
+{
+       struct bond_dev_private *internals = eth_dev->data->dev_private;
+       int i;
+       int ret = 0;
+       uint16_t port_id;
+
+       switch (internals->mode) {
+       /* allmulti mode is propagated to all slaves */
+       case BONDING_MODE_ROUND_ROBIN:
+       case BONDING_MODE_BALANCE:
+       case BONDING_MODE_BROADCAST:
+       case BONDING_MODE_8023AD: {
+               unsigned int slave_ok = 0;
+
+               for (i = 0; i < internals->slave_count; i++) {
+                       uint16_t port_id = internals->slaves[i].port_id;
+
+                       if (internals->mode == BONDING_MODE_8023AD &&
+                           bond_mode_8023ad_ports[port_id].forced_rx_flags ==
+                                       BOND_8023AD_FORCED_ALLMULTI)
+                               continue;
+
+                       ret = rte_eth_allmulticast_disable(port_id);
+                       if (ret != 0)
+                               RTE_BOND_LOG(ERR,
+                                       "Failed to disable allmulti mode for port %u: %s",
+                                       port_id, rte_strerror(-ret));
+                       else
+                               slave_ok++;
+               }
+               /*
+                * Report success if operation is successful on at least
+                * on one slave. Otherwise return last error code.
+                */
+               if (slave_ok > 0)
+                       ret = 0;
+               break;
+       }
+       /* allmulti mode is propagated only to primary slave */
+       case BONDING_MODE_ACTIVE_BACKUP:
+       case BONDING_MODE_TLB:
+       case BONDING_MODE_ALB:
+       default:
+               /* Do not touch allmulti when there cannot be primary ports */
+               if (internals->slave_count == 0)
+                       break;
+               port_id = internals->current_primary_port;
+               ret = rte_eth_allmulticast_disable(port_id);
+               if (ret != 0)
+                       RTE_BOND_LOG(ERR,
+                               "Failed to disable allmulti mode for port %u: %s",
+                               port_id, rte_strerror(-ret));
+       }
+
+       return ret;
 }
 
 static void
@@ -2531,6 +2774,7 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
        struct bond_dev_private *internals;
        struct rte_eth_link link;
        int rc = -1;
+       int ret;
 
        uint8_t lsc_flag = 0;
        int valid_slave = 0;
@@ -2571,8 +2815,11 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
        active_pos = find_slave_by_id(internals->active_slaves,
                        internals->active_slave_count, port_id);
 
-       rte_eth_link_get_nowait(port_id, &link);
-       if (link.link_status) {
+       ret = rte_eth_link_get_nowait(port_id, &link);
+       if (ret < 0)
+               RTE_BOND_LOG(ERR, "Slave (port %u) link get failed", port_id);
+
+       if (ret == 0 && link.link_status) {
                if (active_pos < internals->active_slave_count)
                        goto link_update;
 
@@ -2907,6 +3154,8 @@ const struct eth_dev_ops default_dev_ops = {
        .stats_reset          = bond_ethdev_stats_reset,
        .promiscuous_enable   = bond_ethdev_promiscuous_enable,
        .promiscuous_disable  = bond_ethdev_promiscuous_disable,
+       .allmulticast_enable  = bond_ethdev_allmulticast_enable,
+       .allmulticast_disable = bond_ethdev_allmulticast_disable,
        .reta_update          = bond_ethdev_rss_reta_update,
        .reta_query           = bond_ethdev_rss_reta_query,
        .rss_hash_update      = bond_ethdev_rss_hash_update,