This patch redesigns the API to set the link speed/s configure
for an ethernet port. Specifically:

- it allows to define a set of advertised speeds for
  auto-negociation.
- it allows to disable link auto-negociation (single fixed speed).
- default: auto-negociate all supported speeds.

Other changes:

* Added utility MACROs ETH_SPEED_NUM_XXX with the numeric
  values of all supported link speeds, in Mbps.
* Converted link_speed to uint32_t to accomodate 100G speeds
  and beyond (bug).
* Added autoneg flag in struct rte_eth_link to indicate if
  link speed was a result of auto-negociation or was fixed
  by configuration.
* Added utility function to convert numeric speeds to bitmap
  fields.
* Added rte_eth_speed_to_bm_flag() to version map.

Signed-off-by: Marc Sune <marcdevel at gmail.com>
---
 app/test-pipeline/init.c                  |   2 +-
 app/test-pmd/cmdline.c                    | 124 +++++++++++++++---------------
 app/test-pmd/config.c                     |   4 +-
 app/test/virtual_pmd.c                    |   4 +-
 drivers/net/af_packet/rte_eth_af_packet.c |   5 +-
 drivers/net/bnx2x/bnx2x_ethdev.c          |   8 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c |  14 ++--
 drivers/net/cxgbe/base/t4_hw.c            |   8 +-
 drivers/net/cxgbe/cxgbe_ethdev.c          |   2 +-
 drivers/net/e1000/em_ethdev.c             | 116 ++++++++++++++--------------
 drivers/net/e1000/igb_ethdev.c            | 111 +++++++++++++-------------
 drivers/net/fm10k/fm10k_ethdev.c          |   8 +-
 drivers/net/i40e/i40e_ethdev.c            |  73 +++++++++---------
 drivers/net/i40e/i40e_ethdev_vf.c         |  11 +--
 drivers/net/ixgbe/ixgbe_ethdev.c          |  78 ++++++++-----------
 drivers/net/mlx4/mlx4.c                   |   6 +-
 drivers/net/mlx5/mlx5_ethdev.c            |  10 +--
 drivers/net/mpipe/mpipe_tilegx.c          |   6 +-
 drivers/net/nfp/nfp_net.c                 |   4 +-
 drivers/net/null/rte_eth_null.c           |   5 +-
 drivers/net/pcap/rte_eth_pcap.c           |   9 ++-
 drivers/net/ring/rte_eth_ring.c           |   5 +-
 drivers/net/virtio/virtio_ethdev.c        |   2 +-
 drivers/net/virtio/virtio_ethdev.h        |   2 -
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |   5 +-
 drivers/net/xenvirt/rte_eth_xenvirt.c     |   5 +-
 examples/ip_pipeline/config_parse.c       |   3 +-
 lib/librte_ether/rte_ethdev.c             |  49 ++++++++++++
 lib/librte_ether/rte_ethdev.h             | 113 +++++++++++++++++----------
 lib/librte_ether/rte_ether_version.map    |   6 ++
 30 files changed, 448 insertions(+), 350 deletions(-)

diff --git a/app/test-pipeline/init.c b/app/test-pipeline/init.c
index db2196b..6a69fe2 100644
--- a/app/test-pipeline/init.c
+++ b/app/test-pipeline/init.c
@@ -200,7 +200,7 @@ app_ports_check_link(void)
                port = (uint8_t) app.ports[i];
                memset(&link, 0, sizeof(link));
                rte_eth_link_get_nowait(port, &link);
-               RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n",
+               RTE_LOG(INFO, USER1, "Port %u (%d Gbps) %s\n",
                        port,
                        link.link_speed / 1000,
                        link.link_status ? "UP" : "DOWN");
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 52e9f5f..57ad25f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -956,14 +956,65 @@ struct cmd_config_speed_all {
        cmdline_fixed_string_t value2;
 };

+static int
+parse_and_check_speed_duplex(char *value1, char *value2, uint32_t *link_speed)
+{
+
+       int duplex;
+
+       if (!strcmp(value2, "half")) {
+               duplex = 0;
+       } else if (!strcmp(value2, "full")) {
+               duplex = 1;
+       } else if (!strcmp(value2, "auto")) {
+               duplex = 1;
+       } else {
+               printf("Unknown parameter\n");
+               return -1;
+       }
+
+       if (!strcmp(value1, "10")) {
+               *link_speed = (duplex) ? ETH_LINK_SPEED_10M :
+                                                       ETH_LINK_SPEED_10M_HD;
+       } else if (!strcmp(value1, "100")) {
+               *link_speed = (duplex) ? ETH_LINK_SPEED_100M :
+                                                       ETH_LINK_SPEED_100M_HD;
+       } else if (!strcmp(value1, "1000")) {
+               if (!duplex)
+                       goto invalid_speed_param;
+               *link_speed = ETH_LINK_SPEED_1G;
+       } else if (!strcmp(value1, "10000")) {
+               if (!duplex)
+                       goto invalid_speed_param;
+               *link_speed = ETH_LINK_SPEED_10G;
+       } else if (!strcmp(value1, "40000")) {
+               if (!duplex)
+                       goto invalid_speed_param;
+               *link_speed = ETH_LINK_SPEED_40G;
+       } else if (!strcmp(value1, "auto")) {
+               if (!duplex)
+                       goto invalid_speed_param;
+               *link_speed = ETH_LINK_SPEED_AUTONEG;
+       } else {
+               printf("Unknown parameter\n");
+               return -1;
+       }
+
+       return 0;
+
+invalid_speed_param:
+
+       printf("Invalid speed parameter\n");
+       return -1;
+}
+
 static void
 cmd_config_speed_all_parsed(void *parsed_result,
                        __attribute__((unused)) struct cmdline *cl,
                        __attribute__((unused)) void *data)
 {
        struct cmd_config_speed_all *res = parsed_result;
-       uint16_t link_speed = ETH_LINK_SPEED_AUTONEG;
-       uint16_t link_duplex = 0;
+       uint32_t link_speed;
        portid_t pid;

        if (!all_ports_stopped()) {
@@ -971,40 +1022,18 @@ cmd_config_speed_all_parsed(void *parsed_result,
                return;
        }

-       if (!strcmp(res->value1, "10"))
-               link_speed = ETH_LINK_SPEED_10;
-       else if (!strcmp(res->value1, "100"))
-               link_speed = ETH_LINK_SPEED_100;
-       else if (!strcmp(res->value1, "1000"))
-               link_speed = ETH_LINK_SPEED_1000;
-       else if (!strcmp(res->value1, "10000"))
-               link_speed = ETH_LINK_SPEED_10G;
-       else if (!strcmp(res->value1, "40000"))
-               link_speed = ETH_LINK_SPEED_40G;
-       else if (!strcmp(res->value1, "auto"))
-               link_speed = ETH_LINK_SPEED_AUTONEG;
-       else {
-               printf("Unknown parameter\n");
+       if (parse_and_check_speed_duplex(res->value1,
+                                               res->value2,
+                                               &link_speed) < 0)
                return;
-       }
-
-       if (!strcmp(res->value2, "half"))
-               link_duplex = ETH_LINK_HALF_DUPLEX;
-       else if (!strcmp(res->value2, "full"))
-               link_duplex = ETH_LINK_FULL_DUPLEX;
-       else if (!strcmp(res->value2, "auto"))
-               link_duplex = ETH_LINK_AUTONEG_DUPLEX;
-       else {
-               printf("Unknown parameter\n");
-               return;
-       }

        FOREACH_PORT(pid, ports) {
-               ports[pid].dev_conf.link_speed = link_speed;
-               ports[pid].dev_conf.link_duplex = link_duplex;
+               ports[pid].dev_conf.link_speeds = link_speed;
        }

        cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+
+       return;
 }

 cmdline_parse_token_string_t cmd_config_speed_all_port =
@@ -1059,8 +1088,7 @@ cmd_config_speed_specific_parsed(void *parsed_result,
                                __attribute__((unused)) void *data)
 {
        struct cmd_config_speed_specific *res = parsed_result;
-       uint16_t link_speed = ETH_LINK_SPEED_AUTONEG;
-       uint16_t link_duplex = 0;
+       uint32_t link_speed;

        if (!all_ports_stopped()) {
                printf("Please stop all ports first\n");
@@ -1070,36 +1098,12 @@ cmd_config_speed_specific_parsed(void *parsed_result,
        if (port_id_is_invalid(res->id, ENABLED_WARN))
                return;

-       if (!strcmp(res->value1, "10"))
-               link_speed = ETH_LINK_SPEED_10;
-       else if (!strcmp(res->value1, "100"))
-               link_speed = ETH_LINK_SPEED_100;
-       else if (!strcmp(res->value1, "1000"))
-               link_speed = ETH_LINK_SPEED_1000;
-       else if (!strcmp(res->value1, "10000"))
-               link_speed = ETH_LINK_SPEED_10000;
-       else if (!strcmp(res->value1, "40000"))
-               link_speed = ETH_LINK_SPEED_40G;
-       else if (!strcmp(res->value1, "auto"))
-               link_speed = ETH_LINK_SPEED_AUTONEG;
-       else {
-               printf("Unknown parameter\n");
+       if (parse_and_check_speed_duplex(res->value1,
+                                               res->value2,
+                                               &link_speed) < 0)
                return;
-       }
-
-       if (!strcmp(res->value2, "half"))
-               link_duplex = ETH_LINK_HALF_DUPLEX;
-       else if (!strcmp(res->value2, "full"))
-               link_duplex = ETH_LINK_FULL_DUPLEX;
-       else if (!strcmp(res->value2, "auto"))
-               link_duplex = ETH_LINK_AUTONEG_DUPLEX;
-       else {
-               printf("Unknown parameter\n");
-               return;
-       }

-       ports[res->id].dev_conf.link_speed = link_speed;
-       ports[res->id].dev_conf.link_duplex = link_duplex;
+       ports[res->id].dev_conf.link_speeds = link_speed;

        cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
 }
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 0062484..d43f64f 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -2241,7 +2241,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t 
queue_idx, uint16_t rate)
                return 1;
        rte_eth_link_get_nowait(port_id, &link);
        if (rate > link.link_speed) {
-               printf("Invalid rate value:%u bigger than link speed: %u\n",
+               printf("Invalid rate value:%u bigger than link speed: %d\n",
                        rate, link.link_speed);
                return 1;
        }
@@ -2266,7 +2266,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t 
rate, uint64_t q_msk)
                return 1;
        rte_eth_link_get_nowait(port_id, &link);
        if (rate > link.link_speed) {
-               printf("Invalid rate value:%u bigger than link speed: %u\n",
+               printf("Invalid rate value:%u bigger than link speed: %d\n",
                        rate, link.link_speed);
                return 1;
        }
diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index a538c8a..3c4040b 100644
--- a/app/test/virtual_pmd.c
+++ b/app/test/virtual_pmd.c
@@ -603,8 +603,8 @@ virtual_ethdev_create(const char *name, struct ether_addr 
*mac_addr,

        TAILQ_INIT(&(eth_dev->link_intr_cbs));

-       eth_dev->data->dev_link.link_status = 0;
-       eth_dev->data->dev_link.link_speed = ETH_LINK_SPEED_10000;
+       eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+       eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_10G;
        eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;

        eth_dev->data->mac_addrs = rte_zmalloc(name, ETHER_ADDR_LEN, 0);
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c 
b/drivers/net/af_packet/rte_eth_af_packet.c
index 767f36b..5db1db2 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -116,9 +116,10 @@ static const char *valid_arguments[] = {
 static const char *drivername = "AF_PACKET PMD";

 static struct rte_eth_link pmd_link = {
-       .link_speed = 10000,
+       .link_speed = ETH_SPEED_NUM_10G,
        .link_duplex = ETH_LINK_FULL_DUPLEX,
-       .link_status = 0
+       .link_status = ETH_LINK_DOWN,
+       .link_autoneg = ETH_LINK_SPEED_NEG
 };

 static uint16_t
diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index b547ac3..efefae6 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -45,8 +45,12 @@ bnx2x_link_update(struct rte_eth_dev *dev)
                        dev->data->dev_link.link_duplex = ETH_LINK_HALF_DUPLEX;
                        break;
                default:
-                       dev->data->dev_link.link_duplex = 
ETH_LINK_AUTONEG_DUPLEX;
+                       break;
        }
+
+       dev->data->dev_link.link_autoneg = ~(dev->data->dev_conf.link_speeds &
+                                               ETH_LINK_SPEED_NO_AUTONEG);
+
        dev->data->dev_link.link_status = sc->link_vars.link_up;
 }

@@ -347,7 +351,7 @@ bnx2x_dev_infos_get(struct rte_eth_dev *dev, __rte_unused 
struct rte_eth_dev_inf
        dev_info->min_rx_bufsize = BNX2X_MIN_RX_BUF_SIZE;
        dev_info->max_rx_pktlen  = BNX2X_MAX_RX_PKT_LEN;
        dev_info->max_mac_addrs  = BNX2X_MAX_MAC_ADDRS;
-       dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_20G;
+       dev_info->speed_capa = ETH_LINK_SPEED_10G | ETH_LINK_SPEED_20G;
 }

 static void
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.c 
b/drivers/net/bonding/rte_eth_bond_8023ad.c
index b3b30f6..3b446e1 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad.c
+++ b/drivers/net/bonding/rte_eth_bond_8023ad.c
@@ -708,25 +708,25 @@ link_speed_key(uint16_t speed) {
        uint16_t key_speed;

        switch (speed) {
-       case ETH_LINK_SPEED_AUTONEG:
+       case ETH_SPEED_NUM_NONE:
                key_speed = 0x00;
                break;
-       case ETH_LINK_SPEED_10:
+       case ETH_SPEED_NUM_10M:
                key_speed = BOND_LINK_SPEED_KEY_10M;
                break;
-       case ETH_LINK_SPEED_100:
+       case ETH_SPEED_NUM_100M:
                key_speed = BOND_LINK_SPEED_KEY_100M;
                break;
-       case ETH_LINK_SPEED_1000:
+       case ETH_SPEED_NUM_1G:
                key_speed = BOND_LINK_SPEED_KEY_1000M;
                break;
-       case ETH_LINK_SPEED_10G:
+       case ETH_SPEED_NUM_10G:
                key_speed = BOND_LINK_SPEED_KEY_10G;
                break;
-       case ETH_LINK_SPEED_20G:
+       case ETH_SPEED_NUM_20G:
                key_speed = BOND_LINK_SPEED_KEY_20G;
                break;
-       case ETH_LINK_SPEED_40G:
+       case ETH_SPEED_NUM_40G:
                key_speed = BOND_LINK_SPEED_KEY_40G;
                break;
        default:
diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 884d2cf..79af806 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -2159,13 +2159,13 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 
*rpl)
                if (stat & F_FW_PORT_CMD_TXPAUSE)
                        fc |= PAUSE_TX;
                if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
-                       speed = ETH_LINK_SPEED_100;
+                       speed = ETH_SPEED_NUM_100M;
                else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-                       speed = ETH_LINK_SPEED_1000;
+                       speed = ETH_SPEED_NUM_1G;
                else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-                       speed = ETH_LINK_SPEED_10000;
+                       speed = ETH_SPEED_NUM_10G;
                else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
-                       speed = ETH_LINK_SPEED_40G;
+                       speed = ETH_SPEED_NUM_40G;

                for_each_port(adap, i) {
                        pi = adap2pinfo(adap, i);
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 203e119..05b954d 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -171,7 +171,7 @@ static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev,

        device_info->rx_desc_lim = cxgbe_desc_lim;
        device_info->tx_desc_lim = cxgbe_desc_lim;
-       device_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
+       device_info->speed_capa = ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G;
 }

 static void cxgbe_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index e40dc37..12c4c63 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -509,6 +509,9 @@ eth_em_start(struct rte_eth_dev *dev)
        struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
        int ret, mask;
        uint32_t intr_vector = 0;
+       uint32_t *speeds;
+       int num_speeds;
+       bool autoneg;

        PMD_INIT_FUNC_TRACE();

@@ -583,56 +586,46 @@ eth_em_start(struct rte_eth_dev *dev)
        E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);

        /* Setup link speed and duplex */
-       switch (dev->data->dev_conf.link_speed) {
-       case ETH_LINK_SPEED_AUTONEG:
-               if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
-               else if (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_HALF_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX;
-               else if (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_FULL_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX;
-               else
-                       goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_10:
-               if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_10_SPEED;
-               else if (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_HALF_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_10_HALF;
-               else if (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_FULL_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_10_FULL;
-               else
-                       goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_100:
-               if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_100_SPEED;
-               else if (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_HALF_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_100_HALF;
-               else if (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_FULL_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_100_FULL;
-               else
+       speeds = &dev->data->dev_conf.link_speeds;
+       if (*speeds == ETH_LINK_SPEED_AUTONEG) {
+               hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
+       } else {
+               num_speeds = 0;
+               autoneg = ~(*speeds & ETH_LINK_SPEED_NO_AUTONEG);
+
+               /* Reset */
+               hw->phy.autoneg_advertised = 0;
+
+               if (*speeds & ~(ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M |
+                               ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M |
+                               ETH_LINK_SPEED_1G)) {
+                       num_speeds = -1;
                        goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_1000:
-               if ((dev->data->dev_conf.link_duplex ==
-                               ETH_LINK_AUTONEG_DUPLEX) ||
-                       (dev->data->dev_conf.link_duplex ==
-                                       ETH_LINK_FULL_DUPLEX))
-                       hw->phy.autoneg_advertised = ADVERTISE_1000_FULL;
-               else
+               }
+               if (*speeds & ETH_LINK_SPEED_10M_HD) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_10_HALF;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_10M) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_10_FULL;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_100M_HD) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_100_HALF;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_100M) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_100_FULL;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_1G) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_1000_FULL;
+                       num_speeds++;
+               }
+               if (num_speeds == 0 || (!autoneg && (num_speeds > 2)))
                        goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_10000:
-       default:
-               goto error_invalid_config;
        }
+
        e1000_setup_link(hw);

        if (rte_intr_allow_others(intr_handle)) {
@@ -665,9 +658,8 @@ eth_em_start(struct rte_eth_dev *dev)
        return 0;

 error_invalid_config:
-       PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u",
-                    dev->data->dev_conf.link_speed,
-                    dev->data->dev_conf.link_duplex, dev->data->port_id);
+       PMD_INIT_LOG(ERR, "Invalid advertised speeds (%u) for port %u",
+                    dev->data->dev_conf.link_speeds, dev->data->port_id);
        em_dev_clear_queues(dev);
        return -EINVAL;
 }
@@ -1024,11 +1016,11 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
                .nb_align = EM_TXD_ALIGN,
        };

-       dev_info->speed_capa = ETH_SPEED_CAP_10M_HD |
-                                       ETH_SPEED_CAP_10M_FD |
-                                       ETH_SPEED_CAP_100M_HD |
-                                       ETH_SPEED_CAP_100M_FD |
-                                       ETH_SPEED_CAP_1G;
+       dev_info->speed_capa = ETH_LINK_SPEED_10M_HD |
+                                       ETH_LINK_SPEED_10M |
+                                       ETH_LINK_SPEED_100M_HD |
+                                       ETH_LINK_SPEED_100M |
+                                       ETH_LINK_SPEED_1G;
 }

 /* return 0 means link status changed, -1 means not changed */
@@ -1077,13 +1069,17 @@ eth_em_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)

        /* Now we check if a transition has happened */
        if (link_check && (link.link_status == 0)) {
-               hw->mac.ops.get_link_up_info(hw, &link.link_speed,
-                       &link.link_duplex);
-               link.link_status = 1;
+               uint16_t duplex, speed;
+               hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+
+               link.link_duplex = (duplex) ? ETH_LINK_FULL_DUPLEX :
+                                               ETH_LINK_HALF_DUPLEX;
+               link.link_speed = speed;
+               link.link_status = ETH_LINK_UP;
        } else if (!link_check && (link.link_status == 1)) {
                link.link_speed = 0;
-               link.link_duplex = 0;
-               link.link_status = 0;
+               link.link_duplex = ETH_LINK_HALF_DUPLEX;
+               link.link_status = ETH_LINK_DOWN;
        }
        rte_em_dev_atomic_write_link_status(dev, &link);

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 7eac8ea..6682df5 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1119,6 +1119,9 @@ eth_igb_start(struct rte_eth_dev *dev)
        int ret, mask;
        uint32_t intr_vector = 0;
        uint32_t ctrl_ext;
+       uint32_t *speeds;
+       int num_speeds;
+       bool autoneg;

        PMD_INIT_FUNC_TRACE();

@@ -1219,48 +1222,46 @@ eth_igb_start(struct rte_eth_dev *dev)
        }

        /* Setup link speed and duplex */
-       switch (dev->data->dev_conf.link_speed) {
-       case ETH_LINK_SPEED_AUTONEG:
-               if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
-               else if (dev->data->dev_conf.link_duplex == 
ETH_LINK_HALF_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX;
-               else if (dev->data->dev_conf.link_duplex == 
ETH_LINK_FULL_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX;
-               else
-                       goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_10:
-               if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_10_SPEED;
-               else if (dev->data->dev_conf.link_duplex == 
ETH_LINK_HALF_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_10_HALF;
-               else if (dev->data->dev_conf.link_duplex == 
ETH_LINK_FULL_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_10_FULL;
-               else
-                       goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_100:
-               if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
-                       hw->phy.autoneg_advertised = E1000_ALL_100_SPEED;
-               else if (dev->data->dev_conf.link_duplex == 
ETH_LINK_HALF_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_100_HALF;
-               else if (dev->data->dev_conf.link_duplex == 
ETH_LINK_FULL_DUPLEX)
-                       hw->phy.autoneg_advertised = ADVERTISE_100_FULL;
-               else
+       speeds = &dev->data->dev_conf.link_speeds;
+       if (*speeds == ETH_LINK_SPEED_AUTONEG) {
+               hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
+       } else {
+               num_speeds = 0;
+               autoneg = ~(*speeds & ETH_LINK_SPEED_NO_AUTONEG);
+
+               /* Reset */
+               hw->phy.autoneg_advertised = 0;
+
+               if (*speeds & ~(ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M |
+                               ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M |
+                               ETH_LINK_SPEED_1G)) {
+                       num_speeds = -1;
                        goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_1000:
-               if ((dev->data->dev_conf.link_duplex == 
ETH_LINK_AUTONEG_DUPLEX) ||
-                               (dev->data->dev_conf.link_duplex == 
ETH_LINK_FULL_DUPLEX))
-                       hw->phy.autoneg_advertised = ADVERTISE_1000_FULL;
-               else
+               }
+               if (*speeds & ETH_LINK_SPEED_10M_HD) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_10_HALF;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_10M) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_10_FULL;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_100M_HD) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_100_HALF;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_100M) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_100_FULL;
+                       num_speeds++;
+               }
+               if (*speeds & ETH_LINK_SPEED_1G) {
+                       hw->phy.autoneg_advertised |= ADVERTISE_1000_FULL;
+                       num_speeds++;
+               }
+               if (num_speeds == 0 || (!autoneg && (num_speeds > 2)))
                        goto error_invalid_config;
-               break;
-       case ETH_LINK_SPEED_10000:
-       default:
-               goto error_invalid_config;
        }
+
        e1000_setup_link(hw);

        if (rte_intr_allow_others(intr_handle)) {
@@ -1292,9 +1293,8 @@ eth_igb_start(struct rte_eth_dev *dev)
        return 0;

 error_invalid_config:
-       PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u",
-                    dev->data->dev_conf.link_speed,
-                    dev->data->dev_conf.link_duplex, dev->data->port_id);
+       PMD_INIT_LOG(ERR, "Invalid advertised speeds (%u) for port %u",
+                    dev->data->dev_conf.link_speeds, dev->data->port_id);
        igb_dev_clear_queues(dev);
        return -EINVAL;
 }
@@ -1909,11 +1909,11 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
        dev_info->rx_desc_lim = rx_desc_lim;
        dev_info->tx_desc_lim = tx_desc_lim;

-       dev_info->speed_capa = ETH_SPEED_CAP_10M_HD |
-                                       ETH_SPEED_CAP_10M_FD |
-                                       ETH_SPEED_CAP_100M_HD |
-                                       ETH_SPEED_CAP_100M_FD |
-                                       ETH_SPEED_CAP_1G;
+       dev_info->speed_capa = ETH_LINK_SPEED_10M_HD |
+                                       ETH_LINK_SPEED_10M |
+                                       ETH_LINK_SPEED_100M_HD |
+                                       ETH_LINK_SPEED_100M |
+                                       ETH_LINK_SPEED_1G;
 }

 static void
@@ -2023,13 +2023,20 @@ eth_igb_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)

        /* Now we check if a transition has happened */
        if (link_check) {
-               hw->mac.ops.get_link_up_info(hw, &link.link_speed,
-                                         &link.link_duplex);
-               link.link_status = 1;
+               uint16_t duplex, speed;
+               hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+
+               link.link_duplex = (duplex) ? ETH_LINK_FULL_DUPLEX :
+                                                       ETH_LINK_HALF_DUPLEX;
+               link.link_speed = speed;
+               link.link_status = ETH_LINK_UP;
+               link.link_autoneg = ~(dev->data->dev_conf.link_speeds &
+                                               ETH_LINK_SPEED_NO_AUTONEG);
        } else if (!link_check) {
                link.link_speed = 0;
-               link.link_duplex = 0;
-               link.link_status = 0;
+               link.link_duplex = ETH_LINK_HALF_DUPLEX;
+               link.link_status = ETH_LINK_DOWN;
+               link.link_autoneg = ETH_LINK_SPEED_FIXED;
        }
        rte_igb_dev_atomic_write_link_status(dev, &link);

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 2e6ec60..f44818f 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1172,7 +1172,7 @@ fm10k_link_update(struct rte_eth_dev *dev,
         * is no 50Gbps Ethernet. */
        dev->data->dev_link.link_speed  = 0;
        dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
-       dev->data->dev_link.link_status = 1;
+       dev->data->dev_link.link_status = ETH_LINK_UP;

        return 0;
 }
@@ -1334,9 +1334,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
                .nb_align = FM10K_MULT_TX_DESC,
        };

-       dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_2_5G |
-                                       ETH_SPEED_CAP_10G | ETH_SPEED_CAP_25G |
-                                       ETH_SPEED_CAP_40G | ETH_SPEED_CAP_100G;
+       dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_2_5G |
+                               ETH_LINK_SPEED_10G | ETH_LINK_SPEED_25G |
+                               ETH_LINK_SPEED_40G | ETH_LINK_SPEED_100G;
 }

 static int
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 78a0cbd..e440dcf 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1326,27 +1326,20 @@ i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 }

 static inline uint8_t
-i40e_parse_link_speed(uint16_t eth_link_speed)
+i40e_parse_link_speeds(uint16_t link_speeds)
 {
        uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN;

-       switch (eth_link_speed) {
-       case ETH_LINK_SPEED_40G:
-               link_speed = I40E_LINK_SPEED_40GB;
-               break;
-       case ETH_LINK_SPEED_20G:
-               link_speed = I40E_LINK_SPEED_20GB;
-               break;
-       case ETH_LINK_SPEED_10G:
-               link_speed = I40E_LINK_SPEED_10GB;
-               break;
-       case ETH_LINK_SPEED_1000:
-               link_speed = I40E_LINK_SPEED_1GB;
-               break;
-       case ETH_LINK_SPEED_100:
-               link_speed = I40E_LINK_SPEED_100MB;
-               break;
-       }
+       if (link_speeds & ETH_LINK_SPEED_40G)
+               link_speed |= I40E_LINK_SPEED_40GB;
+       if (link_speeds & ETH_LINK_SPEED_20G)
+               link_speed |= I40E_LINK_SPEED_20GB;
+       if (link_speeds & ETH_LINK_SPEED_10G)
+               link_speed |= I40E_LINK_SPEED_10GB;
+       if (link_speeds & ETH_LINK_SPEED_1G)
+               link_speed |= I40E_LINK_SPEED_1GB;
+       if (link_speeds & ETH_LINK_SPEED_100M)
+               link_speed |= I40E_LINK_SPEED_100MB;

        return link_speed;
 }
@@ -1372,9 +1365,9 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct rte_eth_conf *conf = &dev->data->dev_conf;

-       speed = i40e_parse_link_speed(conf->link_speed);
+       speed = i40e_parse_link_speeds(conf->link_speeds);
        abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
-       if (conf->link_speed == ETH_LINK_SPEED_AUTONEG)
+       if (conf->link_speeds & ETH_LINK_SPEED_AUTONEG)
                abilities |= I40E_AQ_PHY_AN_ENABLED;
        else
                abilities |= I40E_AQ_PHY_LINK_ENABLED;
@@ -1394,10 +1387,8 @@ i40e_dev_start(struct rte_eth_dev *dev)

        hw->adapter_stopped = 0;

-       if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) &&
-               (dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) {
-               PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu",
-                            dev->data->dev_conf.link_duplex,
+       if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_NO_AUTONEG) {
+               PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; 
autonegociation disabled",
                             dev->data->port_id);
                return -EINVAL;
        }
@@ -1470,6 +1461,13 @@ i40e_dev_start(struct rte_eth_dev *dev)
        }

        /* Apply link configure */
+       if (dev->data->dev_conf.link_speeds & ~(ETH_LINK_SPEED_100M |
+                               ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
+                               ETH_LINK_SPEED_20G | ETH_LINK_SPEED_40G)) {
+               PMD_DRV_LOG(ERR, "Invalid link setting");
+               goto err_up;
+       }
+
        ret = i40e_apply_link_speed(dev);
        if (I40E_SUCCESS != ret) {
                PMD_DRV_LOG(ERR, "Fail to apply link setting");
@@ -1713,7 +1711,7 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
                /* Get link status information from hardware */
                status = i40e_aq_get_link_info(hw, false, &link_status, NULL);
                if (status != I40E_SUCCESS) {
-                       link.link_speed = ETH_LINK_SPEED_100;
+                       link.link_speed = ETH_SPEED_NUM_100M;
                        link.link_duplex = ETH_LINK_FULL_DUPLEX;
                        PMD_DRV_LOG(ERR, "Failed to get link info");
                        goto out;
@@ -1735,25 +1733,28 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
        /* Parse the link status */
        switch (link_status.link_speed) {
        case I40E_LINK_SPEED_100MB:
-               link.link_speed = ETH_LINK_SPEED_100;
+               link.link_speed = ETH_SPEED_NUM_100M;
                break;
        case I40E_LINK_SPEED_1GB:
-               link.link_speed = ETH_LINK_SPEED_1000;
+               link.link_speed = ETH_SPEED_NUM_1G;
                break;
        case I40E_LINK_SPEED_10GB:
-               link.link_speed = ETH_LINK_SPEED_10G;
+               link.link_speed = ETH_SPEED_NUM_10G;
                break;
        case I40E_LINK_SPEED_20GB:
-               link.link_speed = ETH_LINK_SPEED_20G;
+               link.link_speed = ETH_SPEED_NUM_20G;
                break;
        case I40E_LINK_SPEED_40GB:
-               link.link_speed = ETH_LINK_SPEED_40G;
+               link.link_speed = ETH_SPEED_NUM_40G;
                break;
        default:
-               link.link_speed = ETH_LINK_SPEED_100;
+               link.link_speed = ETH_SPEED_NUM_100M;
                break;
        }

+       link.link_autoneg = ~(dev->data->dev_conf.link_speeds &
+                                               ETH_LINK_SPEED_NO_AUTONEG);
+
 out:
        rte_i40e_dev_atomic_write_link_status(dev, &link);
        if (link.link_status == old.link_status)
@@ -2308,10 +2309,10 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)

        if (i40e_is_40G_device(hw->device_id))
                /* For XL710 */
-               dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
+               dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G;
        else
                /* For X710 */
-               dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
+               dev_info->speed_capa = ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G;

 }

@@ -7835,15 +7836,15 @@ i40e_start_timecounters(struct rte_eth_dev *dev)
        rte_i40e_dev_atomic_read_link_status(dev, &link);

        switch (link.link_speed) {
-       case ETH_LINK_SPEED_40G:
+       case ETH_SPEED_NUM_40G:
                tsync_inc_l = I40E_PTP_40GB_INCVAL & 0xFFFFFFFF;
                tsync_inc_h = I40E_PTP_40GB_INCVAL >> 32;
                break;
-       case ETH_LINK_SPEED_10G:
+       case ETH_SPEED_NUM_10G:
                tsync_inc_l = I40E_PTP_10GB_INCVAL & 0xFFFFFFFF;
                tsync_inc_h = I40E_PTP_10GB_INCVAL >> 32;
                break;
-       case ETH_LINK_SPEED_1000:
+       case ETH_SPEED_NUM_1G:
                tsync_inc_l = I40E_PTP_1GB_INCVAL & 0xFFFFFFFF;
                tsync_inc_h = I40E_PTP_1GB_INCVAL >> 32;
                break;
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c 
b/drivers/net/i40e/i40e_ethdev_vf.c
index 13c5b3d..dd8f1e2 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1911,13 +1911,14 @@ i40evf_dev_link_update(struct rte_eth_dev *dev,
         * DPDK pf host provide interfacet to acquire link status
         * while Linux driver does not
         */
-       if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
+       if (vf->version_major == I40E_DPDK_VERSION_MAJOR) {
                i40evf_get_link_status(dev, &new_link);
-       else {
+       } else {
                /* Always assume it's up, for Linux driver PF host */
-               new_link.link_duplex = ETH_LINK_AUTONEG_DUPLEX;
-               new_link.link_speed  = ETH_LINK_SPEED_10000;
-               new_link.link_status = 1;
+               new_link.link_speed  = ETH_SPEED_NUM_10G;
+               new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+               new_link.link_autoneg = ETH_LINK_SPEED_NEG;
+               new_link.link_status = ETH_LINK_UP;
        }
        i40evf_dev_atomic_write_link_status(dev, &new_link);

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 7e29c18..4fa07b6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1979,14 +1979,13 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        int mask = 0;
        int status;
        uint16_t vf, idx;
+       uint32_t *link_speeds;

        PMD_INIT_FUNC_TRACE();

        /* IXGBE devices don't support half duplex */
-       if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) &&
-                       (dev->data->dev_conf.link_duplex != 
ETH_LINK_FULL_DUPLEX)) {
-               PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu",
-                            dev->data->dev_conf.link_duplex,
+       if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_NO_AUTONEG) {
+               PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; 
autonegociation disabled",
                             dev->data->port_id);
                return -EINVAL;
        }
@@ -2076,32 +2075,22 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        if (err)
                goto error;

-       switch(dev->data->dev_conf.link_speed) {
-       case ETH_LINK_SPEED_AUTONEG:
-               speed = (hw->mac.type != ixgbe_mac_82598EB) ?
-                               IXGBE_LINK_SPEED_82599_AUTONEG :
-                               IXGBE_LINK_SPEED_82598_AUTONEG;
-               break;
-       case ETH_LINK_SPEED_100:
-               /*
-                * Invalid for 82598 but error will be detected by
-                * ixgbe_setup_link()
-                */
-               speed = IXGBE_LINK_SPEED_100_FULL;
-               break;
-       case ETH_LINK_SPEED_1000:
-               speed = IXGBE_LINK_SPEED_1GB_FULL;
-               break;
-       case ETH_LINK_SPEED_10000:
-               speed = IXGBE_LINK_SPEED_10GB_FULL;
-               break;
-       default:
-               PMD_INIT_LOG(ERR, "Invalid link_speed (%hu) for port %hhu",
-                            dev->data->dev_conf.link_speed,
-                            dev->data->port_id);
+       link_speeds = &dev->data->dev_conf.link_speeds;
+       if (*link_speeds & ~(ETH_LINK_SPEED_100M | ETH_LINK_SPEED_1G |
+                                                       ETH_LINK_SPEED_10G)) {
+               PMD_INIT_LOG(ERR, "Invalid link setting");
                goto error;
        }

+       speed = 0x0;
+
+       if (*link_speeds & ETH_LINK_SPEED_10G)
+               speed |= IXGBE_LINK_SPEED_10GB_FULL;
+       if (*link_speeds & ETH_LINK_SPEED_1G)
+               speed |= IXGBE_LINK_SPEED_1GB_FULL;
+       if (*link_speeds & ETH_LINK_SPEED_100M)
+               speed |= IXGBE_LINK_SPEED_100_FULL;
+
        err = ixgbe_setup_link(hw, speed, link_up);
        if (err)
                goto error;
@@ -2828,15 +2817,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
        dev_info->reta_size = ixgbe_reta_size_get(hw->mac.type);
        dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;

-       dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
+       dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G;

        if (hw->mac.type == ixgbe_mac_X540 ||
            hw->mac.type == ixgbe_mac_X540_vf ||
            hw->mac.type == ixgbe_mac_X550 ||
-           hw->mac.type == ixgbe_mac_X550_vf)
+           hw->mac.type == ixgbe_mac_X550_vf) {

-               dev_info->speed_capa |= ETH_SPEED_CAP_100M_FD /*|
-                                       ETH_SPEED_CAP_100M_HD*/;
+               dev_info->speed_capa |= ETH_LINK_SPEED_100M /*|
+                                       ETH_LINK_SPEED_100M_HD*/;
+       }
 }

 static void
@@ -2903,9 +2893,9 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)
        int link_up;
        int diag;

-       link.link_status = 0;
+       link.link_status = ETH_LINK_DOWN;
        link.link_speed = 0;
-       link.link_duplex = 0;
+       link.link_duplex = ETH_LINK_HALF_DUPLEX;
        memset(&old, 0, sizeof(old));
        rte_ixgbe_dev_atomic_read_link_status(dev, &old);

@@ -2918,8 +2908,8 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)
                diag = ixgbe_check_link(hw, &link_speed, &link_up, 1);

        if (diag != 0) {
-               link.link_speed = ETH_LINK_SPEED_100;
-               link.link_duplex = ETH_LINK_HALF_DUPLEX;
+               link.link_speed = ETH_SPEED_NUM_100M;
+               link.link_duplex = ETH_LINK_FULL_DUPLEX;
                rte_ixgbe_dev_atomic_write_link_status(dev, &link);
                if (link.link_status == old.link_status)
                        return -1;
@@ -2932,26 +2922,26 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)
                        return -1;
                return 0;
        }
-       link.link_status = 1;
+       link.link_status = ETH_LINK_UP;
        link.link_duplex = ETH_LINK_FULL_DUPLEX;

        switch (link_speed) {
        default:
        case IXGBE_LINK_SPEED_UNKNOWN:
-               link.link_duplex = ETH_LINK_HALF_DUPLEX;
-               link.link_speed = ETH_LINK_SPEED_100;
+               link.link_duplex = ETH_LINK_FULL_DUPLEX;
+               link.link_speed = ETH_SPEED_NUM_100M;
                break;

        case IXGBE_LINK_SPEED_100_FULL:
-               link.link_speed = ETH_LINK_SPEED_100;
+               link.link_speed = ETH_SPEED_NUM_100M;
                break;

        case IXGBE_LINK_SPEED_1GB_FULL:
-               link.link_speed = ETH_LINK_SPEED_1000;
+               link.link_speed = ETH_SPEED_NUM_1G;
                break;

        case IXGBE_LINK_SPEED_10GB_FULL:
-               link.link_speed = ETH_LINK_SPEED_10000;
+               link.link_speed = ETH_SPEED_NUM_10G;
                break;
        }
        rte_ixgbe_dev_atomic_write_link_status(dev, &link);
@@ -5725,15 +5715,15 @@ ixgbe_start_timecounters(struct rte_eth_dev *dev)
        rte_ixgbe_dev_atomic_read_link_status(dev, &link);

        switch (link.link_speed) {
-       case ETH_LINK_SPEED_100:
+       case ETH_SPEED_NUM_100M:
                incval = IXGBE_INCVAL_100;
                shift = IXGBE_INCVAL_SHIFT_100;
                break;
-       case ETH_LINK_SPEED_1000:
+       case ETH_SPEED_NUM_1G:
                incval = IXGBE_INCVAL_1GB;
                shift = IXGBE_INCVAL_SHIFT_1GB;
                break;
-       case ETH_LINK_SPEED_10000:
+       case ETH_SPEED_NUM_10G:
        default:
                incval = IXGBE_INCVAL_10GB;
                shift = IXGBE_INCVAL_SHIFT_10GB;
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index c5688a7..01c3a5c 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -4265,8 +4265,8 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *info)
        if (priv_get_ifname(priv, &ifname) == 0)
                info->if_index = if_nametoindex(ifname);

-       info->speed_capa = ETH_SPEED_CAP_10G |ETH_SPEED_CAP_40G |
-                                       ETH_SPEED_CAP_56G;
+       info->speed_capa = ETH_LINK_SPEED_10G |ETH_LINK_SPEED_40G |
+                                       ETH_LINK_SPEED_56G;

        priv_unlock(priv);
 }
@@ -4636,6 +4636,8 @@ mlx4_link_update_unlocked(struct rte_eth_dev *dev, int 
wait_to_complete)
                dev_link.link_speed = link_speed;
        dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ?
                                ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX);
+       dev_link.link_autoneg = ~(dev->data->dev_conf.link_speeds &
+                                               ETH_LINK_SPEED_NO_AUTONEG);
        if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) {
                /* Link status changed. */
                dev->data->dev_link = dev_link;
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index 9c997c5..48de24e 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -524,11 +524,11 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *info)
         * The API should be updated to solve this problem. */
        info->reta_size = priv->ind_table_max_size;

-       info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G |
-                                       ETH_SPEED_CAP_25G |
-                                       ETH_SPEED_CAP_40G |
-                                       ETH_SPEED_CAP_50G |
-                                       ETH_SPEED_CAP_100G;
+       info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
+                                               ETH_LINK_SPEED_25G |
+                                               ETH_LINK_SPEED_40G |
+                                               ETH_LINK_SPEED_50G |
+                                               ETH_LINK_SPEED_100G;

        priv_unlock(priv);
 }
diff --git a/drivers/net/mpipe/mpipe_tilegx.c b/drivers/net/mpipe/mpipe_tilegx.c
index 04f3c9f..ecb69b1 100644
--- a/drivers/net/mpipe/mpipe_tilegx.c
+++ b/drivers/net/mpipe/mpipe_tilegx.c
@@ -388,14 +388,16 @@ mpipe_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)

                speed = state & GXIO_MPIPE_LINK_SPEED_MASK;

+               new.link_autoneg = ~(dev->data->dev_conf.link_speeds &
+                                               ETH_LINK_SPEED_NO_AUTONEG);
                if (speed == GXIO_MPIPE_LINK_1G) {
                        new.link_speed = ETH_LINK_SPEED_1000;
                        new.link_duplex = ETH_LINK_FULL_DUPLEX;
-                       new.link_status = 1;
+                       new.link_status = ETH_LINK_UP;
                } else if (speed == GXIO_MPIPE_LINK_10G) {
                        new.link_speed = ETH_LINK_SPEED_10000;
                        new.link_duplex = ETH_LINK_FULL_DUPLEX;
-                       new.link_status = 1;
+                       new.link_status = ETH_LINK_UP;
                }

                rc = mpipe_link_compare(&old, &new);
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 98a957a..adde1a2 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -831,7 +831,7 @@ nfp_net_link_update(struct rte_eth_dev *dev, __rte_unused 
int wait_to_complete)

        link.link_duplex = ETH_LINK_FULL_DUPLEX;
        /* Other cards can limit the tx and rx rate per VF */
-       link.link_speed = ETH_LINK_SPEED_40G;
+       link.link_speed = ETH_SPEED_NUM_40G;

        if (old.link_status != link.link_status) {
                nfp_net_dev_atomic_write_link_status(dev, &link);
@@ -1072,7 +1072,7 @@ nfp_net_infos_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
        dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
        dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;

-       dev_info->speed_capa = ETH_SPEED_CAP_50G | ETH_SPEED_CAP_100G;
+       dev_info->speed_capa = ETH_LINK_SPEED_50G | ETH_LINK_SPEED_100G;
 }

 static uint32_t
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 77fc988..55e1fc8 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -93,9 +93,10 @@ struct pmd_internals {
 static struct ether_addr eth_addr = { .addr_bytes = {0} };
 static const char *drivername = "Null PMD";
 static struct rte_eth_link pmd_link = {
-       .link_speed = 10000,
+       .link_speed = ETH_SPEED_NUM_10G,
        .link_duplex = ETH_LINK_FULL_DUPLEX,
-       .link_status = 0
+       .link_status = ETH_LINK_DOWN,
+       .link_autoneg = ETH_LINK_SPEED_NEG,
 };

 static uint16_t
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index f9230eb..650b521 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -125,9 +125,10 @@ static int open_single_iface(const char *iface, pcap_t 
**pcap);
 static struct ether_addr eth_addr = { .addr_bytes = { 0, 0, 0, 0x1, 0x2, 0x3 } 
};
 static const char *drivername = "Pcap PMD";
 static struct rte_eth_link pmd_link = {
-               .link_speed = 10000,
+               .link_speed = ETH_SPEED_NUM_10G,
                .link_duplex = ETH_LINK_FULL_DUPLEX,
-               .link_status = 0
+               .link_status = ETH_LINK_DOWN,
+               .link_autoneg = ETH_LINK_SPEED_FIXED,
 };

 static int
@@ -430,7 +431,7 @@ eth_dev_start(struct rte_eth_dev *dev)

 status_up:

-       dev->data->dev_link.link_status = 1;
+       dev->data->dev_link.link_status = ETH_LINK_UP;
        return 0;
 }

@@ -481,7 +482,7 @@ eth_dev_stop(struct rte_eth_dev *dev)
        }

 status_down:
-       dev->data->dev_link.link_status = 0;
+       dev->data->dev_link.link_status = ETH_LINK_DOWN;
 }

 static int
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index d92b088..043175a 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -71,9 +71,10 @@ struct pmd_internals {

 static const char *drivername = "Rings PMD";
 static struct rte_eth_link pmd_link = {
-               .link_speed = 10000,
+               .link_speed = ETH_SPEED_NUM_10G,
                .link_duplex = ETH_LINK_FULL_DUPLEX,
-               .link_status = 0
+               .link_status = ETH_LINK_DOWN,
+               .link_autoneg = ETH_LINK_SPEED_NEG
 };

 static uint16_t
diff --git a/drivers/net/virtio/virtio_ethdev.c 
b/drivers/net/virtio/virtio_ethdev.c
index caa970c..12e71af 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1381,7 +1381,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, 
__rte_unused int wait_to_complet
        memset(&link, 0, sizeof(link));
        virtio_dev_atomic_read_link_status(dev, &link);
        old = link;
-       link.link_duplex = FULL_DUPLEX;
+       link.link_duplex = ETH_LINK_FULL_DUPLEX;
        link.link_speed  = SPEED_10G;

        if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) {
diff --git a/drivers/net/virtio/virtio_ethdev.h 
b/drivers/net/virtio/virtio_ethdev.h
index fed9571..66423a0 100644
--- a/drivers/net/virtio/virtio_ethdev.h
+++ b/drivers/net/virtio/virtio_ethdev.h
@@ -42,8 +42,6 @@
 #define SPEED_100      100
 #define SPEED_1000     1000
 #define SPEED_10G      10000
-#define HALF_DUPLEX    1
-#define FULL_DUPLEX    2

 #ifndef PAGE_SIZE
 #define PAGE_SIZE 4096
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c 
b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index c363bf6..2bb6ee9 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -736,9 +736,10 @@ vmxnet3_dev_link_update(struct rte_eth_dev *dev, 
__attribute__((unused)) int wai
        ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);

        if (ret & 0x1) {
-               link.link_status = 1;
+               link.link_status = ETH_LINK_UP;
                link.link_duplex = ETH_LINK_FULL_DUPLEX;
-               link.link_speed = ETH_LINK_SPEED_10000;
+               link.link_speed = ETH_SPEED_NUM_10G;
+               link.link_autoneg = ETH_LINK_SPEED_FIXED;
        }

        vmxnet3_dev_atomic_write_link_status(dev, &link);
diff --git a/drivers/net/xenvirt/rte_eth_xenvirt.c 
b/drivers/net/xenvirt/rte_eth_xenvirt.c
index 3f31806..0fcf5d3 100644
--- a/drivers/net/xenvirt/rte_eth_xenvirt.c
+++ b/drivers/net/xenvirt/rte_eth_xenvirt.c
@@ -70,9 +70,10 @@ static int virtio_idx = 0;
 static const char *drivername = "xen virtio PMD";

 static struct rte_eth_link pmd_link = {
-               .link_speed = 10000,
+               .link_speed = ETH_SPEED_NUM_10G,
                .link_duplex = ETH_LINK_FULL_DUPLEX,
-               .link_status = 0
+               .link_status = ETH_LINK_DOWN,
+               .link_autoneg = ETH_LINK_SPEED_FIXED
 };

 static void
diff --git a/examples/ip_pipeline/config_parse.c 
b/examples/ip_pipeline/config_parse.c
index 1bedbe4..c581d41 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -84,8 +84,7 @@ static const struct app_link_params link_params_default = {
        .mac_addr = 0,

        .conf = {
-               .link_speed = 0,
-               .link_duplex = 0,
+               .link_speeds = 0,
                .rxmode = {
                        .mq_mode = ETH_MQ_RX_NONE,

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1257965..d42b021 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -863,6 +863,55 @@ rte_eth_dev_tx_queue_config(struct rte_eth_dev *dev, 
uint16_t nb_queues)
 }

 int
+rte_eth_speed_to_bm_flag(uint32_t speed, int duplex, uint32_t *flag)
+{
+       switch (speed) {
+       case ETH_SPEED_NUM_10M:
+               *flag = (duplex) ? ETH_LINK_SPEED_10M :
+                                                       ETH_LINK_SPEED_10M_HD;
+               break;
+       case ETH_SPEED_NUM_100M:
+               *flag = (duplex) ? ETH_LINK_SPEED_100M :
+                                                       ETH_LINK_SPEED_100M_HD;
+               break;
+       case ETH_SPEED_NUM_1G:
+               *flag = ETH_LINK_SPEED_1G;
+               break;
+       case ETH_SPEED_NUM_2_5G:
+               *flag = ETH_LINK_SPEED_2_5G;
+               break;
+       case ETH_SPEED_NUM_5G:
+               *flag = ETH_LINK_SPEED_5G;
+               break;
+       case ETH_SPEED_NUM_10G:
+               *flag = ETH_LINK_SPEED_10G;
+               break;
+       case ETH_SPEED_NUM_20G:
+               *flag = ETH_LINK_SPEED_20G;
+               break;
+       case ETH_SPEED_NUM_25G:
+               *flag = ETH_LINK_SPEED_25G;
+               break;
+       case ETH_SPEED_NUM_40G:
+               *flag = ETH_LINK_SPEED_40G;
+               break;
+       case ETH_SPEED_NUM_50G:
+               *flag = ETH_LINK_SPEED_50G;
+               break;
+       case ETH_SPEED_NUM_56G:
+               *flag = ETH_LINK_SPEED_56G;
+               break;
+       case ETH_SPEED_NUM_100G:
+               *flag = ETH_LINK_SPEED_100G;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int
 rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
                      const struct rte_eth_conf *dev_conf)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 83ddbb7..14a0438 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -242,26 +242,59 @@ struct rte_eth_stats {
 };

 /**
+ * Device supported speeds bitmap flags
+ */
+#define ETH_LINK_SPEED_AUTONEG         (0 << 0)  /*< Autonegociate (all 
speeds)  */
+#define ETH_LINK_SPEED_NO_AUTONEG      (1 << 0)  /*< Disable autoneg (fixed 
speed)  */
+#define ETH_LINK_SPEED_10M_HD          (1 << 1)  /*< 10 Mbps half-duplex */
+#define ETH_LINK_SPEED_10M             (1 << 2)  /*< 10 Mbps full-duplex */
+#define ETH_LINK_SPEED_100M_HD         (1 << 3)  /*< 100 Mbps half-duplex */
+#define ETH_LINK_SPEED_100M            (1 << 4)  /*< 100 Mbps full-duplex */
+#define ETH_LINK_SPEED_1G              (1 << 5)  /*< 1 Gbps */
+#define ETH_LINK_SPEED_2_5G            (1 << 6)  /*< 2.5 Gbps */
+#define ETH_LINK_SPEED_5G              (1 << 7)  /*< 5 Gbps */
+#define ETH_LINK_SPEED_10G             (1 << 8)  /*< 10 Mbps */
+#define ETH_LINK_SPEED_20G             (1 << 9)  /*< 20 Gbps */
+#define ETH_LINK_SPEED_25G             (1 << 10)  /*< 25 Gbps */
+#define ETH_LINK_SPEED_40G             (1 << 11)  /*< 40 Gbps */
+#define ETH_LINK_SPEED_50G             (1 << 12)  /*< 50 Gbps */
+#define ETH_LINK_SPEED_56G             (1 << 13)  /*< 56 Gbps */
+#define ETH_LINK_SPEED_100G            (1 << 14)  /*< 100 Gbps */
+
+/**
+ * Ethernet numeric link speeds in Mbps
+ */
+#define ETH_SPEED_NUM_NONE     0      /*< Not defined */
+#define ETH_SPEED_NUM_10M      10     /*< 10 Mbps */
+#define ETH_SPEED_NUM_100M     100    /*< 100 Mbps */
+#define ETH_SPEED_NUM_1G       1000   /*< 1 Gbps */
+#define ETH_SPEED_NUM_2_5G     2500   /*< 2.5 Gbps */
+#define ETH_SPEED_NUM_5G       5000   /*< 5 Gbps */
+#define ETH_SPEED_NUM_10G      10000  /*< 10 Mbps */
+#define ETH_SPEED_NUM_20G      20000  /*< 20 Gbps */
+#define ETH_SPEED_NUM_25G      25000  /*< 25 Gbps */
+#define ETH_SPEED_NUM_40G      40000  /*< 40 Gbps */
+#define ETH_SPEED_NUM_50G      50000  /*< 50 Gbps */
+#define ETH_SPEED_NUM_56G      56000  /*< 56 Gbps */
+#define ETH_SPEED_NUM_100G     100000 /*< 100 Gbps */
+
+/**
  * A structure used to retrieve link-level information of an Ethernet port.
  */
 struct rte_eth_link {
-       uint16_t link_speed;      /**< ETH_LINK_SPEED_[10, 100, 1000, 10000] */
-       uint16_t link_duplex;     /**< ETH_LINK_[HALF_DUPLEX, FULL_DUPLEX] */
-       uint8_t  link_status : 1; /**< 1 -> link up, 0 -> link down */
-}__attribute__((aligned(8)));     /**< aligned for atomic64 read/write */
-
-#define ETH_LINK_SPEED_AUTONEG  0       /**< Auto-negotiate link speed. */
-#define ETH_LINK_SPEED_10       10      /**< 10 megabits/second. */
-#define ETH_LINK_SPEED_100      100     /**< 100 megabits/second. */
-#define ETH_LINK_SPEED_1000     1000    /**< 1 gigabits/second. */
-#define ETH_LINK_SPEED_10000    10000   /**< 10 gigabits/second. */
-#define ETH_LINK_SPEED_10G      10000   /**< alias of 10 gigabits/second. */
-#define ETH_LINK_SPEED_20G      20000   /**< 20 gigabits/second. */
-#define ETH_LINK_SPEED_40G      40000   /**< 40 gigabits/second. */
+       uint32_t link_speed;        /**< Link speed (ETH_SPEED_NUM_) */
+       uint16_t link_duplex  : 1;  /**< 1 -> full duplex, 0 -> half duplex */
+       uint16_t link_autoneg : 1;  /**< 1 -> link speed has been autoneg */
+       uint16_t link_status  : 1;  /**< 1 -> link up, 0 -> link down */
+} __attribute__((aligned(8)));      /**< aligned for atomic64 read/write */

-#define ETH_LINK_AUTONEG_DUPLEX 0       /**< Auto-negotiate duplex. */
-#define ETH_LINK_HALF_DUPLEX    1       /**< Half-duplex connection. */
-#define ETH_LINK_FULL_DUPLEX    2       /**< Full-duplex connection. */
+/* Utility constants */
+#define ETH_LINK_HALF_DUPLEX    0      /**< Half-duplex connection. */
+#define ETH_LINK_FULL_DUPLEX    1      /**< Full-duplex connection. */
+#define ETH_LINK_SPEED_FIXED    0      /**< Link speed was not autonegociated. 
*/
+#define ETH_LINK_SPEED_NEG      1      /**< Link speed was autonegociated. */
+#define ETH_LINK_DOWN          0       /**< Link is down. */
+#define ETH_LINK_UP            1       /**< Link is up. */

 /**
  * A structure used to configure the ring threshold registers of an RX/TX
@@ -760,10 +793,14 @@ struct rte_intr_conf {
  * configuration settings may be needed.
  */
 struct rte_eth_conf {
-       uint16_t link_speed;
-       /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */
-       uint16_t link_duplex;
-       /**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for autonegotation */
+       uint32_t link_speeds; /**< bitmap of ETH_LINK_SPEED_XXX of speeds to be
+                               used. ETH_LINK_SPEED_NO_AUTONEG disables link
+                               autonegociation, and a unique speed shall be
+                               set. Otherwise, the bitmap defines the set of
+                               speeds to be advertised. If the special value
+                               ETH_LINK_SPEED_AUTONEG (0) is used, all speeds
+                               supported are advertised.
+                               */
        struct rte_eth_rxmode rxmode; /**< Port RX configuration. */
        struct rte_eth_txmode txmode; /**< Port TX configuration. */
        uint32_t lpbk_mode; /**< Loopback operation mode. By default the value
@@ -825,26 +862,6 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_QINQ_INSERT 0x00000100

 /**
- * Device supported speeds
- */
-#define ETH_SPEED_CAP_NOT_PHY  (0)  /*< No phy media > */
-#define ETH_SPEED_CAP_10M_HD   (1 << 0)  /*< 10 Mbps half-duplex> */
-#define ETH_SPEED_CAP_10M_FD   (1 << 1)  /*< 10 Mbps full-duplex> */
-#define ETH_SPEED_CAP_100M_HD  (1 << 2)  /*< 100 Mbps half-duplex> */
-#define ETH_SPEED_CAP_100M_FD  (1 << 3)  /*< 100 Mbps full-duplex> */
-#define ETH_SPEED_CAP_1G       (1 << 4)  /*< 1 Gbps > */
-#define ETH_SPEED_CAP_2_5G     (1 << 5)  /*< 2.5 Gbps > */
-#define ETH_SPEED_CAP_5G       (1 << 6)  /*< 5 Gbps > */
-#define ETH_SPEED_CAP_10G      (1 << 7)  /*< 10 Mbps > */
-#define ETH_SPEED_CAP_20G      (1 << 8)  /*< 20 Gbps > */
-#define ETH_SPEED_CAP_25G      (1 << 9)  /*< 25 Gbps > */
-#define ETH_SPEED_CAP_40G      (1 << 10)  /*< 40 Gbps > */
-#define ETH_SPEED_CAP_50G      (1 << 11)  /*< 50 Gbps > */
-#define ETH_SPEED_CAP_56G      (1 << 12)  /*< 56 Gbps > */
-#define ETH_SPEED_CAP_100G     (1 << 13)  /*< 100 Gbps > */
-
-
-/**
  * Ethernet device information
  */
 struct rte_eth_dev_info {
@@ -1811,6 +1828,22 @@ struct eth_driver {
 void rte_eth_driver_register(struct eth_driver *eth_drv);

 /**
+ * Convert a numerical speed in Mbps to a bitmap flag that can be used in
+ * the bitmap link_speeds of the struct rte_eth_conf
+ *
+ * @param
+ *   Numerical speed value in Mbps
+ * @param
+ *   Boolean is duplex (only for 10/100 speeds)
+ * @param
+ *   On success, the converted speed into a bitmap flag
+ * @return
+ *   0 on success, -EINVAL if the speed cannot be mapped
+ */
+extern int rte_eth_speed_to_bm_flag(uint32_t speed, int duplex,
+                                                       uint32_t *flag);
+
+/**
  * Configure an Ethernet device.
  * This function must be invoked first before any other function in the
  * Ethernet API. This function can also be re-invoked when a device is in the
diff --git a/lib/librte_ether/rte_ether_version.map 
b/lib/librte_ether/rte_ether_version.map
index d8db24d..2c14ad7 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -117,3 +117,9 @@ DPDK_2.2 {

        local: *;
 };
+
+DPDK_2.3 {
+       global:
+
+       rte_eth_speed_to_bm_flag;
+}DPDK_2.2;
-- 
2.1.4

Reply via email to