DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap
@ 2015-05-11 23:45 Marc Sune
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
                   ` (3 more replies)
  0 siblings, 4 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-11 23:45 UTC (permalink / raw)
  To: dev

The current rte_eth_dev_info abstraction does not provide any mechanism to
know the supported speed(s) of an ethdev.

For some drivers (e.g. ixgbe), an educated guess can be done based on the
driver's name (driver_name in rte_eth_dev_info), see:

http://dpdk.org/ml/archives/dev/2013-August/000412.html

However, i) doing string comparisons is annoying, and can silently
break existing applications if PMDs change their names ii) it does not
provide all the supported capabilities of the ethdev iii) for some drivers it
is impossible determine correctly the (max) speed by the application
(e.g. in i40, distinguish between XL710 and X710).

This small patch adds speed_capa bitmap in rte_eth_dev_info, which is filled
by the PMDs according to the physical device capabilities.

WARNING: the patch is only tested with e1000s, and should be reviewed for
accuracy.


Marc Sune (2):
  Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  Filling speed capability bitmaps in the PMDs

 lib/librte_ether/rte_ethdev.h       | 24 ++++++++++++++++++++++++
 lib/librte_pmd_e1000/em_ethdev.c    |  6 ++++++
 lib/librte_pmd_e1000/igb_ethdev.c   |  6 ++++++
 lib/librte_pmd_fm10k/fm10k_ethdev.c |  3 +++
 lib/librte_pmd_i40e/i40e_ethdev.c   |  9 +++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 lib/librte_pmd_mlx4/mlx4.c          |  6 ++++++
 7 files changed, 64 insertions(+)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-11 23:45 [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
@ 2015-05-11 23:45 ` Marc Sune
  2015-05-25 17:46   ` Stephen Hemminger
  2015-05-26 15:03   ` Stephen Hemminger
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-11 23:45 UTC (permalink / raw)
  To: dev

Added constants and bitmap to struct rte_eth_dev_info to be used by PMDs.

Signed-off-by: Marc Sune <marc.sune@bisdn.de>
---
 lib/librte_ether/rte_ethdev.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 4648290..05f6e88 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -899,6 +899,29 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_UDP_TSO     0x00000040
 #define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */
 
+/**
+ * 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 {
 	struct rte_pci_device *pci_dev; /**< Device PCI information. */
 	const char *driver_name; /**< Device Driver name. */
@@ -924,6 +947,7 @@ struct rte_eth_dev_info {
 	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
 	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
 	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
+	uint16_t speed_capa;  /**< Supported speeds bitmap. */
 };
 
 /** Maximum name length for extended statistics counters */
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [RFC PATCH 2/2] Filling speed capability bitmaps in the PMDs
  2015-05-11 23:45 [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
@ 2015-05-11 23:45 ` Marc Sune
  2015-05-25 16:32 ` [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-05-26 19:50 ` [dpdk-dev] [PATCH v2 " Marc Sune
  3 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-11 23:45 UTC (permalink / raw)
  To: dev

Added speed capabilities to all pmds supporting physical NICs:

* e1000
* ixgbe
* i40
* mlx4
* fm10k

This commit should be revised to ensure accuracy. It is mostly
untested (HW not available).

Signed-off-by: Marc Sune <marc.sune@bisdn.de>
---
 lib/librte_pmd_e1000/em_ethdev.c    |  6 ++++++
 lib/librte_pmd_e1000/igb_ethdev.c   |  6 ++++++
 lib/librte_pmd_fm10k/fm10k_ethdev.c |  3 +++
 lib/librte_pmd_i40e/i40e_ethdev.c   |  9 +++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 lib/librte_pmd_mlx4/mlx4.c          |  6 ++++++
 6 files changed, 40 insertions(+)

diff --git a/lib/librte_pmd_e1000/em_ethdev.c b/lib/librte_pmd_e1000/em_ethdev.c
index da02988..593e182 100644
--- a/lib/librte_pmd_e1000/em_ethdev.c
+++ b/lib/librte_pmd_e1000/em_ethdev.c
@@ -883,6 +883,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	dev_info->max_rx_queues = 1;
 	dev_info->max_tx_queues = 1;
+
+	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;
 }
 
 /* return 0 means link status changed, -1 means not changed */
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 4415155..8b5514f 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -1398,6 +1398,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		},
 		.txq_flags = 0,
 	};
+
+	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;
 }
 
 static void
diff --git a/lib/librte_pmd_fm10k/fm10k_ethdev.c b/lib/librte_pmd_fm10k/fm10k_ethdev.c
index 275c19c..e97b857 100644
--- a/lib/librte_pmd_fm10k/fm10k_ethdev.c
+++ b/lib/librte_pmd_fm10k/fm10k_ethdev.c
@@ -791,6 +791,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
 				ETH_TXQ_FLAGS_NOOFFLOADS,
 	};
 
+	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;
 }
 
 static int
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index 43762f2..70675d6 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -1518,6 +1518,7 @@ static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *vsi = pf->main_vsi;
 
 	dev_info->max_rx_queues = vsi->nb_qps;
@@ -1573,6 +1574,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
 	}
+
+	if (i40e_is_40G_device(hw->device_id))
+		/* For XL710 */
+		dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
+	else
+		/* For X710 */
+		dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
+
 }
 
 static int
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 5f9a1cf..1b5de9a 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -2054,6 +2054,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	};
 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
+
+	dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_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)
+
+		dev_info->speed_capa |= ETH_SPEED_CAP_100M_FD |
+					ETH_SPEED_CAP_100M_HD;
 }
 
 static void
diff --git a/lib/librte_pmd_mlx4/mlx4.c b/lib/librte_pmd_mlx4/mlx4.c
index f915bc1..d4442fb 100644
--- a/lib/librte_pmd_mlx4/mlx4.c
+++ b/lib/librte_pmd_mlx4/mlx4.c
@@ -3482,6 +3482,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 	info->max_rx_queues = max;
 	info->max_tx_queues = max;
 	info->max_mac_addrs = elemof(priv->mac);
+
+	info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_20G |
+					ETH_SPEED_CAP_25G | ETH_SPEED_CAP_40G |
+					ETH_SPEED_CAP_50G | ETH_SPEED_CAP_56G |
+					ETH_SPEED_CAP_100G;
+
 	priv_unlock(priv);
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap
  2015-05-11 23:45 [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
@ 2015-05-25 16:32 ` Marc Sune
  2015-05-26 19:50 ` [dpdk-dev] [PATCH v2 " Marc Sune
  3 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-25 16:32 UTC (permalink / raw)
  To: dev

Any objections to this one? Otherwise I will rebase and propose a formal 
patch

marc

On 12/05/15 01:45, Marc Sune wrote:
> The current rte_eth_dev_info abstraction does not provide any mechanism to
> know the supported speed(s) of an ethdev.
>
> For some drivers (e.g. ixgbe), an educated guess can be done based on the
> driver's name (driver_name in rte_eth_dev_info), see:
>
> http://dpdk.org/ml/archives/dev/2013-August/000412.html
>
> However, i) doing string comparisons is annoying, and can silently
> break existing applications if PMDs change their names ii) it does not
> provide all the supported capabilities of the ethdev iii) for some drivers it
> is impossible determine correctly the (max) speed by the application
> (e.g. in i40, distinguish between XL710 and X710).
>
> This small patch adds speed_capa bitmap in rte_eth_dev_info, which is filled
> by the PMDs according to the physical device capabilities.
>
> WARNING: the patch is only tested with e1000s, and should be reviewed for
> accuracy.
>
>
> Marc Sune (2):
>    Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
>    Filling speed capability bitmaps in the PMDs
>
>   lib/librte_ether/rte_ethdev.h       | 24 ++++++++++++++++++++++++
>   lib/librte_pmd_e1000/em_ethdev.c    |  6 ++++++
>   lib/librte_pmd_e1000/igb_ethdev.c   |  6 ++++++
>   lib/librte_pmd_fm10k/fm10k_ethdev.c |  3 +++
>   lib/librte_pmd_i40e/i40e_ethdev.c   |  9 +++++++++
>   lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 10 ++++++++++
>   lib/librte_pmd_mlx4/mlx4.c          |  6 ++++++
>   7 files changed, 64 insertions(+)
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
@ 2015-05-25 17:46   ` Stephen Hemminger
  2015-05-26  8:41     ` Marc Sune
  2015-05-26 15:03   ` Stephen Hemminger
  1 sibling, 1 reply; 64+ messages in thread
From: Stephen Hemminger @ 2015-05-25 17:46 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

On Tue, 12 May 2015 01:45:45 +0200
Marc Sune <marc.sune@bisdn.de> wrote:

> +/**
> + * Ethernet device information
> + */
>  struct rte_eth_dev_info {
>  	struct rte_pci_device *pci_dev; /**< Device PCI information. */
>  	const char *driver_name; /**< Device Driver name. */
> @@ -924,6 +947,7 @@ struct rte_eth_dev_info {
>  	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
>  	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
>  	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
> +	uint16_t speed_capa;  /**< Supported speeds bitmap. */

Since you are likely to run out of 16 bits in future, why not 32 bits now?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-25 17:46   ` Stephen Hemminger
@ 2015-05-26  8:41     ` Marc Sune
  0 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-26  8:41 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev



On 25/05/15 19:46, Stephen Hemminger wrote:
> On Tue, 12 May 2015 01:45:45 +0200
> Marc Sune <marc.sune@bisdn.de> wrote:
>
>> +/**
>> + * Ethernet device information
>> + */
>>   struct rte_eth_dev_info {
>>   	struct rte_pci_device *pci_dev; /**< Device PCI information. */
>>   	const char *driver_name; /**< Device Driver name. */
>> @@ -924,6 +947,7 @@ struct rte_eth_dev_info {
>>   	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
>>   	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
>>   	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
>> +	uint16_t speed_capa;  /**< Supported speeds bitmap. */
> Since you are likely to run out of 16 bits in future, why not 32 bits now?

Indeed, why not. I will convert it to uint32_t when I send the new version.

Thanks
marc

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
  2015-05-25 17:46   ` Stephen Hemminger
@ 2015-05-26 15:03   ` Stephen Hemminger
  2015-05-26 15:09     ` Marc Sune
  1 sibling, 1 reply; 64+ messages in thread
From: Stephen Hemminger @ 2015-05-26 15:03 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

On Tue, 12 May 2015 01:45:45 +0200
Marc Sune <marc.sune@bisdn.de> wrote:

> +/**
> + * Ethernet device information
> + */
>  struct rte_eth_dev_info {
>  	struct rte_pci_device *pci_dev; /**< Device PCI information. */
>  	const char *driver_name; /**< Device Driver name. */
> @@ -924,6 +947,7 @@ struct rte_eth_dev_info {
>  	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
>  	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
>  	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
> +	uint16_t speed_capa;  /**< Supported speeds bitmap. */
>  };
>  

Since you are changing size of key structure, this is an ABI change.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-26 15:03   ` Stephen Hemminger
@ 2015-05-26 15:09     ` Marc Sune
  0 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-26 15:09 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev



On 26/05/15 17:03, Stephen Hemminger wrote:
> On Tue, 12 May 2015 01:45:45 +0200
> Marc Sune <marc.sune@bisdn.de> wrote:
>
>> +/**
>> + * Ethernet device information
>> + */
>>   struct rte_eth_dev_info {
>>   	struct rte_pci_device *pci_dev; /**< Device PCI information. */
>>   	const char *driver_name; /**< Device Driver name. */
>> @@ -924,6 +947,7 @@ struct rte_eth_dev_info {
>>   	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
>>   	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
>>   	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
>> +	uint16_t speed_capa;  /**< Supported speeds bitmap. */
>>   };
>>   
> Since you are changing size of key structure, this is an ABI change.

Yes. This means target would be 2.2?

I will send the new version anyway to further discuss, and will rebase 
again once necessary.

Marc

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v2 0/2] ethdev: add port speed capability bitmap
  2015-05-11 23:45 [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
                   ` (2 preceding siblings ...)
  2015-05-25 16:32 ` [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
@ 2015-05-26 19:50 ` Marc Sune
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
                     ` (2 more replies)
  3 siblings, 3 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-26 19:50 UTC (permalink / raw)
  To: dev

The current rte_eth_dev_info abstraction does not provide any mechanism to
get the supported speed(s) of an ethdev.

For some drivers (e.g. ixgbe), an educated guess can be done based on the
driver's name (driver_name in rte_eth_dev_info), see:

http://dpdk.org/ml/archives/dev/2013-August/000412.html

However, i) doing string comparisons is annoying, and can silently
break existing applications if PMDs change their names ii) it does not
provide all the supported capabilities of the ethdev iii) for some drivers it
is impossible determine correctly the (max) speed by the application
(e.g. in i40, distinguish between XL710 and X710).

This small patch adds speed_capa bitmap in rte_eth_dev_info, which is filled
by the PMDs according to the physical device capabilities.

v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
(checkpatch).

Marc Sune (2):
  Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  Filling speed capability bitmaps in the PMDs

 drivers/net/e1000/em_ethdev.c    |  6 ++++++
 drivers/net/e1000/igb_ethdev.c   |  6 ++++++
 drivers/net/fm10k/fm10k_ethdev.c |  3 +++
 drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 drivers/net/mlx4/mlx4.c          |  6 ++++++
 lib/librte_ether/rte_ethdev.h    | 24 ++++++++++++++++++++++++
 7 files changed, 64 insertions(+)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-26 19:50 ` [dpdk-dev] [PATCH v2 " Marc Sune
@ 2015-05-26 19:50   ` Marc Sune
  2015-05-27  4:02     ` Thomas Monjalon
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
  2015-08-28 23:20   ` [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap Marc Sune
  2 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-05-26 19:50 UTC (permalink / raw)
  To: dev

Added constants and bitmap to struct rte_eth_dev_info to be used by PMDs.

Signed-off-by: Marc Sune <marc.sune@bisdn.de>
---
 lib/librte_ether/rte_ethdev.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 16dbe00..f57676b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -900,6 +900,29 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_UDP_TSO     0x00000040
 #define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */
 
+/**
+ * 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 {
 	struct rte_pci_device *pci_dev; /**< Device PCI information. */
 	const char *driver_name; /**< Device Driver name. */
@@ -925,6 +948,7 @@ struct rte_eth_dev_info {
 	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
 	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
 	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
+	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_CAP_). */
 };
 
 /** Maximum name length for extended statistics counters */
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs
  2015-05-26 19:50 ` [dpdk-dev] [PATCH v2 " Marc Sune
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
@ 2015-05-26 19:50   ` Marc Sune
  2015-05-26 21:20     ` Igor Ryzhov
  2015-08-28 23:20   ` [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap Marc Sune
  2 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-05-26 19:50 UTC (permalink / raw)
  To: dev

Added speed capabilities to all pmds supporting physical NICs:

* e1000
* ixgbe
* i40
* mlx4
* fm10k

Signed-off-by: Marc Sune <marc.sune@bisdn.de>
---
 drivers/net/e1000/em_ethdev.c    |  6 ++++++
 drivers/net/e1000/igb_ethdev.c   |  6 ++++++
 drivers/net/fm10k/fm10k_ethdev.c |  3 +++
 drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 drivers/net/mlx4/mlx4.c          |  6 ++++++
 6 files changed, 40 insertions(+)

diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index d28030e..8e25cfa 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -883,6 +883,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	dev_info->max_rx_queues = 1;
 	dev_info->max_tx_queues = 1;
+
+	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;
 }
 
 /* return 0 means link status changed, -1 means not changed */
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e4b370d..424ad6f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1398,6 +1398,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		},
 		.txq_flags = 0,
 	};
+
+	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;
 }
 
 static void
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 275c19c..e97b857 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -791,6 +791,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
 				ETH_TXQ_FLAGS_NOOFFLOADS,
 	};
 
+	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;
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index fb64027..5e9db6b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1519,6 +1519,7 @@ static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *vsi = pf->main_vsi;
 
 	dev_info->max_rx_queues = vsi->nb_qps;
@@ -1574,6 +1575,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
 	}
+
+	if (i40e_is_40G_device(hw->device_id))
+		/* For XL710 */
+		dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
+	else
+		/* For X710 */
+		dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
+
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 0d9f9b2..78b13a8 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -2054,6 +2054,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	};
 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
+
+	dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_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)
+
+		dev_info->speed_capa |= ETH_SPEED_CAP_100M_FD |
+					ETH_SPEED_CAP_100M_HD;
 }
 
 static void
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index f915bc1..d4442fb 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -3482,6 +3482,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 	info->max_rx_queues = max;
 	info->max_tx_queues = max;
 	info->max_mac_addrs = elemof(priv->mac);
+
+	info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_20G |
+					ETH_SPEED_CAP_25G | ETH_SPEED_CAP_40G |
+					ETH_SPEED_CAP_50G | ETH_SPEED_CAP_56G |
+					ETH_SPEED_CAP_100G;
+
 	priv_unlock(priv);
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
@ 2015-05-26 21:20     ` Igor Ryzhov
  2015-05-27  8:59       ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Igor Ryzhov @ 2015-05-26 21:20 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

Hello, Marc!

You swapped values for X710 and XL710 - you use 1G and 10G for XL710, 10G and 40G for X710.

Best regards,
Igor

> 26 мая 2015 г., в 22:50, Marc Sune <marc.sune@bisdn.de> написал(а):
> 
> Added speed capabilities to all pmds supporting physical NICs:
> 
> * e1000
> * ixgbe
> * i40
> * mlx4
> * fm10k
> 
> Signed-off-by: Marc Sune <marc.sune@bisdn.de>
> ---
> drivers/net/e1000/em_ethdev.c    |  6 ++++++
> drivers/net/e1000/igb_ethdev.c   |  6 ++++++
> drivers/net/fm10k/fm10k_ethdev.c |  3 +++
> drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
> drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
> drivers/net/mlx4/mlx4.c          |  6 ++++++
> 6 files changed, 40 insertions(+)
> 
> diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
> index d28030e..8e25cfa 100644
> --- a/drivers/net/e1000/em_ethdev.c
> +++ b/drivers/net/e1000/em_ethdev.c
> @@ -883,6 +883,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> 
> 	dev_info->max_rx_queues = 1;
> 	dev_info->max_tx_queues = 1;
> +
> +	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;
> }
> 
> /* return 0 means link status changed, -1 means not changed */
> diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
> index e4b370d..424ad6f 100644
> --- a/drivers/net/e1000/igb_ethdev.c
> +++ b/drivers/net/e1000/igb_ethdev.c
> @@ -1398,6 +1398,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> 		},
> 		.txq_flags = 0,
> 	};
> +
> +	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;
> }
> 
> static void
> diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
> index 275c19c..e97b857 100644
> --- a/drivers/net/fm10k/fm10k_ethdev.c
> +++ b/drivers/net/fm10k/fm10k_ethdev.c
> @@ -791,6 +791,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
> 				ETH_TXQ_FLAGS_NOOFFLOADS,
> 	};
> 
> +	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;
> }
> 
> static int
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index fb64027..5e9db6b 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -1519,6 +1519,7 @@ static void
> i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> {
> 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> 	struct i40e_vsi *vsi = pf->main_vsi;
> 
> 	dev_info->max_rx_queues = vsi->nb_qps;
> @@ -1574,6 +1575,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
> 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
> 	}
> +
> +	if (i40e_is_40G_device(hw->device_id))
> +		/* For XL710 */
> +		dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
> +	else
> +		/* For X710 */
> +		dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
> +
> }
> 
> static int
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
> index 0d9f9b2..78b13a8 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -2054,6 +2054,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> 	};
> 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
> 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
> +
> +	dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_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)
> +
> +		dev_info->speed_capa |= ETH_SPEED_CAP_100M_FD |
> +					ETH_SPEED_CAP_100M_HD;
> }
> 
> static void
> diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
> index f915bc1..d4442fb 100644
> --- a/drivers/net/mlx4/mlx4.c
> +++ b/drivers/net/mlx4/mlx4.c
> @@ -3482,6 +3482,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
> 	info->max_rx_queues = max;
> 	info->max_tx_queues = max;
> 	info->max_mac_addrs = elemof(priv->mac);
> +
> +	info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_20G |
> +					ETH_SPEED_CAP_25G | ETH_SPEED_CAP_40G |
> +					ETH_SPEED_CAP_50G | ETH_SPEED_CAP_56G |
> +					ETH_SPEED_CAP_100G;
> +
> 	priv_unlock(priv);
> }
> 
> -- 
> 2.1.4
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
@ 2015-05-27  4:02     ` Thomas Monjalon
  2015-05-27  9:15       ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Thomas Monjalon @ 2015-05-27  4:02 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

Hi Marc,

2015-05-26 21:50, Marc Sune:
> Added constants and bitmap to struct rte_eth_dev_info to be used by PMDs.
> 
> Signed-off-by: Marc Sune <marc.sune@bisdn.de>
[...]
> +/**
> + * Device supported speeds
> + */
> +#define ETH_SPEED_CAP_NOT_PHY	(0)  /*< No phy media > */

Why not starting with lower values? Some new drivers may be interested
by lower speed.

> +#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 > */

We should note that rte_eth_link is using ETH_LINK_SPEED_* constants
which are not some bitmaps so we have to create these new constants.
Furthermore, rte_eth_link.link_speed is an uint16_t so it is limited
to 40G. Should we use some constant bitmaps here also?
What about removing _CAP suffix from your constants?

[...]
> +	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_CAP_). */

If the constants are ETH_SPEED_CAP, why not wording this variable speed_cap?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs
  2015-05-26 21:20     ` Igor Ryzhov
@ 2015-05-27  8:59       ` Marc Sune
  0 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-05-27  8:59 UTC (permalink / raw)
  To: Igor Ryzhov; +Cc: dev



On 26/05/15 23:20, Igor Ryzhov wrote:
> Hello, Marc!
>
> You swapped values for X710 and XL710 - you use 1G and 10G for XL710, 10G and 40G for X710.

Thanks, I will fix that in v3. This is why I was saying in the RFC patch 
that it needed to be carefully reviewed.

marc

>
> Best regards,
> Igor
>
>> 26 мая 2015 г., в 22:50, Marc Sune <marc.sune@bisdn.de> написал(а):
>>
>> Added speed capabilities to all pmds supporting physical NICs:
>>
>> * e1000
>> * ixgbe
>> * i40
>> * mlx4
>> * fm10k
>>
>> Signed-off-by: Marc Sune <marc.sune@bisdn.de>
>> ---
>> drivers/net/e1000/em_ethdev.c    |  6 ++++++
>> drivers/net/e1000/igb_ethdev.c   |  6 ++++++
>> drivers/net/fm10k/fm10k_ethdev.c |  3 +++
>> drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
>> drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
>> drivers/net/mlx4/mlx4.c          |  6 ++++++
>> 6 files changed, 40 insertions(+)
>>
>> diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
>> index d28030e..8e25cfa 100644
>> --- a/drivers/net/e1000/em_ethdev.c
>> +++ b/drivers/net/e1000/em_ethdev.c
>> @@ -883,6 +883,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>>
>> 	dev_info->max_rx_queues = 1;
>> 	dev_info->max_tx_queues = 1;
>> +
>> +	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;
>> }
>>
>> /* return 0 means link status changed, -1 means not changed */
>> diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
>> index e4b370d..424ad6f 100644
>> --- a/drivers/net/e1000/igb_ethdev.c
>> +++ b/drivers/net/e1000/igb_ethdev.c
>> @@ -1398,6 +1398,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>> 		},
>> 		.txq_flags = 0,
>> 	};
>> +
>> +	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;
>> }
>>
>> static void
>> diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
>> index 275c19c..e97b857 100644
>> --- a/drivers/net/fm10k/fm10k_ethdev.c
>> +++ b/drivers/net/fm10k/fm10k_ethdev.c
>> @@ -791,6 +791,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
>> 				ETH_TXQ_FLAGS_NOOFFLOADS,
>> 	};
>>
>> +	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;
>> }
>>
>> static int
>> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
>> index fb64027..5e9db6b 100644
>> --- a/drivers/net/i40e/i40e_ethdev.c
>> +++ b/drivers/net/i40e/i40e_ethdev.c
>> @@ -1519,6 +1519,7 @@ static void
>> i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>> {
>> 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
>> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
>> 	struct i40e_vsi *vsi = pf->main_vsi;
>>
>> 	dev_info->max_rx_queues = vsi->nb_qps;
>> @@ -1574,6 +1575,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>> 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
>> 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
>> 	}
>> +
>> +	if (i40e_is_40G_device(hw->device_id))
>> +		/* For XL710 */
>> +		dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
>> +	else
>> +		/* For X710 */
>> +		dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
>> +
>> }
>>
>> static int
>> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
>> index 0d9f9b2..78b13a8 100644
>> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
>> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
>> @@ -2054,6 +2054,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>> 	};
>> 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
>> 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
>> +
>> +	dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_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)
>> +
>> +		dev_info->speed_capa |= ETH_SPEED_CAP_100M_FD |
>> +					ETH_SPEED_CAP_100M_HD;
>> }
>>
>> static void
>> diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
>> index f915bc1..d4442fb 100644
>> --- a/drivers/net/mlx4/mlx4.c
>> +++ b/drivers/net/mlx4/mlx4.c
>> @@ -3482,6 +3482,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
>> 	info->max_rx_queues = max;
>> 	info->max_tx_queues = max;
>> 	info->max_mac_addrs = elemof(priv->mac);
>> +
>> +	info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_20G |
>> +					ETH_SPEED_CAP_25G | ETH_SPEED_CAP_40G |
>> +					ETH_SPEED_CAP_50G | ETH_SPEED_CAP_56G |
>> +					ETH_SPEED_CAP_100G;
>> +
>> 	priv_unlock(priv);
>> }
>>
>> -- 
>> 2.1.4
>>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-27  4:02     ` Thomas Monjalon
@ 2015-05-27  9:15       ` Marc Sune
  2015-05-29 18:23         ` Thomas Monjalon
  0 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-05-27  9:15 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev



On 27/05/15 06:02, Thomas Monjalon wrote:
> Hi Marc,
>
> 2015-05-26 21:50, Marc Sune:
>> Added constants and bitmap to struct rte_eth_dev_info to be used by PMDs.
>>
>> Signed-off-by: Marc Sune <marc.sune@bisdn.de>
> [...]
>> +/**
>> + * Device supported speeds
>> + */
>> +#define ETH_SPEED_CAP_NOT_PHY	(0)  /*< No phy media > */
> Why not starting with lower values? Some new drivers may be interested
> by lower speed.

Ok, but which values? 1Mbps FD/HD? Even lower than that?

If you have some NIC(s) in mind with lower values, please point me to 
that and I will collect&add the missing speeds.

>
>> +#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 > */
> We should note that rte_eth_link is using ETH_LINK_SPEED_* constants
> which are not some bitmaps so we have to create these new constants.

Yes, I can add that to the patch description (1/2).

> Furthermore, rte_eth_link.link_speed is an uint16_t so it is limited
> to 40G. Should we use some constant bitmaps here also?

I also thought about converting link_speed into a bitmap to unify the 
constants before starting the patch (there is redundancy), but I wanted 
to be minimally invasive; changing link to a bitmap can break existing apps.

I can also merge them if we think is a better idea.
> What about removing _CAP suffix from your constants?

I added the suffix to make clearer the distinction with link speeds. I 
can remove it if we merge both or if we consider it is not necessary.

>
> [...]
>> +	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_CAP_). */
> If the constants are ETH_SPEED_CAP, why not wording this variable speed_cap?

I followed the convention of the existing rx/tx offload capability bitmaps:

marc@dev:~/git/bisdn/msune/xdpd/libs/dpdk/lib$ grep _capa\; * -R
librte_ether/rte_ethdev.h:    uint32_t rx_offload_capa; /**< Device RX 
offload capabilities. */
librte_ether/rte_ethdev.h:    uint32_t tx_offload_capa; /**< Device TX 
offload capabilities. */

I am fine with speed_cap or speed_caps, but I think we should have some 
consistency on how we name bitmaps.

If we would want to make the bitmaps more explicit, we could define some 
helper typedefs in EAL:

typedef uint16_t bitmap16_t;
typedef uint32_t bitmap32_t;
typedef uint64_t bitmap64_t;

and replace the bitmaps of the structs, again specially the ones used by 
the users.

marc

>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-27  9:15       ` Marc Sune
@ 2015-05-29 18:23         ` Thomas Monjalon
  2015-06-08  8:50           ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Thomas Monjalon @ 2015-05-29 18:23 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

2015-05-27 11:15, Marc Sune:
> On 27/05/15 06:02, Thomas Monjalon wrote:
> > Why not starting with lower values? Some new drivers may be interested
> > by lower speed.
> 
> Ok, but which values? 1Mbps FD/HD? Even lower than that?
> 
> If you have some NIC(s) in mind with lower values, please point me to 
> that and I will collect&add the missing speeds.

No sorry, I missed how low your first values were.

> >> +#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 > */
> > We should note that rte_eth_link is using ETH_LINK_SPEED_* constants
> > which are not some bitmaps so we have to create these new constants.
> 
> Yes, I can add that to the patch description (1/2).
> 
> > Furthermore, rte_eth_link.link_speed is an uint16_t so it is limited
> > to 40G. Should we use some constant bitmaps here also?
> 
> I also thought about converting link_speed into a bitmap to unify the 
> constants before starting the patch (there is redundancy), but I wanted 
> to be minimally invasive; changing link to a bitmap can break existing apps.
> 
> I can also merge them if we think is a better idea.

Maybe. Someone against this idea?

> > What about removing _CAP suffix from your constants?
> 
> I added the suffix to make clearer the distinction with link speeds. I 
> can remove it if we merge both or if we consider it is not necessary.
> 
> >
> > [...]
> >> +	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_CAP_). */
> > If the constants are ETH_SPEED_CAP, why not wording this variable speed_cap?
> 
> I followed the convention of the existing rx/tx offload capability bitmaps:
> 
> marc@dev:~/git/bisdn/msune/xdpd/libs/dpdk/lib$ grep _capa\; * -R
> librte_ether/rte_ethdev.h:    uint32_t rx_offload_capa; /**< Device RX 
> offload capabilities. */
> librte_ether/rte_ethdev.h:    uint32_t tx_offload_capa; /**< Device TX 
> offload capabilities. */
> 
> I am fine with speed_cap or speed_caps, but I think we should have some 
> consistency on how we name bitmaps.

You're right.

> If we would want to make the bitmaps more explicit, we could define some 
> helper typedefs in EAL:
> 
> typedef uint16_t bitmap16_t;
> typedef uint32_t bitmap32_t;
> typedef uint64_t bitmap64_t;
> 
> and replace the bitmaps of the structs, again specially the ones used by 
> the users.

No, if we want to show this variable is a bitmap, the variable name
may be changed, not the type. It would bring clarity when reading code
using this variable but I think it's not really needed.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-05-29 18:23         ` Thomas Monjalon
@ 2015-06-08  8:50           ` Marc Sune
  2015-06-11  9:08             ` Thomas Monjalon
  0 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-06-08  8:50 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev



On 29/05/15 20:23, Thomas Monjalon wrote:
> 2015-05-27 11:15, Marc Sune:
>> On 27/05/15 06:02, Thomas Monjalon wrote:
>>> Why not starting with lower values? Some new drivers may be interested
>>> by lower speed.
>> Ok, but which values? 1Mbps FD/HD? Even lower than that?
>>
>> If you have some NIC(s) in mind with lower values, please point me to
>> that and I will collect&add the missing speeds.
> No sorry, I missed how low your first values were.
>
>>>> +#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 > */
>>> We should note that rte_eth_link is using ETH_LINK_SPEED_* constants
>>> which are not some bitmaps so we have to create these new constants.
>> Yes, I can add that to the patch description (1/2).
>>
>>> Furthermore, rte_eth_link.link_speed is an uint16_t so it is limited
>>> to 40G. Should we use some constant bitmaps here also?
>> I also thought about converting link_speed into a bitmap to unify the
>> constants before starting the patch (there is redundancy), but I wanted
>> to be minimally invasive; changing link to a bitmap can break existing apps.
>>
>> I can also merge them if we think is a better idea.
> Maybe. Someone against this idea?

Me. I tried implementing this unified speed constantss, but the problem 
is that for the capabilities full-duplex/half-duplex speeds are unrolled 
(e.g. 100M_HD/100_FD). There is no generic 100M to set a specific speed, 
so if you want a fiex speed and duplex auto-negociation witht the 
current set of constants, it would look weird; e.g. 
link_speed=ETH_SPEED_100M_HD and then set 
link_duplex=ETH_LINK_AUTONEG_DUPLEX):

  232 struct rte_eth_link {
  233         uint16_t link_speed;      /**< ETH_LINK_SPEED_[10, 100, 
1000, 10000] */
  234         uint16_t link_duplex;     /**< ETH_LINK_[HALF_DUPLEX, 
FULL_DUPLEX] */
  235         uint8_t  link_status : 1; /**< 1 -> link up, 0 -> link 
down */
  236 }__attribute__((aligned(8)));     /**< aligned for atomic64 
read/write */

There is another minor point, which is when setting the speed in 
rte_eth_conf:

  840 struct rte_eth_conf {
  841         uint16_t link_speed;
  842         /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */

0 is used for speed auto-negociation, but 0 is also used in the 
capabilities bitmap to indicate no PHY_MEDIA (virtual interface). I 
would have to define something like:

906 #define ETH_SPEED_NOT_PHY   (0)  /*< No phy media > */
907 #define ETH_SPEED_AUTONEG   (0)  /*< Autonegociate speed > */

And use (only) NOT_PHY for a capabilities and _AUTONEG for rte_eth_conf.

The options I see:

a) add to the the list of the current speeds generic 10M/100M/1G speeds 
without HD/FD, and just use these speeds in rte_eth_conf.
b) leave them separated.

I would vote for b), since the a) is not completely clean. 
Opinions&other alternatives welcome.

Marc

>
>>> What about removing _CAP suffix from your constants?
>> I added the suffix to make clearer the distinction with link speeds. I
>> can remove it if we merge both or if we consider it is not necessary.
>>
>>> [...]
>>>> +	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_CAP_). */
>>> If the constants are ETH_SPEED_CAP, why not wording this variable speed_cap?
>> I followed the convention of the existing rx/tx offload capability bitmaps:
>>
>> marc@dev:~/git/bisdn/msune/xdpd/libs/dpdk/lib$ grep _capa\; * -R
>> librte_ether/rte_ethdev.h:    uint32_t rx_offload_capa; /**< Device RX
>> offload capabilities. */
>> librte_ether/rte_ethdev.h:    uint32_t tx_offload_capa; /**< Device TX
>> offload capabilities. */
>>
>> I am fine with speed_cap or speed_caps, but I think we should have some
>> consistency on how we name bitmaps.
> You're right.
>
>> If we would want to make the bitmaps more explicit, we could define some
>> helper typedefs in EAL:
>>
>> typedef uint16_t bitmap16_t;
>> typedef uint32_t bitmap32_t;
>> typedef uint64_t bitmap64_t;
>>
>> and replace the bitmaps of the structs, again specially the ones used by
>> the users.
> No, if we want to show this variable is a bitmap, the variable name
> may be changed, not the type. It would bring clarity when reading code
> using this variable but I think it's not really needed.
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-06-08  8:50           ` Marc Sune
@ 2015-06-11  9:08             ` Thomas Monjalon
  2015-06-11 14:35               ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Thomas Monjalon @ 2015-06-11  9:08 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

2015-06-08 10:50, Marc Sune:
> On 29/05/15 20:23, Thomas Monjalon wrote:
> > 2015-05-27 11:15, Marc Sune:
> >> On 27/05/15 06:02, Thomas Monjalon wrote:
> >>>> +#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 > */
> >>> We should note that rte_eth_link is using ETH_LINK_SPEED_* constants
> >>> which are not some bitmaps so we have to create these new constants.
> >> Yes, I can add that to the patch description (1/2).
> >>
> >>> Furthermore, rte_eth_link.link_speed is an uint16_t so it is limited
> >>> to 40G. Should we use some constant bitmaps here also?
> >> I also thought about converting link_speed into a bitmap to unify the
> >> constants before starting the patch (there is redundancy), but I wanted
> >> to be minimally invasive; changing link to a bitmap can break existing apps.
> >>
> >> I can also merge them if we think is a better idea.
> > Maybe. Someone against this idea?
> 
> Me. I tried implementing this unified speed constantss, but the problem 
> is that for the capabilities full-duplex/half-duplex speeds are unrolled 
> (e.g. 100M_HD/100_FD). There is no generic 100M to set a specific speed, 

Or we can define ETH_SPEED_CAP_100M and ETH_SPEED_CAP_100M_FD.
Is it possible to have a NIC doing 100M_FD but not 100M_HD?

> so if you want a fiex speed and duplex auto-negociation witht the 
> current set of constants, it would look weird; e.g. 
> link_speed=ETH_SPEED_100M_HD and then set 
> link_duplex=ETH_LINK_AUTONEG_DUPLEX):
> 
>   232 struct rte_eth_link {
>   233         uint16_t link_speed;      /**< ETH_LINK_SPEED_[10, 100, 
> 1000, 10000] */
>   234         uint16_t link_duplex;     /**< ETH_LINK_[HALF_DUPLEX, 
> FULL_DUPLEX] */
>   235         uint8_t  link_status : 1; /**< 1 -> link up, 0 -> link 
> down */
>   236 }__attribute__((aligned(8)));     /**< aligned for atomic64 
> read/write */
> 
> There is another minor point, which is when setting the speed in 
> rte_eth_conf:
> 
>   840 struct rte_eth_conf {
>   841         uint16_t link_speed;
>   842         /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */
> 
> 0 is used for speed auto-negociation, but 0 is also used in the 
> capabilities bitmap to indicate no PHY_MEDIA (virtual interface). I 
> would have to define something like:
> 
> 906 #define ETH_SPEED_NOT_PHY   (0)  /*< No phy media > */
> 907 #define ETH_SPEED_AUTONEG   (0)  /*< Autonegociate speed > */

Or something like SPEED_UNDEFINED

> And use (only) NOT_PHY for a capabilities and _AUTONEG for rte_eth_conf.
> 
> The options I see:
> 
> a) add to the the list of the current speeds generic 10M/100M/1G speeds 
> without HD/FD, and just use these speeds in rte_eth_conf.
> b) leave them separated.
> 
> I would vote for b), since the a) is not completely clean. 
> Opinions&other alternatives welcome.
> 
> Marc

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-06-11  9:08             ` Thomas Monjalon
@ 2015-06-11 14:35               ` Marc Sune
  0 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-06-11 14:35 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev



On 11/06/15 11:08, Thomas Monjalon wrote:
> 2015-06-08 10:50, Marc Sune:
>> On 29/05/15 20:23, Thomas Monjalon wrote:
>>> 2015-05-27 11:15, Marc Sune:
>>>> On 27/05/15 06:02, Thomas Monjalon wrote:
>>>>>> +#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 > */
>>>>> We should note that rte_eth_link is using ETH_LINK_SPEED_* constants
>>>>> which are not some bitmaps so we have to create these new constants.
>>>> Yes, I can add that to the patch description (1/2).
>>>>
>>>>> Furthermore, rte_eth_link.link_speed is an uint16_t so it is limited
>>>>> to 40G. Should we use some constant bitmaps here also?
>>>> I also thought about converting link_speed into a bitmap to unify the
>>>> constants before starting the patch (there is redundancy), but I wanted
>>>> to be minimally invasive; changing link to a bitmap can break existing apps.
>>>>
>>>> I can also merge them if we think is a better idea.
>>> Maybe. Someone against this idea?
>> Me. I tried implementing this unified speed constantss, but the problem
>> is that for the capabilities full-duplex/half-duplex speeds are unrolled
>> (e.g. 100M_HD/100_FD). There is no generic 100M to set a specific speed,
> Or we can define ETH_SPEED_CAP_100M and ETH_SPEED_CAP_100M_FD.
> Is it possible to have a NIC doing 100M_FD but not 100M_HD?

Did not check in detail, but I guess this is mostly legacy NICs, not 
supported by DPDK anyway, and that is safe to assume 10M/100M meaning 
supports both HD/FD.

>
>> so if you want a fiex speed and duplex auto-negociation witht the
>> current set of constants, it would look weird; e.g.
>> link_speed=ETH_SPEED_100M_HD and then set
>> link_duplex=ETH_LINK_AUTONEG_DUPLEX):
>>
>>    232 struct rte_eth_link {
>>    233         uint16_t link_speed;      /**< ETH_LINK_SPEED_[10, 100,
>> 1000, 10000] */
>>    234         uint16_t link_duplex;     /**< ETH_LINK_[HALF_DUPLEX,
>> FULL_DUPLEX] */
>>    235         uint8_t  link_status : 1; /**< 1 -> link up, 0 -> link
>> down */
>>    236 }__attribute__((aligned(8)));     /**< aligned for atomic64
>> read/write */
>>
>> There is another minor point, which is when setting the speed in
>> rte_eth_conf:
>>
>>    840 struct rte_eth_conf {
>>    841         uint16_t link_speed;
>>    842         /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */
>>
>> 0 is used for speed auto-negociation, but 0 is also used in the
>> capabilities bitmap to indicate no PHY_MEDIA (virtual interface). I
>> would have to define something like:
>>
>> 906 #define ETH_SPEED_NOT_PHY   (0)  /*< No phy media > */
>> 907 #define ETH_SPEED_AUTONEG   (0)  /*< Autonegociate speed > */
> Or something like SPEED_UNDEFINED

Ok. I will prepare the patch and circulate a v3.

After briefly chatting offline with Thomas, it seems I was not clearly 
stating in my original v1 that this patch is targeting DPDK v2.2, due to 
ABI(and API) issues.

It is, and so I will hold v3 until 2.2 window starts, to make it more clear.

thanks
Marc
>
>> And use (only) NOT_PHY for a capabilities and _AUTONEG for rte_eth_conf.
>>
>> The options I see:
>>
>> a) add to the the list of the current speeds generic 10M/100M/1G speeds
>> without HD/FD, and just use these speeds in rte_eth_conf.
>> b) leave them separated.
>>
>> I would vote for b), since the a) is not completely clean.
>> Opinions&other alternatives welcome.
>>
>> Marc

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap
  2015-05-26 19:50 ` [dpdk-dev] [PATCH v2 " Marc Sune
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
  2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
@ 2015-08-28 23:20   ` Marc Sune
  2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
                       ` (2 more replies)
  2 siblings, 3 replies; 64+ messages in thread
From: Marc Sune @ 2015-08-28 23:20 UTC (permalink / raw)
  To: dev; +Cc: Marc Sune

From: Marc Sune <marcdevel@gmail.de>

The current rte_eth_dev_info abstraction does not provide any mechanism to
get the supported speed(s) of an ethdev.

For some drivers (e.g. ixgbe), an educated guess can be done based on the
driver's name (driver_name in rte_eth_dev_info), see:

http://dpdk.org/ml/archives/dev/2013-August/000412.html

However, i) doing string comparisons is annoying, and can silently
break existing applications if PMDs change their names ii) it does not
provide all the supported capabilities of the ethdev iii) for some drivers it
is impossible determine correctly the (max) speed by the application
(e.g. in i40, distinguish between XL710 and X710).

This small patch adds speed_capa bitmap in rte_eth_dev_info, which is filled
by the PMDs according to the physical device capabilities.

v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
(checkpatch).

v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into ETH_SPEED.
    Converted field speed in struct rte_eth_link to speed, to allow a bitmap
    for defining the announced speeds, as suggested M. Brorup. Fixed spelling
    issues.

Marc Sune (2):
  Added ETH_SPEED_ bitmap in rte_eth_dev_info
  Filling speed capability bitmaps in the PMDs

 app/test-pmd/cmdline.c                    | 32 +++++++++++------------
 app/test/virtual_pmd.c                    |  2 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c | 14 +++++------
 drivers/net/e1000/em_ethdev.c             | 20 +++++++++------
 drivers/net/e1000/igb_ethdev.c            | 20 +++++++++------
 drivers/net/fm10k/fm10k_ethdev.c          |  3 +++
 drivers/net/i40e/i40e_ethdev.c            | 37 ++++++++++++++++-----------
 drivers/net/i40e/i40e_ethdev_vf.c         |  2 +-
 drivers/net/ixgbe/ixgbe_ethdev.c          | 32 +++++++++++++++--------
 drivers/net/mlx4/mlx4.c                   |  6 +++++
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  2 +-
 lib/librte_ether/rte_ethdev.h             | 42 ++++++++++++++++++++++---------
 12 files changed, 135 insertions(+), 77 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v3 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info
  2015-08-28 23:20   ` [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap Marc Sune
@ 2015-08-28 23:20     ` Marc Sune
  2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
  2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
  2 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-08-28 23:20 UTC (permalink / raw)
  To: dev; +Cc: Marc Sune

Currently there was no way to recover all the supported speeds of a certain
ether device.

This commit adds a speed capability bitmap to rte_eth_dev_info struct, to be
filled by PMDs. It also renames ETH_LINK_SPEED_XXX to ETH_SPEED, in order to
unify speed capabilities and link speeds. It also adds missing speeds to
ETH_SPEED.

The field speed in the struct rte_eth_link is now a bitmap and therefore is
renamed to speeds. This allows to specify a list of speeds to be announced
during autonegociation, as suggested by M. Brorup. Driver do not support yet
this capabilities.

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 app/test-pmd/cmdline.c                    | 32 +++++++++++------------
 app/test/virtual_pmd.c                    |  2 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c | 14 +++++------
 drivers/net/e1000/em_ethdev.c             | 14 +++++------
 drivers/net/e1000/igb_ethdev.c            | 14 +++++------
 drivers/net/i40e/i40e_ethdev.c            | 28 ++++++++++-----------
 drivers/net/i40e/i40e_ethdev_vf.c         |  2 +-
 drivers/net/ixgbe/ixgbe_ethdev.c          | 22 ++++++++--------
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  2 +-
 lib/librte_ether/rte_ethdev.h             | 42 ++++++++++++++++++++++---------
 10 files changed, 95 insertions(+), 77 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 8142910..8e131c7 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -898,7 +898,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 			__attribute__((unused)) void *data)
 {
 	struct cmd_config_speed_all *res = parsed_result;
-	uint16_t link_speed = ETH_LINK_SPEED_AUTONEG;
+	uint16_t link_speed = ETH_SPEED_AUTONEG;
 	uint16_t link_duplex = 0;
 	portid_t pid;
 
@@ -908,17 +908,17 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	if (!strcmp(res->value1, "10"))
-		link_speed = ETH_LINK_SPEED_10;
+		link_speed = ETH_SPEED_10M;
 	else if (!strcmp(res->value1, "100"))
-		link_speed = ETH_LINK_SPEED_100;
+		link_speed = ETH_SPEED_100M;
 	else if (!strcmp(res->value1, "1000"))
-		link_speed = ETH_LINK_SPEED_1000;
+		link_speed = ETH_SPEED_1G;
 	else if (!strcmp(res->value1, "10000"))
-		link_speed = ETH_LINK_SPEED_10G;
+		link_speed = ETH_SPEED_10G;
 	else if (!strcmp(res->value1, "40000"))
-		link_speed = ETH_LINK_SPEED_40G;
+		link_speed = ETH_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
-		link_speed = ETH_LINK_SPEED_AUTONEG;
+		link_speed = ETH_SPEED_AUTONEG;
 	else {
 		printf("Unknown parameter\n");
 		return;
@@ -936,7 +936,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	FOREACH_PORT(pid, ports) {
-		ports[pid].dev_conf.link_speed = link_speed;
+		ports[pid].dev_conf.link_speeds = link_speed;
 		ports[pid].dev_conf.link_duplex = link_duplex;
 	}
 
@@ -995,7 +995,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_speed = ETH_SPEED_AUTONEG;
 	uint16_t link_duplex = 0;
 
 	if (!all_ports_stopped()) {
@@ -1007,17 +1007,17 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 		return;
 
 	if (!strcmp(res->value1, "10"))
-		link_speed = ETH_LINK_SPEED_10;
+		link_speed = ETH_SPEED_10M;
 	else if (!strcmp(res->value1, "100"))
-		link_speed = ETH_LINK_SPEED_100;
+		link_speed = ETH_SPEED_100M;
 	else if (!strcmp(res->value1, "1000"))
-		link_speed = ETH_LINK_SPEED_1000;
+		link_speed = ETH_SPEED_1G;
 	else if (!strcmp(res->value1, "10000"))
-		link_speed = ETH_LINK_SPEED_10000;
+		link_speed = ETH_SPEED_10G;
 	else if (!strcmp(res->value1, "40000"))
-		link_speed = ETH_LINK_SPEED_40G;
+		link_speed = ETH_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
-		link_speed = ETH_LINK_SPEED_AUTONEG;
+		link_speed = ETH_SPEED_AUTONEG;
 	else {
 		printf("Unknown parameter\n");
 		return;
@@ -1034,7 +1034,7 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 		return;
 	}
 
-	ports[res->id].dev_conf.link_speed = link_speed;
+	ports[res->id].dev_conf.link_speeds = link_speed;
 	ports[res->id].dev_conf.link_duplex = link_duplex;
 
 	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index a538c8a..2167807 100644
--- a/app/test/virtual_pmd.c
+++ b/app/test/virtual_pmd.c
@@ -604,7 +604,7 @@ 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_speed = ETH_SPEED_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/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index 97a828e..202d811 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_AUTONEG:
 		key_speed = 0x00;
 		break;
-	case ETH_LINK_SPEED_10:
+	case ETH_SPEED_10M:
 		key_speed = BOND_LINK_SPEED_KEY_10M;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		key_speed = BOND_LINK_SPEED_KEY_100M;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		key_speed = BOND_LINK_SPEED_KEY_1000M;
 		break;
-	case ETH_LINK_SPEED_10G:
+	case ETH_SPEED_10G:
 		key_speed = BOND_LINK_SPEED_KEY_10G;
 		break;
-	case ETH_LINK_SPEED_20G:
+	case ETH_SPEED_20G:
 		key_speed = BOND_LINK_SPEED_KEY_20G;
 		break;
-	case ETH_LINK_SPEED_40G:
+	case ETH_SPEED_40G:
 		key_speed = BOND_LINK_SPEED_KEY_40G;
 		break;
 	default:
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index a306c55..5ca1830 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -508,8 +508,8 @@ 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:
+	switch (dev->data->dev_conf.link_speeds) {
+	case ETH_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 ==
@@ -521,7 +521,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10:
+	case ETH_SPEED_10M:
 		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 ==
@@ -533,7 +533,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		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 ==
@@ -545,7 +545,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		if ((dev->data->dev_conf.link_duplex ==
 				ETH_LINK_AUTONEG_DUPLEX) ||
 			(dev->data->dev_conf.link_duplex ==
@@ -554,7 +554,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10000:
+	case ETH_SPEED_10G:
 	default:
 		goto error_invalid_config;
 	}
@@ -576,7 +576,7 @@ eth_em_start(struct rte_eth_dev *dev)
 
 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_speeds,
 		     dev->data->dev_conf.link_duplex, dev->data->port_id);
 	em_dev_clear_queues(dev);
 	return (-EINVAL);
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 24c7510..7c5e952 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -857,8 +857,8 @@ 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:
+	switch (dev->data->dev_conf.link_speeds) {
+	case ETH_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)
@@ -868,7 +868,7 @@ eth_igb_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10:
+	case ETH_SPEED_10M:
 		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)
@@ -878,7 +878,7 @@ eth_igb_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		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)
@@ -888,14 +888,14 @@ eth_igb_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		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
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10000:
+	case ETH_SPEED_10G:
 	default:
 		goto error_invalid_config;
 	}
@@ -914,7 +914,7 @@ eth_igb_start(struct rte_eth_dev *dev)
 
 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_speeds,
 		     dev->data->dev_conf.link_duplex, dev->data->port_id);
 	igb_dev_clear_queues(dev);
 	return (-EINVAL);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2ada502..056b081 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -756,19 +756,19 @@ i40e_parse_link_speed(uint16_t eth_link_speed)
 	uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN;
 
 	switch (eth_link_speed) {
-	case ETH_LINK_SPEED_40G:
+	case ETH_SPEED_40G:
 		link_speed = I40E_LINK_SPEED_40GB;
 		break;
-	case ETH_LINK_SPEED_20G:
+	case ETH_SPEED_20G:
 		link_speed = I40E_LINK_SPEED_20GB;
 		break;
-	case ETH_LINK_SPEED_10G:
+	case ETH_SPEED_10G:
 		link_speed = I40E_LINK_SPEED_10GB;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		link_speed = I40E_LINK_SPEED_1GB;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		link_speed = I40E_LINK_SPEED_100MB;
 		break;
 	}
@@ -840,9 +840,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_speed(conf->link_speeds);
 	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
-	if (conf->link_speed == ETH_LINK_SPEED_AUTONEG)
+	if (conf->link_speeds == ETH_SPEED_AUTONEG)
 		abilities |= I40E_AQ_PHY_AN_ENABLED;
 	else
 		abilities |= I40E_AQ_PHY_LINK_ENABLED;
@@ -1104,7 +1104,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_100M;
 			link.link_duplex = ETH_LINK_FULL_DUPLEX;
 			PMD_DRV_LOG(ERR, "Failed to get link info");
 			goto out;
@@ -1126,22 +1126,22 @@ 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_100M;
 		break;
 	case I40E_LINK_SPEED_1GB:
-		link.link_speed = ETH_LINK_SPEED_1000;
+		link.link_speed = ETH_SPEED_1G;
 		break;
 	case I40E_LINK_SPEED_10GB:
-		link.link_speed = ETH_LINK_SPEED_10G;
+		link.link_speed = ETH_SPEED_10G;
 		break;
 	case I40E_LINK_SPEED_20GB:
-		link.link_speed = ETH_LINK_SPEED_20G;
+		link.link_speed = ETH_SPEED_20G;
 		break;
 	case I40E_LINK_SPEED_40GB:
-		link.link_speed = ETH_LINK_SPEED_40G;
+		link.link_speed = ETH_SPEED_40G;
 		break;
 	default:
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		break;
 	}
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index f7332e7..013e358 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1592,7 +1592,7 @@ i40evf_dev_link_update(struct rte_eth_dev *dev,
 	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_speed  = ETH_SPEED_10G;
 		new_link.link_status = 1;
 	}
 	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 7414a2e..b2fcffc 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1534,28 +1534,28 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	if (err)
 		goto error;
 
-	switch(dev->data->dev_conf.link_speed) {
-	case ETH_LINK_SPEED_AUTONEG:
+	switch(dev->data->dev_conf.link_speeds) {
+	case ETH_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:
+	case ETH_SPEED_100M:
 		/*
 		 * Invalid for 82598 but error will be detected by
 		 * ixgbe_setup_link()
 		 */
 		speed = IXGBE_LINK_SPEED_100_FULL;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		speed = IXGBE_LINK_SPEED_1GB_FULL;
 		break;
-	case ETH_LINK_SPEED_10000:
+	case ETH_SPEED_10G:
 		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->dev_conf.link_speeds,
 			     dev->data->port_id);
 		goto error;
 	}
@@ -2134,7 +2134,7 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 	else
 		diag = ixgbe_check_link(hw, &link_speed, &link_up, 1);
 	if (diag != 0) {
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
 		rte_ixgbe_dev_atomic_write_link_status(dev, &link);
 		if (link.link_status == old.link_status)
@@ -2161,19 +2161,19 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 	default:
 	case IXGBE_LINK_SPEED_UNKNOWN:
 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		break;
 
 	case IXGBE_LINK_SPEED_100_FULL:
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		break;
 
 	case IXGBE_LINK_SPEED_1GB_FULL:
-		link.link_speed = ETH_LINK_SPEED_1000;
+		link.link_speed = ETH_SPEED_1G;
 		break;
 
 	case IXGBE_LINK_SPEED_10GB_FULL:
-		link.link_speed = ETH_LINK_SPEED_10000;
+		link.link_speed = ETH_SPEED_10G;
 		break;
 	}
 	rte_ixgbe_dev_atomic_write_link_status(dev, &link);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 59e3122..15af283 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -664,7 +664,7 @@ vmxnet3_dev_link_update(struct rte_eth_dev *dev, __attribute__((unused)) int wai
 	if (ret & 0x1) {
 		link.link_status = 1;
 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
-		link.link_speed = ETH_LINK_SPEED_10000;
+		link.link_speed = ETH_SPEED_10G;
 
 		rte_vmxnet3_dev_atomic_write_link_status(dev, &link);
 
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 04c192d..39ba789 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -227,23 +227,37 @@ struct rte_eth_stats {
 };
 
 /**
+ * Device supported speeds
+ */
+#define ETH_SPEED_AUTONEG	(0 << 0)  /*< Autonegociate speed  */
+#define ETH_SPEED_UNKNOWN	(0 << 0)  /*< No phy media  */
+#define ETH_SPEED_10M_HD	(1 << 0)  /*< 10 Mbps half-duplex */
+#define ETH_SPEED_10M		(1 << 1)  /*< 10 Mbps full-duplex */
+#define ETH_SPEED_100M_HD	(1 << 2)  /*< 100 Mbps half-duplex */
+#define ETH_SPEED_100M		(1 << 3)  /*< 100 Mbps full-duplex */
+#define ETH_SPEED_1G		(1 << 4)  /*< 1 Gbps */
+#define ETH_SPEED_2_5G		(1 << 5)  /*< 2.5 Gbps */
+#define ETH_SPEED_5G		(1 << 6)  /*< 5 Gbps */
+#define ETH_SPEED_10G		(1 << 7)  /*< 10 Mbps */
+#define ETH_SPEED_20G		(1 << 8)  /*< 20 Gbps */
+#define ETH_SPEED_25G		(1 << 9)  /*< 25 Gbps */
+#define ETH_SPEED_40G		(1 << 10)  /*< 40 Gbps */
+#define ETH_SPEED_50G		(1 << 11)  /*< 50 Gbps */
+#define ETH_SPEED_56G		(1 << 12)  /*< 56 Gbps */
+#define ETH_SPEED_100G		(1 << 13)  /*< 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_speed;      /**< ETH_SPEED_ bitmap (announce speeds) */
 	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. */
-
+/**
+ * Device link status
+ */
 #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. */
@@ -838,8 +852,8 @@ 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_speeds;
+	/**< bitmap of ETH_SPEED_XXX to be announced or 0 for autonegotation */
 	uint16_t link_duplex;
 	/**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for autonegotation */
 	struct rte_eth_rxmode rxmode; /**< Port RX configuration. */
@@ -900,6 +914,9 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_UDP_TSO     0x00000040
 #define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */
 
+/**
+ * Ethernet device information
+ */
 struct rte_eth_dev_info {
 	struct rte_pci_device *pci_dev; /**< Device PCI information. */
 	const char *driver_name; /**< Device Driver name. */
@@ -925,6 +942,7 @@ struct rte_eth_dev_info {
 	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
 	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
 	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
+	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_XXX). */
 };
 
 /** Maximum name length for extended statistics counters */
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v3 2/2] Filling speed capability bitmaps in the PMDs
  2015-08-28 23:20   ` [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
@ 2015-08-28 23:20     ` Marc Sune
  2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
  2 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-08-28 23:20 UTC (permalink / raw)
  To: dev; +Cc: Marc Sune

Added speed capabilities to all pmds supporting physical NICs:

* e1000
* ixgbe
* i40
* mlx4
* fm10k

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 drivers/net/e1000/em_ethdev.c    |  6 ++++++
 drivers/net/e1000/igb_ethdev.c   |  6 ++++++
 drivers/net/fm10k/fm10k_ethdev.c |  3 +++
 drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 drivers/net/mlx4/mlx4.c          |  6 ++++++
 6 files changed, 40 insertions(+)

diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 5ca1830..cd64843 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -888,6 +888,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	dev_info->max_rx_queues = 1;
 	dev_info->max_tx_queues = 1;
+
+	dev_info->speed_capa = ETH_SPEED_10M_HD |
+					ETH_SPEED_10M |
+					ETH_SPEED_100M_HD |
+					ETH_SPEED_100M |
+					ETH_SPEED_1G;
 }
 
 /* return 0 means link status changed, -1 means not changed */
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 7c5e952..d511400 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1404,6 +1404,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		},
 		.txq_flags = 0,
 	};
+
+	dev_info->speed_capa = ETH_SPEED_10M_HD |
+					ETH_SPEED_10M |
+					ETH_SPEED_100M_HD |
+					ETH_SPEED_100M |
+					ETH_SPEED_1G;
 }
 
 static void
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 4afd5ab..40b1dd1 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -791,6 +791,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
 				ETH_TXQ_FLAGS_NOOFFLOADS,
 	};
 
+	dev_info->speed_capa = ETH_SPEED_1G | ETH_SPEED_2_5G |
+					ETH_SPEED_10G | ETH_SPEED_25G |
+					ETH_SPEED_40G | ETH_SPEED_100G;
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 056b081..87b1840 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1519,6 +1519,7 @@ static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *vsi = pf->main_vsi;
 
 	dev_info->max_rx_queues = vsi->nb_qps;
@@ -1574,6 +1575,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
 	}
+
+	if (i40e_is_40G_device(hw->device_id))
+		/* For XL710 */
+		dev_info->speed_capa = ETH_SPEED_10G | ETH_SPEED_40G;
+	else
+		/* For X710 */
+		dev_info->speed_capa = ETH_SPEED_1G | ETH_SPEED_10G;
+
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b2fcffc..2e57a7c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -2060,6 +2060,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	};
 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
+
+	dev_info->speed_capa = ETH_SPEED_1G | ETH_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)
+
+		dev_info->speed_capa |= ETH_SPEED_100M |
+					ETH_SPEED_100M_HD;
 }
 
 static void
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index fde23e1..f3dbe58 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -3487,6 +3487,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 	info->max_rx_queues = max;
 	info->max_tx_queues = max;
 	info->max_mac_addrs = elemof(priv->mac);
+
+	info->speed_capa = ETH_SPEED_10G | ETH_SPEED_20G |
+					ETH_SPEED_25G | ETH_SPEED_40G |
+					ETH_SPEED_50G | ETH_SPEED_56G |
+					ETH_SPEED_100G;
+
 	priv_unlock(priv);
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-08-28 23:20   ` [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
  2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
@ 2015-08-29  0:16     ` Marc Sune
  2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
                         ` (3 more replies)
  2 siblings, 4 replies; 64+ messages in thread
From: Marc Sune @ 2015-08-29  0:16 UTC (permalink / raw)
  To: dev

The current rte_eth_dev_info abstraction does not provide any mechanism to
get the supported speed(s) of an ethdev.

For some drivers (e.g. ixgbe), an educated guess can be done based on the
driver's name (driver_name in rte_eth_dev_info), see:

http://dpdk.org/ml/archives/dev/2013-August/000412.html

However, i) doing string comparisons is annoying, and can silently
break existing applications if PMDs change their names ii) it does not
provide all the supported capabilities of the ethdev iii) for some drivers it
is impossible determine correctly the (max) speed by the application
(e.g. in i40, distinguish between XL710 and X710).

This small patch adds speed_capa bitmap in rte_eth_dev_info, which is filled
by the PMDs according to the physical device capabilities.

v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
(checkpatch).

v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into ETH_SPEED.
    Converted field speed in struct rte_eth_conf to speeds, to allow a bitmap
    for defining the announced speeds, as suggested by M. Brorup. Fixed
    spelling issues.

v4: fixed errata in the documentation of field speeds of rte_eth_conf, and
    commit 1/2 message. rebased to v2.1.0. v3 was incorrectly based on
    ~2.1.0-rc1.

Marc Sune (2):
  Added ETH_SPEED_ bitmap in rte_eth_dev_info
  Filling speed capability bitmaps in the PMDs

 app/test-pmd/cmdline.c                    | 32 +++++++++++------------
 app/test/virtual_pmd.c                    |  2 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c | 14 +++++-----
 drivers/net/cxgbe/base/t4_hw.c            |  8 +++---
 drivers/net/e1000/em_ethdev.c             | 20 +++++++++-----
 drivers/net/e1000/igb_ethdev.c            | 20 +++++++++-----
 drivers/net/fm10k/fm10k_ethdev.c          |  3 +++
 drivers/net/i40e/i40e_ethdev.c            | 43 +++++++++++++++++++------------
 drivers/net/i40e/i40e_ethdev_vf.c         |  2 +-
 drivers/net/ixgbe/ixgbe_ethdev.c          | 32 +++++++++++++++--------
 drivers/net/mlx4/mlx4.c                   |  6 +++++
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  2 +-
 lib/librte_ether/rte_ethdev.h             | 42 +++++++++++++++++++++---------
 13 files changed, 142 insertions(+), 84 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v4 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info
  2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
@ 2015-08-29  0:16       ` Marc Sune
  2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-08-29  0:16 UTC (permalink / raw)
  To: dev

Currently there was no way to recover all the supported speeds of a certain
ether device.

This commit adds a speed capability bitmap to rte_eth_dev_info struct, to be
filled by PMDs. It also renames ETH_LINK_SPEED_XXX to ETH_SPEED, in order to
unify speed capabilities and link speeds. It also adds missing speeds to
ETH_SPEED.

The field speed in the struct rte_eth_conf is now a bitmap and therefore is
renamed to speeds. This allows to specify a list of speeds to be announced
during autonegociation, as suggested by M. Brorup. Drivers do not support (yet)
this capability.

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 app/test-pmd/cmdline.c                    | 32 +++++++++++------------
 app/test/virtual_pmd.c                    |  2 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c | 14 +++++------
 drivers/net/cxgbe/base/t4_hw.c            |  8 +++---
 drivers/net/e1000/em_ethdev.c             | 14 +++++------
 drivers/net/e1000/igb_ethdev.c            | 14 +++++------
 drivers/net/i40e/i40e_ethdev.c            | 34 ++++++++++++-------------
 drivers/net/i40e/i40e_ethdev_vf.c         |  2 +-
 drivers/net/ixgbe/ixgbe_ethdev.c          | 22 ++++++++--------
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  2 +-
 examples/ip_pipeline/config_parse.c       |  2 +-
 lib/librte_ether/rte_ethdev.h             | 42 ++++++++++++++++++++++---------
 12 files changed, 103 insertions(+), 85 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5799c9c..053acf6 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -903,7 +903,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 			__attribute__((unused)) void *data)
 {
 	struct cmd_config_speed_all *res = parsed_result;
-	uint16_t link_speed = ETH_LINK_SPEED_AUTONEG;
+	uint16_t link_speed = ETH_SPEED_AUTONEG;
 	uint16_t link_duplex = 0;
 	portid_t pid;
 
@@ -913,17 +913,17 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	if (!strcmp(res->value1, "10"))
-		link_speed = ETH_LINK_SPEED_10;
+		link_speed = ETH_SPEED_10M;
 	else if (!strcmp(res->value1, "100"))
-		link_speed = ETH_LINK_SPEED_100;
+		link_speed = ETH_SPEED_100M;
 	else if (!strcmp(res->value1, "1000"))
-		link_speed = ETH_LINK_SPEED_1000;
+		link_speed = ETH_SPEED_1G;
 	else if (!strcmp(res->value1, "10000"))
-		link_speed = ETH_LINK_SPEED_10G;
+		link_speed = ETH_SPEED_10G;
 	else if (!strcmp(res->value1, "40000"))
-		link_speed = ETH_LINK_SPEED_40G;
+		link_speed = ETH_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
-		link_speed = ETH_LINK_SPEED_AUTONEG;
+		link_speed = ETH_SPEED_AUTONEG;
 	else {
 		printf("Unknown parameter\n");
 		return;
@@ -941,7 +941,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	FOREACH_PORT(pid, ports) {
-		ports[pid].dev_conf.link_speed = link_speed;
+		ports[pid].dev_conf.link_speeds = link_speed;
 		ports[pid].dev_conf.link_duplex = link_duplex;
 	}
 
@@ -1000,7 +1000,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_speed = ETH_SPEED_AUTONEG;
 	uint16_t link_duplex = 0;
 
 	if (!all_ports_stopped()) {
@@ -1012,17 +1012,17 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 		return;
 
 	if (!strcmp(res->value1, "10"))
-		link_speed = ETH_LINK_SPEED_10;
+		link_speed = ETH_SPEED_10M;
 	else if (!strcmp(res->value1, "100"))
-		link_speed = ETH_LINK_SPEED_100;
+		link_speed = ETH_SPEED_100M;
 	else if (!strcmp(res->value1, "1000"))
-		link_speed = ETH_LINK_SPEED_1000;
+		link_speed = ETH_SPEED_1G;
 	else if (!strcmp(res->value1, "10000"))
-		link_speed = ETH_LINK_SPEED_10000;
+		link_speed = ETH_SPEED_10G;
 	else if (!strcmp(res->value1, "40000"))
-		link_speed = ETH_LINK_SPEED_40G;
+		link_speed = ETH_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
-		link_speed = ETH_LINK_SPEED_AUTONEG;
+		link_speed = ETH_SPEED_AUTONEG;
 	else {
 		printf("Unknown parameter\n");
 		return;
@@ -1039,7 +1039,7 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 		return;
 	}
 
-	ports[res->id].dev_conf.link_speed = link_speed;
+	ports[res->id].dev_conf.link_speeds = link_speed;
 	ports[res->id].dev_conf.link_duplex = link_duplex;
 
 	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index a538c8a..2167807 100644
--- a/app/test/virtual_pmd.c
+++ b/app/test/virtual_pmd.c
@@ -604,7 +604,7 @@ 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_speed = ETH_SPEED_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/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index c0f0b99..c0097ec 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_AUTONEG:
 		key_speed = 0x00;
 		break;
-	case ETH_LINK_SPEED_10:
+	case ETH_SPEED_10M:
 		key_speed = BOND_LINK_SPEED_KEY_10M;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		key_speed = BOND_LINK_SPEED_KEY_100M;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		key_speed = BOND_LINK_SPEED_KEY_1000M;
 		break;
-	case ETH_LINK_SPEED_10G:
+	case ETH_SPEED_10G:
 		key_speed = BOND_LINK_SPEED_KEY_10G;
 		break;
-	case ETH_LINK_SPEED_20G:
+	case ETH_SPEED_20G:
 		key_speed = BOND_LINK_SPEED_KEY_20G;
 		break;
-	case ETH_LINK_SPEED_40G:
+	case ETH_SPEED_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..2ce08f1 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_100M;
 		else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-			speed = ETH_LINK_SPEED_1000;
+			speed = ETH_SPEED_1G;
 		else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-			speed = ETH_LINK_SPEED_10000;
+			speed = ETH_SPEED_10G;
 		else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
-			speed = ETH_LINK_SPEED_40G;
+			speed = ETH_SPEED_40G;
 
 		for_each_port(adap, i) {
 			pi = adap2pinfo(adap, i);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 912f5dd..f0216f9 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -547,8 +547,8 @@ 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:
+	switch (dev->data->dev_conf.link_speeds) {
+	case ETH_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 ==
@@ -560,7 +560,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10:
+	case ETH_SPEED_10M:
 		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 ==
@@ -572,7 +572,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		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 ==
@@ -584,7 +584,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		if ((dev->data->dev_conf.link_duplex ==
 				ETH_LINK_AUTONEG_DUPLEX) ||
 			(dev->data->dev_conf.link_duplex ==
@@ -593,7 +593,7 @@ eth_em_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10000:
+	case ETH_SPEED_10G:
 	default:
 		goto error_invalid_config;
 	}
@@ -617,7 +617,7 @@ eth_em_start(struct rte_eth_dev *dev)
 
 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_speeds,
 		     dev->data->dev_conf.link_duplex, dev->data->port_id);
 	em_dev_clear_queues(dev);
 	return (-EINVAL);
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index c7e6d55..25f1755 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -994,8 +994,8 @@ 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:
+	switch (dev->data->dev_conf.link_speeds) {
+	case ETH_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)
@@ -1005,7 +1005,7 @@ eth_igb_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10:
+	case ETH_SPEED_10M:
 		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)
@@ -1015,7 +1015,7 @@ eth_igb_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		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)
@@ -1025,14 +1025,14 @@ eth_igb_start(struct rte_eth_dev *dev)
 		else
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		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
 			goto error_invalid_config;
 		break;
-	case ETH_LINK_SPEED_10000:
+	case ETH_SPEED_10G:
 	default:
 		goto error_invalid_config;
 	}
@@ -1068,7 +1068,7 @@ eth_igb_start(struct rte_eth_dev *dev)
 
 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_speeds,
 		     dev->data->dev_conf.link_duplex, dev->data->port_id);
 	igb_dev_clear_queues(dev);
 	return (-EINVAL);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 40b0526..8f340cd 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -840,19 +840,19 @@ i40e_parse_link_speed(uint16_t eth_link_speed)
 	uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN;
 
 	switch (eth_link_speed) {
-	case ETH_LINK_SPEED_40G:
+	case ETH_SPEED_40G:
 		link_speed = I40E_LINK_SPEED_40GB;
 		break;
-	case ETH_LINK_SPEED_20G:
+	case ETH_SPEED_20G:
 		link_speed = I40E_LINK_SPEED_20GB;
 		break;
-	case ETH_LINK_SPEED_10G:
+	case ETH_SPEED_10G:
 		link_speed = I40E_LINK_SPEED_10GB;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		link_speed = I40E_LINK_SPEED_1GB;
 		break;
-	case ETH_LINK_SPEED_100:
+	case ETH_SPEED_100M:
 		link_speed = I40E_LINK_SPEED_100MB;
 		break;
 	}
@@ -924,9 +924,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_speed(conf->link_speeds);
 	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
-	if (conf->link_speed == ETH_LINK_SPEED_AUTONEG)
+	if (conf->link_speeds == ETH_SPEED_AUTONEG)
 		abilities |= I40E_AQ_PHY_AN_ENABLED;
 	else
 		abilities |= I40E_AQ_PHY_LINK_ENABLED;
@@ -1209,7 +1209,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_100M;
 			link.link_duplex = ETH_LINK_FULL_DUPLEX;
 			PMD_DRV_LOG(ERR, "Failed to get link info");
 			goto out;
@@ -1231,22 +1231,22 @@ 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_100M;
 		break;
 	case I40E_LINK_SPEED_1GB:
-		link.link_speed = ETH_LINK_SPEED_1000;
+		link.link_speed = ETH_SPEED_1G;
 		break;
 	case I40E_LINK_SPEED_10GB:
-		link.link_speed = ETH_LINK_SPEED_10G;
+		link.link_speed = ETH_SPEED_10G;
 		break;
 	case I40E_LINK_SPEED_20GB:
-		link.link_speed = ETH_LINK_SPEED_20G;
+		link.link_speed = ETH_SPEED_20G;
 		break;
 	case I40E_LINK_SPEED_40GB:
-		link.link_speed = ETH_LINK_SPEED_40G;
+		link.link_speed = ETH_SPEED_40G;
 		break;
 	default:
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		break;
 	}
 
@@ -6185,15 +6185,15 @@ i40e_timesync_enable(struct rte_eth_dev *dev)
 	uint32_t tsync_inc_h;
 
 	switch (link->link_speed) {
-	case ETH_LINK_SPEED_40G:
+	case ETH_SPEED_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_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_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 b694400..91a279e 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1640,7 +1640,7 @@ i40evf_dev_link_update(struct rte_eth_dev *dev,
 	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_speed  = ETH_SPEED_10G;
 		new_link.link_status = 1;
 	}
 	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 b8ee1e9..9b65d81 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1783,28 +1783,28 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	if (err)
 		goto error;
 
-	switch(dev->data->dev_conf.link_speed) {
-	case ETH_LINK_SPEED_AUTONEG:
+	switch(dev->data->dev_conf.link_speeds) {
+	case ETH_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:
+	case ETH_SPEED_100M:
 		/*
 		 * Invalid for 82598 but error will be detected by
 		 * ixgbe_setup_link()
 		 */
 		speed = IXGBE_LINK_SPEED_100_FULL;
 		break;
-	case ETH_LINK_SPEED_1000:
+	case ETH_SPEED_1G:
 		speed = IXGBE_LINK_SPEED_1GB_FULL;
 		break;
-	case ETH_LINK_SPEED_10000:
+	case ETH_SPEED_10G:
 		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->dev_conf.link_speeds,
 			     dev->data->port_id);
 		goto error;
 	}
@@ -2494,7 +2494,7 @@ 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_speed = ETH_SPEED_100M;
 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
 		rte_ixgbe_dev_atomic_write_link_status(dev, &link);
 		if (link.link_status == old.link_status)
@@ -2515,19 +2515,19 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 	default:
 	case IXGBE_LINK_SPEED_UNKNOWN:
 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		break;
 
 	case IXGBE_LINK_SPEED_100_FULL:
-		link.link_speed = ETH_LINK_SPEED_100;
+		link.link_speed = ETH_SPEED_100M;
 		break;
 
 	case IXGBE_LINK_SPEED_1GB_FULL:
-		link.link_speed = ETH_LINK_SPEED_1000;
+		link.link_speed = ETH_SPEED_1G;
 		break;
 
 	case IXGBE_LINK_SPEED_10GB_FULL:
-		link.link_speed = ETH_LINK_SPEED_10000;
+		link.link_speed = ETH_SPEED_10G;
 		break;
 	}
 	rte_ixgbe_dev_atomic_write_link_status(dev, &link);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index a70be5c..017241c 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -699,7 +699,7 @@ vmxnet3_dev_link_update(struct rte_eth_dev *dev, __attribute__((unused)) int wai
 	if (ret & 0x1) {
 		link.link_status = 1;
 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
-		link.link_speed = ETH_LINK_SPEED_10000;
+		link.link_speed = ETH_SPEED_1G;
 	}
 
 	vmxnet3_dev_atomic_write_link_status(dev, &link);
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index c9b78f9..61f45df 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -83,7 +83,7 @@ static const struct app_link_params link_params_default = {
 	.mac_addr = 0,
 
 	.conf = {
-		.link_speed = 0,
+		.link_speeds = 0,
 		.link_duplex = 0,
 		.rxmode = {
 			.mq_mode = ETH_MQ_RX_NONE,
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 544afe0..641207f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -238,23 +238,37 @@ struct rte_eth_stats {
 };
 
 /**
+ * Device supported speeds
+ */
+#define ETH_SPEED_AUTONEG	(0 << 0)  /*< Autonegociate speed  */
+#define ETH_SPEED_UNKNOWN	(0 << 0)  /*< No phy media  */
+#define ETH_SPEED_10M_HD	(1 << 0)  /*< 10 Mbps half-duplex */
+#define ETH_SPEED_10M		(1 << 1)  /*< 10 Mbps full-duplex */
+#define ETH_SPEED_100M_HD	(1 << 2)  /*< 100 Mbps half-duplex */
+#define ETH_SPEED_100M		(1 << 3)  /*< 100 Mbps full-duplex */
+#define ETH_SPEED_1G		(1 << 4)  /*< 1 Gbps */
+#define ETH_SPEED_2_5G		(1 << 5)  /*< 2.5 Gbps */
+#define ETH_SPEED_5G		(1 << 6)  /*< 5 Gbps */
+#define ETH_SPEED_10G		(1 << 7)  /*< 10 Mbps */
+#define ETH_SPEED_20G		(1 << 8)  /*< 20 Gbps */
+#define ETH_SPEED_25G		(1 << 9)  /*< 25 Gbps */
+#define ETH_SPEED_40G		(1 << 10)  /*< 40 Gbps */
+#define ETH_SPEED_50G		(1 << 11)  /*< 50 Gbps */
+#define ETH_SPEED_56G		(1 << 12)  /*< 56 Gbps */
+#define ETH_SPEED_100G		(1 << 13)  /*< 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_speed;      /**< Link speed ETH_SPEED_ */
 	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. */
-
+/**
+ * Device link status
+ */
 #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. */
@@ -857,8 +871,8 @@ 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_speeds;
+	/**< bitmap of ETH_SPEED_XXX to be announced or 0 for autonegotation */
 	uint16_t link_duplex;
 	/**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for autonegotation */
 	struct rte_eth_rxmode rxmode; /**< Port RX configuration. */
@@ -921,6 +935,9 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */
 #define DEV_TX_OFFLOAD_QINQ_INSERT 0x00000100
 
+/**
+ * Ethernet device information
+ */
 struct rte_eth_dev_info {
 	struct rte_pci_device *pci_dev; /**< Device PCI information. */
 	const char *driver_name; /**< Device Driver name. */
@@ -947,6 +964,7 @@ struct rte_eth_dev_info {
 	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
 	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
 	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
+	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_XXX). */
 };
 
 /** Maximum name length for extended statistics counters */
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v4 2/2] Filling speed capability bitmaps in the PMDs
  2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
@ 2015-08-29  0:16       ` Marc Sune
  2015-09-07 20:52       ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
  3 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-08-29  0:16 UTC (permalink / raw)
  To: dev

Added speed capabilities to all pmds supporting physical NICs:

* e1000
* ixgbe
* i40
* mlx4
* fm10k

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 drivers/net/e1000/em_ethdev.c    |  6 ++++++
 drivers/net/e1000/igb_ethdev.c   |  6 ++++++
 drivers/net/fm10k/fm10k_ethdev.c |  3 +++
 drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 drivers/net/mlx4/mlx4.c          |  6 ++++++
 6 files changed, 40 insertions(+)

diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index f0216f9..501e8b6 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -933,6 +933,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	dev_info->max_rx_queues = 1;
 	dev_info->max_tx_queues = 1;
+
+	dev_info->speed_capa = ETH_SPEED_10M_HD |
+					ETH_SPEED_10M |
+					ETH_SPEED_100M_HD |
+					ETH_SPEED_100M |
+					ETH_SPEED_1G;
 }
 
 /* return 0 means link status changed, -1 means not changed */
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 25f1755..a1c42e6 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1588,6 +1588,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		},
 		.txq_flags = 0,
 	};
+
+	dev_info->speed_capa = ETH_SPEED_10M_HD |
+					ETH_SPEED_10M |
+					ETH_SPEED_100M_HD |
+					ETH_SPEED_100M |
+					ETH_SPEED_1G;
 }
 
 static void
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index a69c990..875028e 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -964,6 +964,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
 				ETH_TXQ_FLAGS_NOOFFLOADS,
 	};
 
+	dev_info->speed_capa = ETH_SPEED_1G | ETH_SPEED_2_5G |
+					ETH_SPEED_10G | ETH_SPEED_25G |
+					ETH_SPEED_40G | ETH_SPEED_100G;
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8f340cd..0a535a2 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1624,6 +1624,7 @@ static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *vsi = pf->main_vsi;
 
 	dev_info->max_rx_queues = vsi->nb_qps;
@@ -1683,6 +1684,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
 	}
+
+	if (i40e_is_40G_device(hw->device_id))
+		/* For XL710 */
+		dev_info->speed_capa = ETH_SPEED_10G | ETH_SPEED_40G;
+	else
+		/* For X710 */
+		dev_info->speed_capa = ETH_SPEED_1G | ETH_SPEED_10G;
+
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 9b65d81..11ff5ea 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -2417,6 +2417,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->hash_key_size = IXGBE_HKEY_MAX_INDEX * sizeof(uint32_t);
 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
+
+	dev_info->speed_capa = ETH_SPEED_1G | ETH_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)
+
+		dev_info->speed_capa |= ETH_SPEED_100M |
+					ETH_SPEED_100M_HD;
 }
 
 static void
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index fa3cb7e..31f4970 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -3876,6 +3876,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 		  DEV_TX_OFFLOAD_UDP_CKSUM |
 		  DEV_TX_OFFLOAD_TCP_CKSUM) :
 		 0);
+
+	info->speed_capa = ETH_SPEED_10G | ETH_SPEED_20G |
+					ETH_SPEED_25G | ETH_SPEED_40G |
+					ETH_SPEED_50G | ETH_SPEED_56G |
+					ETH_SPEED_100G;
+
 	priv_unlock(priv);
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
  2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
  2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
@ 2015-09-07 20:52       ` Marc Sune
  2015-09-08 10:03         ` Nélio Laranjeiro
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
  3 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-09-07 20:52 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

2015-08-29 2:16 GMT+02:00 Marc Sune <marcdevel@gmail.com>:

> The current rte_eth_dev_info abstraction does not provide any mechanism to
> get the supported speed(s) of an ethdev.
>
> For some drivers (e.g. ixgbe), an educated guess can be done based on the
> driver's name (driver_name in rte_eth_dev_info), see:
>
> http://dpdk.org/ml/archives/dev/2013-August/000412.html
>
> However, i) doing string comparisons is annoying, and can silently
> break existing applications if PMDs change their names ii) it does not
> provide all the supported capabilities of the ethdev iii) for some drivers
> it
> is impossible determine correctly the (max) speed by the application
> (e.g. in i40, distinguish between XL710 and X710).
>
> This small patch adds speed_capa bitmap in rte_eth_dev_info, which is
> filled
> by the PMDs according to the physical device capabilities.
>
> v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
> (checkpatch).
>
> v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into
> ETH_SPEED.
>     Converted field speed in struct rte_eth_conf to speeds, to allow a
> bitmap
>     for defining the announced speeds, as suggested by M. Brorup. Fixed
>     spelling issues.
>
> v4: fixed errata in the documentation of field speeds of rte_eth_conf, and
>     commit 1/2 message. rebased to v2.1.0. v3 was incorrectly based on
>     ~2.1.0-rc1.
>

Thomas,

Since mostly you were commenting for v1 and v2; any opinion on this one?

Regards
marc


>
> Marc Sune (2):
>   Added ETH_SPEED_ bitmap in rte_eth_dev_info
>   Filling speed capability bitmaps in the PMDs
>
>  app/test-pmd/cmdline.c                    | 32 +++++++++++------------
>  app/test/virtual_pmd.c                    |  2 +-
>  drivers/net/bonding/rte_eth_bond_8023ad.c | 14 +++++-----
>  drivers/net/cxgbe/base/t4_hw.c            |  8 +++---
>  drivers/net/e1000/em_ethdev.c             | 20 +++++++++-----
>  drivers/net/e1000/igb_ethdev.c            | 20 +++++++++-----
>  drivers/net/fm10k/fm10k_ethdev.c          |  3 +++
>  drivers/net/i40e/i40e_ethdev.c            | 43
> +++++++++++++++++++------------
>  drivers/net/i40e/i40e_ethdev_vf.c         |  2 +-
>  drivers/net/ixgbe/ixgbe_ethdev.c          | 32 +++++++++++++++--------
>  drivers/net/mlx4/mlx4.c                   |  6 +++++
>  drivers/net/vmxnet3/vmxnet3_ethdev.c      |  2 +-
>  lib/librte_ether/rte_ethdev.h             | 42
> +++++++++++++++++++++---------
>  13 files changed, 142 insertions(+), 84 deletions(-)
>
> --
> 2.1.4
>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-07 20:52       ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
@ 2015-09-08 10:03         ` Nélio Laranjeiro
  2015-09-08 20:26           ` Marc Sune
  2015-09-09 13:10           ` Nélio Laranjeiro
  0 siblings, 2 replies; 64+ messages in thread
From: Nélio Laranjeiro @ 2015-09-08 10:03 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

On Mon, Sep 07, 2015 at 10:52:53PM +0200, Marc Sune wrote:
> 2015-08-29 2:16 GMT+02:00 Marc Sune <marcdevel@gmail.com>:
> 
> > The current rte_eth_dev_info abstraction does not provide any mechanism to
> > get the supported speed(s) of an ethdev.
> >
> > For some drivers (e.g. ixgbe), an educated guess can be done based on the
> > driver's name (driver_name in rte_eth_dev_info), see:
> >
> > http://dpdk.org/ml/archives/dev/2013-August/000412.html
> >
> > However, i) doing string comparisons is annoying, and can silently
> > break existing applications if PMDs change their names ii) it does not
> > provide all the supported capabilities of the ethdev iii) for some drivers
> > it
> > is impossible determine correctly the (max) speed by the application
> > (e.g. in i40, distinguish between XL710 and X710).
> >
> > This small patch adds speed_capa bitmap in rte_eth_dev_info, which is
> > filled
> > by the PMDs according to the physical device capabilities.
> >
> > v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
> > (checkpatch).
> >
> > v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into
> > ETH_SPEED.
> >     Converted field speed in struct rte_eth_conf to speeds, to allow a
> > bitmap
> >     for defining the announced speeds, as suggested by M. Brorup. Fixed
> >     spelling issues.
> >
> > v4: fixed errata in the documentation of field speeds of rte_eth_conf, and
> >     commit 1/2 message. rebased to v2.1.0. v3 was incorrectly based on
> >     ~2.1.0-rc1.
> >
> 
> Thomas,
> 
> Since mostly you were commenting for v1 and v2; any opinion on this one?
> 
> Regards
> marc

Hi Marc,

I have read your patches, and there are a few mistakes, for instance mlx4
(ConnectX-3 devices) does not support 100Gbps.

In addition, it seems your new bitmap does not support all kind of
speeds, take a look at the header of Ethtool, in the Linux kernel
(include/uapi/linux/ethtool.h) which already consumes 30bits without even
managing speeds above 56Gbps.  

It would be nice to keep the field to represent the real speed of the
link, in case it is not represented by the bitmap, it could be also
useful for aggregated links (bonding for instance).  The current API
already works this way, it just needs to be extended from 16 to 32 bit
to manage speed above 64Gbps.
 
>[...]

Nélio
-- 
Nélio Laranjeiro
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-08 10:03         ` Nélio Laranjeiro
@ 2015-09-08 20:26           ` Marc Sune
  2015-09-09 13:10           ` Nélio Laranjeiro
  1 sibling, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-09-08 20:26 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: dev

Neilo,


2015-09-08 12:03 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:

> On Mon, Sep 07, 2015 at 10:52:53PM +0200, Marc Sune wrote:
> > 2015-08-29 2:16 GMT+02:00 Marc Sune <marcdevel@gmail.com>:
> >
> > > The current rte_eth_dev_info abstraction does not provide any
> mechanism to
> > > get the supported speed(s) of an ethdev.
> > >
> > > For some drivers (e.g. ixgbe), an educated guess can be done based on
> the
> > > driver's name (driver_name in rte_eth_dev_info), see:
> > >
> > > http://dpdk.org/ml/archives/dev/2013-August/000412.html
> > >
> > > However, i) doing string comparisons is annoying, and can silently
> > > break existing applications if PMDs change their names ii) it does not
> > > provide all the supported capabilities of the ethdev iii) for some
> drivers
> > > it
> > > is impossible determine correctly the (max) speed by the application
> > > (e.g. in i40, distinguish between XL710 and X710).
> > >
> > > This small patch adds speed_capa bitmap in rte_eth_dev_info, which is
> > > filled
> > > by the PMDs according to the physical device capabilities.
> > >
> > > v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
> > > (checkpatch).
> > >
> > > v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into
> > > ETH_SPEED.
> > >     Converted field speed in struct rte_eth_conf to speeds, to allow a
> > > bitmap
> > >     for defining the announced speeds, as suggested by M. Brorup. Fixed
> > >     spelling issues.
> > >
> > > v4: fixed errata in the documentation of field speeds of rte_eth_conf,
> and
> > >     commit 1/2 message. rebased to v2.1.0. v3 was incorrectly based on
> > >     ~2.1.0-rc1.
> > >
> >
> > Thomas,
> >
> > Since mostly you were commenting for v1 and v2; any opinion on this one?
> >
> > Regards
> > marc
>
> Hi Marc,
>
> I have read your patches, and there are a few mistakes, for instance mlx4
> (ConnectX-3 devices) does not support 100Gbps.
>

When I circulated v1 and v2 I was kindly asking maintainers and reviewers
of the drivers to fix any mistakes in SPEED capabilities, since I was
taking the speeds from the online websites&catalogues. Some were fixed, but
apparently some were still missing. I will remove 100Gbps. Please circulate
any other error you have spotted.



>
> In addition, it seems your new bitmap does not support all kind of
> speeds, take a look at the header of Ethtool, in the Linux kernel
> (include/uapi/linux/ethtool.h) which already consumes 30bits without even
> managing speeds above 56Gbps.
>

The bitmaps you are referring is SUPPORTED_ and ADVERTISED_. These bitmaps
not only contain the speeds but PHY properties (e.g. BASE for ETH).

The intention of this patch was to expose speed capabilities, similar to
the bitmap SPEED_ in include/uapi/linux/ethtool.h, which as you see maps
closely to ETH_SPEED_ proposed in this patch.

I think the encoding of other things, like the exact model of the interface
and its PHY details should go somewhere else. But I might be wrong here, so
open to hear opinions.


>
> It would be nice to keep the field to represent the real speed of the
> link, in case it is not represented by the bitmap, it could be also
> useful for aggregated links (bonding for instance).  The current API
> already works this way, it just needs to be extended from 16 to 32 bit
> to manage speed above 64Gbps.
>

This patch does not remove rte_eth_link_get() API. It just changes the
encoding of speed in struct rte_eth_link, to have an homogeneous set of
constants with the speed capabilities bitmap, as discussed previously in
the thread (see Thomas comments). IOW, it returns now a single SPEED_ value
in the struct rte_eth_link's link_speed field.

Marc


>
> >[...]
>
> Nélio
> --
> Nélio Laranjeiro
> 6WIND
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-08 10:03         ` Nélio Laranjeiro
  2015-09-08 20:26           ` Marc Sune
@ 2015-09-09 13:10           ` Nélio Laranjeiro
  2015-09-09 13:33             ` Thomas Monjalon
  1 sibling, 1 reply; 64+ messages in thread
From: Nélio Laranjeiro @ 2015-09-09 13:10 UTC (permalink / raw)
  To: Marc Sune, Thomas Monjalon; +Cc: dev

Marc,

(making this discussion public again)

On Wed, Sep 09, 2015 at 12:07:01PM +0200, Marc Sune wrote:
> Hi Nelio
> 
> 2015-09-09 11:08 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:
> 
>     Marc,
> 
>     On Tue, Sep 08, 2015 at 10:24:36PM +0200, Marc Sune wrote:
>     > Neilo,
>     >
>     > 2015-09-08 12:03 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:
>     >
>     >     On Mon, Sep 07, 2015 at 10:52:53PM +0200, Marc Sune wrote:
>     >     > 2015-08-29 2:16 GMT+02:00 Marc Sune <marcdevel@gmail.com>:
>     >     >
>     >     > > The current rte_eth_dev_info abstraction does not provide any
>     mechanism
>     >     to
>     >     > > get the supported speed(s) of an ethdev.
>     >     > >
>     >     > > For some drivers (e.g. ixgbe), an educated guess can be done
>     based on
>     >     the
>     >     > > driver's name (driver_name in rte_eth_dev_info), see:
>     >     > >
>     >     > > http://dpdk.org/ml/archives/dev/2013-August/000412.html
>     >     > >
>     >     > > However, i) doing string comparisons is annoying, and can
>     silently
>     >     > > break existing applications if PMDs change their names ii) it
>     does not
>     >     > > provide all the supported capabilities of the ethdev iii) for
>     some
>     >     drivers
>     >     > > it
>     >     > > is impossible determine correctly the (max) speed by the
>     application
>     >     > > (e.g. in i40, distinguish between XL710 and X710).
>     >     > >
>     >     > > This small patch adds speed_capa bitmap in rte_eth_dev_info,
>     which is
>     >     > > filled
>     >     > > by the PMDs according to the physical device capabilities.
>     >     > >
>     >     > > v2: rebase, converted speed_capa into 32 bits bitmap, fixed
>     alignment
>     >     > > (checkpatch).
>     >     > >
>     >     > > v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into
>     >     > > ETH_SPEED.
>     >     > >     Converted field speed in struct rte_eth_conf to speeds, to
>     allow a
>     >     > > bitmap
>     >     > >     for defining the announced speeds, as suggested by M. Brorup.
>     Fixed
>     >     > >     spelling issues.
>     >     > >
>     >     > > v4: fixed errata in the documentation of field speeds of
>     rte_eth_conf,
>     >     and
>     >     > >     commit 1/2 message. rebased to v2.1.0. v3 was incorrectly
>     based on
>     >     > >     ~2.1.0-rc1.
>     >     > >
>     >     >
>     >     > Thomas,
>     >     >
>     >     > Since mostly you were commenting for v1 and v2; any opinion on this
>     one?
>     >     >
>     >     > Regards
>     >     > marc
>     >
>     >     Hi Marc,
>     >
>     >     I have read your patches, and there are a few mistakes, for instance
>     mlx4
>     >     (ConnectX-3 devices) does not support 100Gbps.
>     >
>     >
>     > When I circulated v1 and v2 I was kindly asking maintainers and reviewers
>     of
>     > the drivers to fix any mistakes in SPEED capabilities, since I was taking
>     the
>     > speeds from the online websites&catalogues. Some were fixed, but
>     apparently
>     > some were still missing. I will remove 100Gbps. Please circulate any
>     other
>     > error you have spotted.
> 
>     From Mellanox website:
>      - ConnectX-3 EN: 10/40/56Gb/s
>      - ConnectX-3 Pro EN 10GBASE-T: 10G/s
>      - ConnectX-3 Pro: EN 10/40/56GbE
>      - ConnectX-3 Pro Programmable: 10/40Gb/s
> 
>     This PMD works with any of the ConnectX-3 adapters, so the announce speed
>     should be 10/40/56Gb/s.
>    
> 
> 
> I will change this
>  
> 
>     >     In addition, it seems your new bitmap does not support all kind of
>     >     speeds, take a look at the header of Ethtool, in the Linux kernel
>     >     (include/uapi/linux/ethtool.h) which already consumes 30bits without
>     even
>     >     managing speeds above 56Gbps.
>     >
>     >
>     > The bitmaps you are referring is SUPPORTED_ and ADVERTISED_. These
>     bitmaps not
>     > only contain the speeds but PHY properties (e.g. BASE for ETH).
>     >
>     > The intention of this patch was to expose speed capabilities, similar to
>     the
>     > bitmap SPEED_ in include/uapi/linux/ethtool.h, which as you see maps
>     closely to
>     > ETH_SPEED_ proposed in this patch.
>     >
>     > I think the encoding of other things, like the exact model of the
>     interface and
>     > its PHY details should go somewhere else. But I might be wrong here, so
>     open to
>     > hear opinions.
> 
>     I understand the need to have capability fields, but I don't understand
>     why you want to mix speeds and duplex mode in something which was
>     previously only handling speeds.
> 
> 
> Please refer to the comments from Thomas. He was arguing the duplicity in
> speeds between link and capabilities was not necessary, hence patch v3 and 4
> are unifying. The reason why there is only 100 and 100_HD is because of that
> and the "solution" Thomas was proposing.
>
> I was originally doing as you suggested, separating them and not changing
> current APIs. There seems to be a consensus on that, so please reply back
> directly to Thomas for this.

Sorry, I did not follow the thread from the beginning, I only read from
V4 patch.
 
>     We now have redundant information in struct rte_eth_conf, whereas
>     that structure has a speed field which embeds the duplex mode and
>     a duplex field which does the same, which one should be used?
> 
> 
> There is only the RTE_SPEED_ now, so speeds are also setting this (the value
> RTE_SPEED_XX). Old constants have been removed.

It is not what I mean, inside the structure rte_eth_conf, there are two
fields:
  * link_speeds,
  * link_duplex.
  
The link_speeds contains a bitmap of ETH_SPEED_XXX, ETH_SPEED_ already
contains an information on the duplex mode, so the field "link_duplex"
becomes redundant.

>     >     It would be nice to keep the field to represent the real speed of the
>     >     link, in case it is not represented by the bitmap, it could be also
>     >     useful for aggregated links (bonding for instance).  The current API
>     >     already works this way, it just needs to be extended from 16 to 32
>     bit
>     >     to manage speed above 64Gbps.
>     >
>     >
>     > This patch does not remove rte_eth_link_get() API. It just changes the
>     encoding
>     > of speed in struct rte_eth_link, to have an homogeneous set of constants
>     with
>     > the speed capabilities bitmap, as discussed previously in the thread (see
>     > Thomas comments). IOW, it returns now a single SPEED_ value in the struct
>     > rte_eth_link's link_speed field.
> 
>     You change the coding of the speed field, but applications still expect
>     an integer, see port_infos_display function in app/test-pmd/config.c which
>     directly uses printf on rte_eth_link.speed field, there are other places
>     as well in PMDs (bn2x, bond, ...).
> 
> 
> Agree. This has been overlooked, thanks.
>  
>     This patch currently expects that everything uses a bitmap but it is not
>     the case.
> 
>     I don't understand the need to change the rte_eth_link.speed field
>     behavior to have the informations about the capability of the PHY, for
>     this are two distinct things:
>       - capability
>       - speed and duplex negotiated (or not).
> 
>     I suggest to drop the part of the patch which changes the behavior of
>     link_speed in struct rte_eth_link.
> 
> 
> So going back to v2?

I finally took a look at your V2 patch and the discussion which follows
between you and Thomas.

Take a look at the function bandwidth_left in
drivers/net/bonding/rte_eth_bond_pmd.c, it computes a bandwidth in
bits/s from the link_speed for each port present in the bond,
furthermore, it is computed each second in TLB or ALB mode.

Same situation if we need to display the aggregated speed to the user,
it is easier to sum the speed of each slave in the bond, instead of
computing a value from a bitmap to sum it in an integer.

I think V2 is better, maybe you can add a function to convert a single
bitmap value to the equivalent integer and get rid of ETH_SPEED_XXX macros.

Thomas what is your opinion?

-- 
Nélio Laranjeiro
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-09 13:10           ` Nélio Laranjeiro
@ 2015-09-09 13:33             ` Thomas Monjalon
  2015-09-13 19:14               ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Thomas Monjalon @ 2015-09-09 13:33 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: dev

2015-09-09 15:10, Nélio Laranjeiro:
> I think V2 is better, maybe you can add a function to convert a single
> bitmap value to the equivalent integer and get rid of ETH_SPEED_XXX macros.
> 
> Thomas what is your opinion?

Your proposal looks good Nelio.
Thanks

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-09 13:33             ` Thomas Monjalon
@ 2015-09-13 19:14               ` Marc Sune
  2015-09-13 21:18                 ` Thomas Monjalon
  0 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-09-13 19:14 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Thomas,

2015-09-09 15:33 GMT+02:00 Thomas Monjalon <thomas.monjalon@6wind.com>:

> 2015-09-09 15:10, Nélio Laranjeiro:
> > I think V2 is better, maybe you can add a function to convert a single
> > bitmap value to the equivalent integer and get rid of ETH_SPEED_XXX
> macros.
> >
> > Thomas what is your opinion?
>
> Your proposal looks good Nelio.
>

I am confused, specially since you were the one advocating for having a
unified set of constants for speeds (discussion in v2).

In any case, as I see it, if we want to address the comments of  M. Brorup:

http://comments.gmane.org/gmane.comp.networking.dpdk.devel/19664

we need bitmaps for rte_eth_conf link_speed to set the advertised speeds.

 857 struct rte_eth_conf {

 858         uint16_t link_speed;

 859         /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */

 860         uint16_t link_duplex;

Let me know if you really want to come back to v2 or not.

Marc


> Thanks
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-13 19:14               ` Marc Sune
@ 2015-09-13 21:18                 ` Thomas Monjalon
  2015-09-14 10:02                   ` Nélio Laranjeiro
  2015-09-14 10:52                   ` Morten Brørup
  0 siblings, 2 replies; 64+ messages in thread
From: Thomas Monjalon @ 2015-09-13 21:18 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev, Morten Brørup

2015-09-13 21:14, Marc Sune:
> 2015-09-09 15:33 GMT+02:00 Thomas Monjalon <thomas.monjalon@6wind.com>:
> > 2015-09-09 15:10, Nélio Laranjeiro:
> > > I think V2 is better, maybe you can add a function to convert a single
> > > bitmap value to the equivalent integer and get rid of ETH_SPEED_XXX
> > macros.
> > >
> > > Thomas what is your opinion?
> >
> > Your proposal looks good Nelio.
> 
> I am confused, specially since you were the one advocating for having a
> unified set of constants for speeds (discussion in v2).

Yes, my first thought was advocating an unification between capabilities and
negotiated link properties.
After I was convinced by Nelio's arguments: bitmap is good for capabilities
(especially to describe every capabilities in one field) but integer is better
for negotiated speed (especially for aggregated links).
Converting bitmap speed into integer should be easy to implement in a function.

> In any case, as I see it, if we want to address the comments of  M. Brorup:
> 
> http://comments.gmane.org/gmane.comp.networking.dpdk.devel/19664
> 
> we need bitmaps for rte_eth_conf link_speed to set the advertised speeds.

Yes I forgot this interesting comment. It is saying we need
	1/ capabilities
	2/ advertised modes (for auto-negotiation or fixed config)
	3/ negotiated mode
Previously we were focused only on 1/ and 3/.
2/ was only limited to a mode configured without negotiation and was using the
same field as 3/.
Maybe we should really have 3 different fields. 1/ and 2/ would use a bitmap.

> Let me know if you really want to come back to v2 or not.

It needs more discussion. What do you think of the above proposal?
What is the opinion of Nelio? Morten?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-13 21:18                 ` Thomas Monjalon
@ 2015-09-14 10:02                   ` Nélio Laranjeiro
  2015-09-14 10:52                   ` Morten Brørup
  1 sibling, 0 replies; 64+ messages in thread
From: Nélio Laranjeiro @ 2015-09-14 10:02 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, Morten Brørup

On Sun, Sep 13, 2015 at 11:18:33PM +0200, Thomas Monjalon wrote:
> 2015-09-13 21:14, Marc Sune:
> > 2015-09-09 15:33 GMT+02:00 Thomas Monjalon <thomas.monjalon@6wind.com>:
> > > 2015-09-09 15:10, Nélio Laranjeiro:
> > > > I think V2 is better, maybe you can add a function to convert a single
> > > > bitmap value to the equivalent integer and get rid of ETH_SPEED_XXX
> > > macros.
> > > >
> > > > Thomas what is your opinion?
> > >
> > > Your proposal looks good Nelio.
> > 
> > I am confused, specially since you were the one advocating for having a
> > unified set of constants for speeds (discussion in v2).
> 
> Yes, my first thought was advocating an unification between capabilities and
> negotiated link properties.
> After I was convinced by Nelio's arguments: bitmap is good for capabilities
> (especially to describe every capabilities in one field) but integer is better
> for negotiated speed (especially for aggregated links).
> Converting bitmap speed into integer should be easy to implement in a function.
> 
> > In any case, as I see it, if we want to address the comments of  M. Brorup:
> > 
> > http://comments.gmane.org/gmane.comp.networking.dpdk.devel/19664

I read it.

> > 
> > we need bitmaps for rte_eth_conf link_speed to set the advertised speeds.
> 
> Yes I forgot this interesting comment. It is saying we need
> 	1/ capabilities
> 	2/ advertised modes (for auto-negotiation or fixed config)
> 	3/ negotiated mode
> Previously we were focused only on 1/ and 3/.
> 2/ was only limited to a mode configured without negotiation and was using the
> same field as 3/.
> Maybe we should really have 3 different fields. 1/ and 2/ would use a bitmap.
> 
> > Let me know if you really want to come back to v2 or not.
> 
> It needs more discussion. What do you think of the above proposal?
> What is the opinion of Nelio? Morten?

I agree with Morten, and with this proposition (we should be possible to
disable some capabilities in the advertise field).

For that we should have those 3 fields:
  1/ Capability (as a bitmap),  necessary for the user to configure the
     behavior of the PHY.
  2/ Advertise (as a bitmap) to configure the PHY.
  3/ speed, duplex, status (as rte_eth_link structure), necessary to
     verify that the configuration corresponds to what has been set and
     for other purposes.

I still think Marc needs to go back to V2 and continue from this one.
And as Thomas suggested, he could have a function to get rid of the
double defines and use the sames ones for bitmap and non bitmap fields.

Just for information, before I started this discussion I have worked on
a patch to change the rte_eth_link.link_speed from 16 to 32 bit, I did
not pushed it because, it should be pushed afters Marc's one, and it
will need some rework after that.

-- 
Nélio Laranjeiro
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-13 21:18                 ` Thomas Monjalon
  2015-09-14 10:02                   ` Nélio Laranjeiro
@ 2015-09-14 10:52                   ` Morten Brørup
  2015-09-14 21:33                     ` Marc Sune
  1 sibling, 1 reply; 64+ messages in thread
From: Morten Brørup @ 2015-09-14 10:52 UTC (permalink / raw)
  To: Thomas Monjalon, Marc Sune; +Cc: dev

It is important to consider that a multipath link (bonding etc.) is not a physical link, but a logical link (built on top of multiple physical links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad, Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3 multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it doesn't make sense trying to impose physical link properties on a purely logical link. Likewise, it doesn't make sense to impose logical link properties on physical links. In other words: Don't consider bonding or any other logical link types when designing the PHY API.

I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY advertisements) should use the same definitions, specifically a bitmap field. And when you disregard bonding, I don't see any reason to use different definitions for 3/ (PHY negotiation result). This makes it one unified API for all three purposes.

Nelio suggested adding a support function to convert the bitmap field to a speed value as an integer. I strongly support this, because you cannot expect the bitmap to be ordered by speed. This support function will be able to determine which speed is higher when exotic speeds are added to the bitmap. Please extend this conversion function to give three output parameters: speed, full/half duplex, auto negotiation/non-auto negotiation, or add two separate functions to get the duplex and auto-negotiation.

I haven't read the suggested code, but there should be some means in 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the bitmap to indicate if the speed/duplex-indicating bits in the bitmap means forced speed/duplex (in which case only a single speed/duplex-bit should be set) or auto negotiation advertised speed/duplex (in which case multiple speed/duplex-bits can be set). And some means in 3/ (result) and maybe 2/ (advertisements) to select and/or indicate physical interface in dual-personality ports (e.g. ports where the PHY has both an SFP and a RJ45 connector, but only one of the two can be used at any time).


Med venlig hilsen / kind regards
- Morten Brørup

-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] 
Sent: 13. september 2015 23:19
To: Marc Sune
Cc: Nélio Laranjeiro; dev@dpdk.org; Olga Shern; Adrien Mazarguil; Morten Brørup
Subject: Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap

2015-09-13 21:14, Marc Sune:
> 2015-09-09 15:33 GMT+02:00 Thomas Monjalon <thomas.monjalon@6wind.com>:
> > 2015-09-09 15:10, Nélio Laranjeiro:
> > > I think V2 is better, maybe you can add a function to convert a 
> > > single bitmap value to the equivalent integer and get rid of 
> > > ETH_SPEED_XXX
> > macros.
> > >
> > > Thomas what is your opinion?
> >
> > Your proposal looks good Nelio.
> 
> I am confused, specially since you were the one advocating for having 
> a unified set of constants for speeds (discussion in v2).

Yes, my first thought was advocating an unification between capabilities and negotiated link properties.
After I was convinced by Nelio's arguments: bitmap is good for capabilities (especially to describe every capabilities in one field) but integer is better for negotiated speed (especially for aggregated links).
Converting bitmap speed into integer should be easy to implement in a function.

> In any case, as I see it, if we want to address the comments of  M. Brorup:
> 
> http://comments.gmane.org/gmane.comp.networking.dpdk.devel/19664
> 
> we need bitmaps for rte_eth_conf link_speed to set the advertised speeds.

Yes I forgot this interesting comment. It is saying we need
	1/ capabilities
	2/ advertised modes (for auto-negotiation or fixed config)
	3/ negotiated mode
Previously we were focused only on 1/ and 3/.
2/ was only limited to a mode configured without negotiation and was using the same field as 3/.
Maybe we should really have 3 different fields. 1/ and 2/ would use a bitmap.

> Let me know if you really want to come back to v2 or not.

It needs more discussion. What do you think of the above proposal?
What is the opinion of Nelio? Morten?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-14 10:52                   ` Morten Brørup
@ 2015-09-14 21:33                     ` Marc Sune
  2015-09-14 22:50                       ` Morten Brørup
                                         ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Marc Sune @ 2015-09-14 21:33 UTC (permalink / raw)
  To: Morten Brørup; +Cc: dev

2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:

> It is important to consider that a multipath link (bonding etc.) is not a
> physical link, but a logical link (built on top of multiple physical
> links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad,
> Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3
> multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it
> doesn't make sense trying to impose physical link properties on a purely
> logical link. Likewise, it doesn't make sense to impose logical link
> properties on physical links. In other words: Don't consider bonding or any
> other logical link types when designing the PHY API.
>

+1


>
> I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY
> advertisements) should use the same definitions, specifically a bitmap
> field. And when you disregard bonding, I don't see any reason to use
> different definitions for 3/ (PHY negotiation result). This makes it one
> unified API for all three purposes.
>

Agree.


>
> Nelio suggested adding a support function to convert the bitmap field to a
> speed value as an integer. I strongly support this, because you cannot
> expect the bitmap to be ordered by speed.


Agree with Nelio&you. This is useful.


> This support function will be able to determine which speed is higher when
> exotic speeds are added to the bitmap. Please extend this conversion
> function to give three output parameters: speed, full/half duplex, auto
> negotiation/non-auto negotiation, or add two separate functions to get the
> duplex and auto-negotiation.
>

Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my
doubts on using a bit for all speeds. I would suggest to define (unroll)
100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was
suggesting some mails ago.

This was done in v4 (implicitely 100M == 100M_FD). See below.


>
> I haven't read the suggested code, but there should be some means in 2/
> (advertisements) to disable auto negotiation, e.g. a single bit in the
> bitmap to indicate if the speed/duplex-indicating bits in the bitmap means
> forced speed/duplex (in which case only a single speed/duplex-bit should be
> set) or auto negotiation advertised speed/duplex (in which case multiple
> speed/duplex-bits can be set).


Agree.

v3/4 of this patch adds the bitmap in the advertised, as per discussed, to
select a group of speeds This is not implemented by drivers yet (!).

So, as of v4 of this patch, there could be: a) autoneg any supported speed
(=> bitmap == 0) b) autoneg over group of speeds (=> more than one bit set
in the bitmap) c) forced speed (one and only one set in the bitmap).

I think this is precisely what you meant + b) as a bonus


> And some means in 3/ (result) and maybe 2/ (advertisements) to select
> and/or indicate physical interface in dual-personality ports (e.g. ports
> where the PHY has both an SFP and a RJ45 connector, but only one of the two
> can be used at any time).
>
>
For rte_eth_link_get() I don't have such a strong opinion. You either

* encode the link speed and duplex as of now, separating duplex and numeric
speed. I would suggest to add the encoded speed+duplex bitmap flag for
consistency (although redundant).
* or you return a single value, the bitmap with a single flag set of the
unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int
val_bm) and bool rte_eth_duplex_from_bm(int val_bm).


Marc


>
> Med venlig hilsen / kind regards
> - Morten Brørup
>
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: 13. september 2015 23:19
> To: Marc Sune
> Cc: Nélio Laranjeiro; dev@dpdk.org; Olga Shern; Adrien Mazarguil; Morten
> Brørup
> Subject: Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability
> bitmap
>
> 2015-09-13 21:14, Marc Sune:
> > 2015-09-09 15:33 GMT+02:00 Thomas Monjalon <thomas.monjalon@6wind.com>:
> > > 2015-09-09 15:10, Nélio Laranjeiro:
> > > > I think V2 is better, maybe you can add a function to convert a
> > > > single bitmap value to the equivalent integer and get rid of
> > > > ETH_SPEED_XXX
> > > macros.
> > > >
> > > > Thomas what is your opinion?
> > >
> > > Your proposal looks good Nelio.
> >
> > I am confused, specially since you were the one advocating for having
> > a unified set of constants for speeds (discussion in v2).
>
> Yes, my first thought was advocating an unification between capabilities
> and negotiated link properties.
> After I was convinced by Nelio's arguments: bitmap is good for
> capabilities (especially to describe every capabilities in one field) but
> integer is better for negotiated speed (especially for aggregated links).
> Converting bitmap speed into integer should be easy to implement in a
> function.
>
> > In any case, as I see it, if we want to address the comments of  M.
> Brorup:
> >
> > http://comments.gmane.org/gmane.comp.networking.dpdk.devel/19664
> >
> > we need bitmaps for rte_eth_conf link_speed to set the advertised speeds.
>
> Yes I forgot this interesting comment. It is saying we need
>         1/ capabilities
>         2/ advertised modes (for auto-negotiation or fixed config)
>         3/ negotiated mode
> Previously we were focused only on 1/ and 3/.
> 2/ was only limited to a mode configured without negotiation and was using
> the same field as 3/.
> Maybe we should really have 3 different fields. 1/ and 2/ would use a
> bitmap.
>
> > Let me know if you really want to come back to v2 or not.
>
> It needs more discussion. What do you think of the above proposal?
> What is the opinion of Nelio? Morten?
>
>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-14 21:33                     ` Marc Sune
@ 2015-09-14 22:50                       ` Morten Brørup
  2015-09-15  8:25                         ` Nélio Laranjeiro
  2015-09-15  7:05                       ` Thomas Monjalon
  2015-09-15  9:06                       ` Morten Brørup
  2 siblings, 1 reply; 64+ messages in thread
From: Morten Brørup @ 2015-09-14 22:50 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

Comments inline, marked MB>.

Med venlig hilsen / kind regards
- Morten Brørup

Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:

2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> It is important to consider that a multipath link (bonding etc.) is not a physical link, but a logical link (built on top of multiple physical links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad, Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3 multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it doesn't make sense trying to impose physical link properties on a purely logical link. Likewise, it doesn't make sense to impose logical link properties on physical links. In other words: Don't consider bonding or any other logical link types when designing the PHY API.

+1
 

> I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY advertisements) should use the same definitions, specifically a bitmap field. And when you disregard bonding, I don't see any reason to use different definitions for 3/ (PHY negotiation result). This makes it one unified API for all three purposes.

Agree.
 

> Nelio suggested adding a support function to convert the bitmap field to a speed value as an integer. I strongly support this, because you cannot expect the bitmap to be ordered by speed. 

Agree with Nelio&you. This is useful.
 
> This support function will be able to determine which speed is higher when exotic speeds are added to the bitmap. Please extend this conversion function to give three output parameters: speed, full/half duplex, auto negotiation/non-auto negotiation, or add two separate functions to get the duplex and auto-negotiation.

Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my doubts on using a bit for all speeds. I would suggest to define (unroll) 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was suggesting some mails ago.

This was done in v4 (implicitely 100M == 100M_FD). See below.
 
MB> I didn't intend two bits to be allocated in the bitmap for all speeds to support full/half duplex, only for the relevant speeds. Since full duplex is dominant, I agree with the previous decision (originally suggested by Thomas, I think) to make full duplex implicit unless half duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD), 100M_HD, 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.


> I haven't read the suggested code, but there should be some means in 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the bitmap to indicate if the speed/duplex-indicating bits in the bitmap means forced speed/duplex (in which case only a single speed/duplex-bit should be set) or auto negotiation advertised speed/duplex (in which case multiple speed/duplex-bits can be set). 

Agree.

v3/4 of this patch adds the bitmap in the advertised, as per discussed, to select a group of speeds This is not implemented by drivers yet (!).

So, as of v4 of this patch, there could be: a) autoneg any supported speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than one bit set in the bitmap) c) forced speed (one and only one set in the bitmap).

I think this is precisely what you meant + b) as a bonus

MB> This was not what I meant, but it wasn't very clearly written, so I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever you want to name it) to the 2/ (advertisements) bitmap that explicitly turns off auto negotiation and tries to force the selected speed/duplex (i.e. only one other bit can be set in the bitmap when the NO_AUTONEG bit is set). Your c) makes it impossible to use auto negotiation to advertise a specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can also be used in 3/ (result) to indicate that the speed was a result of Parallel Detection, i.e. that auto negotiation failed or was disabled in either end of the link.

MB> However, I like your suggestion a).

 
> And some means in 3/ (result) and maybe 2/ (advertisements) to select and/or indicate physical interface in dual-personality ports (e.g. ports where the PHY has both an SFP and a RJ45 connector, but only one of the two can be used at any time).

For rte_eth_link_get() I don't have such a strong opinion. You either

* encode the link speed and duplex as of now, separating duplex and numeric speed. I would suggest to add the encoded speed+duplex bitmap flag for consistency (although redundant).
* or you return a single value, the bitmap with a single flag set of the unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int val_bm) and bool rte_eth_duplex_from_bm(int val_bm).

MB> I prefer the latter of the two, only because it makes 3/ (result) consistent with 1/ (capabilities) and 2/ (advertisements).


Marc


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-14 21:33                     ` Marc Sune
  2015-09-14 22:50                       ` Morten Brørup
@ 2015-09-15  7:05                       ` Thomas Monjalon
  2015-09-15  7:33                         ` Morten Brørup
  2015-09-15  9:06                       ` Morten Brørup
  2 siblings, 1 reply; 64+ messages in thread
From: Thomas Monjalon @ 2015-09-15  7:05 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev, Morten Brørup

2015-09-14 23:33, Marc Sune:
> 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > This support function will be able to determine which speed is higher when
> > exotic speeds are added to the bitmap. Please extend this conversion
> > function to give three output parameters: speed, full/half duplex, auto
> > negotiation/non-auto negotiation, or add two separate functions to get the
> > duplex and auto-negotiation.
> 
> Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my
> doubts on using a bit for all speeds. I would suggest to define (unroll)
> 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was
> suggesting some mails ago.
> 
> This was done in v4 (implicitely 100M == 100M_FD). See below.

Are we going to use DPDK for such low speeds?
Maybe we can remove half duplex modes?

[...]
> So, as of v4 of this patch, there could be: a) autoneg any supported speed
> (=> bitmap == 0) b) autoneg over group of speeds (=> more than one bit set
> in the bitmap) c) forced speed (one and only one set in the bitmap).

+1

[...]
> * encode the link speed and duplex as of now, separating duplex and numeric
> speed. I would suggest to add the encoded speed+duplex bitmap flag for
> consistency (although redundant).
> * or you return a single value, the bitmap with a single flag set of the
> unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int
> val_bm) and bool rte_eth_duplex_from_bm(int val_bm).

Who has already used half duplex mode with DPDK?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15  7:05                       ` Thomas Monjalon
@ 2015-09-15  7:33                         ` Morten Brørup
  0 siblings, 0 replies; 64+ messages in thread
From: Morten Brørup @ 2015-09-15  7:33 UTC (permalink / raw)
  To: Thomas Monjalon, Marc Sune; +Cc: dev

Very valid question, Thomas. It's always a good idea to take a step back and look at the bigger picture!

Unfortunately, I can mention at least one company that has network appliances in production using such low speeds, and even half duplex: ours (SmartShare Systems). Basing our appliances on DPDK does not change this situation.

When you ship a lot of network appliances to a variety of customers, some of the appliances will eventually end up at customers who connects one of the ports to some equipment which is either very old, or which is configured for forced speed/duplex due to their old IT policy which hasn't been updated for decades. With a sufficient number customers, you are going to see everything possible! Reality surpasses imagination.


Med venlig hilsen / kind regards
- Morten Brørup

-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] 
Sent: 15. september 2015 09:05
To: Marc Sune
Cc: Morten Brørup; Nélio Laranjeiro; dev@dpdk.org; Olga Shern; Adrien Mazarguil
Subject: Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap

2015-09-14 23:33, Marc Sune:
> 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > This support function will be able to determine which speed is 
> > higher when exotic speeds are added to the bitmap. Please extend 
> > this conversion function to give three output parameters: speed, 
> > full/half duplex, auto negotiation/non-auto negotiation, or add two 
> > separate functions to get the duplex and auto-negotiation.
> 
> Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have 
> my doubts on using a bit for all speeds. I would suggest to define 
> (unroll) 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as 
> Thomas was suggesting some mails ago.
> 
> This was done in v4 (implicitely 100M == 100M_FD). See below.

Are we going to use DPDK for such low speeds?
Maybe we can remove half duplex modes?

[...]
> So, as of v4 of this patch, there could be: a) autoneg any supported 
> speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than 
> one bit set in the bitmap) c) forced speed (one and only one set in the bitmap).

+1

[...]
> * encode the link speed and duplex as of now, separating duplex and 
> numeric speed. I would suggest to add the encoded speed+duplex bitmap 
> flag for consistency (although redundant).
> * or you return a single value, the bitmap with a single flag set of 
> the unrolled speeds, and then have the helpers int 
> rte_eth_speed_from_bm(int
> val_bm) and bool rte_eth_duplex_from_bm(int val_bm).

Who has already used half duplex mode with DPDK?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-14 22:50                       ` Morten Brørup
@ 2015-09-15  8:25                         ` Nélio Laranjeiro
  2015-09-15  8:48                           ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Nélio Laranjeiro @ 2015-09-15  8:25 UTC (permalink / raw)
  To: Morten Brørup; +Cc: dev

On Tue, Sep 15, 2015 at 12:50:11AM +0200, Morten Brørup wrote:
> Comments inline, marked MB>.
> 
> Med venlig hilsen / kind regards
> - Morten Brørup
> 
> Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:
> 
> 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > It is important to consider that a multipath link (bonding etc.) is not a physical link, but a logical link (built on top of multiple physical links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad, Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3 multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it doesn't make sense trying to impose physical link properties on a purely logical link. Likewise, it doesn't make sense to impose logical link properties on physical links. In other words: Don't consider bonding or any other logical link types when designing the PHY API.
> 
> +1

+1.

>  
> 
> > I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY advertisements) should use the same definitions, specifically a bitmap field. And when you disregard bonding, I don't see any reason to use different definitions for 3/ (PHY negotiation result). This makes it one unified API for all three purposes.
> 
> Agree.

I don't agree with this one, some PMDs don't use the advertise of
autoneg result to get the speed or the duplex.  You make a
generality from your case above all PMDs.

Mellanox get the speed, duplex and status information from IOCTLs
which are not related to your bitmap.  So at least for this PMD, there
is already a conversion from 3 fields to a bitmap, knowing that it will
use the speed as an integer after.  What is the benefit of your solution?

> > Nelio suggested adding a support function to convert the bitmap field to a speed value as an integer. I strongly support this, because you cannot expect the bitmap to be ordered by speed. 
> 
> Agree with Nelio&you. This is useful.

It was exactly the extreme opposite, a function which takes a
rte_eth_link to a bitmap i.e. speed_to_bm (rte_eth_link link) because,
the speed is mostly used as an integer and not some kind of bitmap.

> > This support function will be able to determine which speed is higher when exotic speeds are added to the bitmap. Please extend this conversion function to give three output parameters: speed, full/half duplex, auto negotiation/non-auto negotiation, or add two separate functions to get the duplex and auto-negotiation.
> 
> Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my doubts on using a bit for all speeds. I would suggest to define (unroll) 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was suggesting some mails ago.
> 
> This was done in v4 (implicitely 100M == 100M_FD). See below.
>  
> MB> I didn't intend two bits to be allocated in the bitmap for all speeds to support full/half duplex, only for the relevant speeds. Since full duplex is dominant, I agree with the previous decision (originally suggested by Thomas, I think) to make full duplex implicit unless half duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD), 100M_HD, 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.
> 
> 
> > I haven't read the suggested code, but there should be some means in 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the bitmap to indicate if the speed/duplex-indicating bits in the bitmap means forced speed/duplex (in which case only a single speed/duplex-bit should be set) or auto negotiation advertised speed/duplex (in which case multiple speed/duplex-bits can be set). 
> 
> Agree.
> 
> v3/4 of this patch adds the bitmap in the advertised, as per discussed, to select a group of speeds This is not implemented by drivers yet (!).
> 
> So, as of v4 of this patch, there could be: a) autoneg any supported speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than one bit set in the bitmap) c) forced speed (one and only one set in the bitmap).
> 
> I think this is precisely what you meant + b) as a bonus
> 
> MB> This was not what I meant, but it wasn't very clearly written, so I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever you want to name it) to the 2/ (advertisements) bitmap that explicitly turns off auto negotiation and tries to force the selected speed/duplex (i.e. only one other bit can be set in the bitmap when the NO_AUTONEG bit is set). Your c) makes it impossible to use auto negotiation to advertise a specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can also be used in 3/ (result) to indicate that the speed was a result of Parallel Detection, i.e. that auto negotiation failed or was disabled in either end of the link.
> 
> MB> However, I like your suggestion a).
> 
>  
> > And some means in 3/ (result) and maybe 2/ (advertisements) to select and/or indicate physical interface in dual-personality ports (e.g. ports where the PHY has both an SFP and a RJ45 connector, but only one of the two can be used at any time).
> 
> For rte_eth_link_get() I don't have such a strong opinion. You either
> 
> * encode the link speed and duplex as of now, separating duplex and numeric speed. I would suggest to add the encoded speed+duplex bitmap flag for consistency (although redundant).
> * or you return a single value, the bitmap with a single flag set of the unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int val_bm) and bool rte_eth_duplex_from_bm(int val_bm).
> 
> MB> I prefer the latter of the two, only because it makes 3/ (result) consistent with 1/ (capabilities) and 2/ (advertisements).

So I agree for 1/ capabilities and 2/ advertisements.

But, I don't agree to modify rte_eth_link_get API
(and rte_eth_link structure) thus 3/ result.
We don't need a "consistent" result, we need something usable.  This is
not the case of the bitmap and using some conversion functions.
Remember that the speed and duplex will not change until the next link
down and there is a lot of code using speeds as integers.
Your solution will just increase the number of instruction to get the
same result, is that a benefit?

In addition, some PMDs need the speed to make some stuff with it,
so this structure will be replicated all over DPDK.

-- 
Nélio Laranjeiro
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15  8:25                         ` Nélio Laranjeiro
@ 2015-09-15  8:48                           ` Marc Sune
  2015-09-15  9:39                             ` Morten Brørup
  2015-09-15 10:04                             ` Adrien Mazarguil
  0 siblings, 2 replies; 64+ messages in thread
From: Marc Sune @ 2015-09-15  8:48 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: dev, Morten Brørup

I will answer Morten in another mail, because I got his point on the
AUTONEG as a separate bit, and it _makes_ sense to me.

But Neilo,

2015-09-15 10:25 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:

> On Tue, Sep 15, 2015 at 12:50:11AM +0200, Morten Brørup wrote:
> > Comments inline, marked MB>.
> >
> > Med venlig hilsen / kind regards
> > - Morten Brørup
> >
> > Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:
> >
> > 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > > It is important to consider that a multipath link (bonding etc.) is
> not a physical link, but a logical link (built on top of multiple physical
> links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad,
> Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3
> multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it
> doesn't make sense trying to impose physical link properties on a purely
> logical link. Likewise, it doesn't make sense to impose logical link
> properties on physical links. In other words: Don't consider bonding or any
> other logical link types when designing the PHY API.
> >
> > +1
>
> +1.
>
> >
> >
> > > I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY
> advertisements) should use the same definitions, specifically a bitmap
> field. And when you disregard bonding, I don't see any reason to use
> different definitions for 3/ (PHY negotiation result). This makes it one
> unified API for all three purposes.
> >
> > Agree.
>
> I don't agree with this one, some PMDs don't use the advertise of
> autoneg result to get the speed or the duplex.  You make a
> generality from your case above all PMDs.
>

can you please explain how a particular PMD is recovering the actual link
speed and the duplex has to do with the design of the (general) API?


>
> Mellanox get the speed, duplex and status information from IOCTLs
> which are not related to your bitmap.  So at least for this PMD, there
> is already a conversion from 3 fields to a bitmap, knowing that it will
> use the speed as an integer after.  What is the benefit of your solution?
>

I said already I don't have a strong preference for 3/. But steering the
design of an API through a "minimum common denominator" principle is not a
good idea, specially since we are talking about a super simple mapping
issue for this specific PMD.


>
> > > Nelio suggested adding a support function to convert the bitmap field
> to a speed value as an integer. I strongly support this, because you cannot
> expect the bitmap to be ordered by speed.
> >
> > Agree with Nelio&you. This is useful.
>
> It was exactly the extreme opposite, a function which takes a
> rte_eth_link to a bitmap i.e. speed_to_bm (rte_eth_link link) because,
> the speed is mostly used as an integer and not some kind of bitmap.
>
> > > This support function will be able to determine which speed is higher
> when exotic speeds are added to the bitmap. Please extend this conversion
> function to give three output parameters: speed, full/half duplex, auto
> negotiation/non-auto negotiation, or add two separate functions to get the
> duplex and auto-negotiation.
> >
> > Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my
> doubts on using a bit for all speeds. I would suggest to define (unroll)
> 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was
> suggesting some mails ago.
> >
> > This was done in v4 (implicitely 100M == 100M_FD). See below.
> >
> > MB> I didn't intend two bits to be allocated in the bitmap for all
> speeds to support full/half duplex, only for the relevant speeds. Since
> full duplex is dominant, I agree with the previous decision (originally
> suggested by Thomas, I think) to make full duplex implicit unless half
> duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD), 100M_HD,
> 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.
> >
> >
> > > I haven't read the suggested code, but there should be some means in
> 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the
> bitmap to indicate if the speed/duplex-indicating bits in the bitmap means
> forced speed/duplex (in which case only a single speed/duplex-bit should be
> set) or auto negotiation advertised speed/duplex (in which case multiple
> speed/duplex-bits can be set).
> >
> > Agree.
> >
> > v3/4 of this patch adds the bitmap in the advertised, as per discussed,
> to select a group of speeds This is not implemented by drivers yet (!).
> >
> > So, as of v4 of this patch, there could be: a) autoneg any supported
> speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than one
> bit set in the bitmap) c) forced speed (one and only one set in the bitmap).
> >
> > I think this is precisely what you meant + b) as a bonus
> >
> > MB> This was not what I meant, but it wasn't very clearly written, so
> I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever you
> want to name it) to the 2/ (advertisements) bitmap that explicitly turns
> off auto negotiation and tries to force the selected speed/duplex (i.e.
> only one other bit can be set in the bitmap when the NO_AUTONEG bit is
> set). Your c) makes it impossible to use auto negotiation to advertise a
> specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can also
> be used in 3/ (result) to indicate that the speed was a result of Parallel
> Detection, i.e. that auto negotiation failed or was disabled in either end
> of the link.
> >
> > MB> However, I like your suggestion a).
> >
> >
> > > And some means in 3/ (result) and maybe 2/ (advertisements) to select
> and/or indicate physical interface in dual-personality ports (e.g. ports
> where the PHY has both an SFP and a RJ45 connector, but only one of the two
> can be used at any time).
> >
> > For rte_eth_link_get() I don't have such a strong opinion. You either
> >
> > * encode the link speed and duplex as of now, separating duplex and
> numeric speed. I would suggest to add the encoded speed+duplex bitmap flag
> for consistency (although redundant).
> > * or you return a single value, the bitmap with a single flag set of the
> unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int
> val_bm) and bool rte_eth_duplex_from_bm(int val_bm).
> >
> > MB> I prefer the latter of the two, only because it makes 3/ (result)
> consistent with 1/ (capabilities) and 2/ (advertisements).
>
> So I agree for 1/ capabilities and 2/ advertisements.
>
> But, I don't agree to modify rte_eth_link_get API
> (and rte_eth_link structure) thus 3/ result.
> We don't need a "consistent" result, we need something usable.  This is
> not the case of the bitmap and using some conversion functions.
> Remember that the speed and duplex will not change until the next link
> down and there is a lot of code using speeds as integers.
> Your solution will just increase the number of instruction to get the
> same result, is that a benefit?
>

So do you think we should care about roughly 10cycles (at very most) which
is what a unique switch case mapping will take? We are not talking about
the dataplane here, Neilo.

The benefit that Morten is arguing here is to have a unified API,
consistent for the user. Once more, I don't have a preference, though I see
what he means. I am not sure if the bitmap for retrieving the link is
really more usable than the current API, which is IMHO what should steer
the discussion, not performance.

marc


>
> In addition, some PMDs need the speed to make some stuff with it,
> so this structure will be replicated all over DPDK.
>
> --
> Nélio Laranjeiro
> 6WIND
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-14 21:33                     ` Marc Sune
  2015-09-14 22:50                       ` Morten Brørup
  2015-09-15  7:05                       ` Thomas Monjalon
@ 2015-09-15  9:06                       ` Morten Brørup
  2 siblings, 0 replies; 64+ messages in thread
From: Morten Brørup @ 2015-09-15  9:06 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

Marc, here's a couple of details that I missed in my email below:

Correction: 1000BASE-T and 1000BASE-X also have half duplex, so full/half duplex is relevant for 10, 100 and 1000 Mbit/s speeds.

The bitmap in 3/ (result) probably also needs a bit ("NO_MEDIA" or whatever) to indicate if a media module (e.g. an SFP+ module) is present or missing (i.e. the SFP+ cage is empty); e.g. refer to the "Media Available" row in table 3-55 in Intel's XL710 Ethernet Controller datasheet (xl710-10-40-controller-datasheet.pdf). Alternatively, this can be indicated by having 1/ (capabilities) returning an empty set of capabilities when no media module has been installed.

Furthermore, the 1/ (capabilities) or 3/ (result) also needs a means to indicate which physical port of a dual-personality port is being used. And by dual-personality ports, I mean a PHY with both an RJ45 copper port and an SFP cage, where only one of them can be active at any time.


Med venlig hilsen / kind regards
- Morten Brørup


-----Original Message-----
From: Morten Brørup 
Sent: 15. september 2015 00:50
To: 'Marc Sune'
Cc: Thomas Monjalon; Nélio Laranjeiro; dev@dpdk.org; Olga Shern; Adrien Mazarguil
Subject: RE: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap

Comments inline, marked MB>.

Med venlig hilsen / kind regards
- Morten Brørup

Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:

2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> It is important to consider that a multipath link (bonding etc.) is not a physical link, but a logical link (built on top of multiple physical links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad, Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3 multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it doesn't make sense trying to impose physical link properties on a purely logical link. Likewise, it doesn't make sense to impose logical link properties on physical links. In other words: Don't consider bonding or any other logical link types when designing the PHY API.

+1
 

> I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY advertisements) should use the same definitions, specifically a bitmap field. And when you disregard bonding, I don't see any reason to use different definitions for 3/ (PHY negotiation result). This makes it one unified API for all three purposes.

Agree.
 

> Nelio suggested adding a support function to convert the bitmap field to a speed value as an integer. I strongly support this, because you cannot expect the bitmap to be ordered by speed. 

Agree with Nelio&you. This is useful.
 
> This support function will be able to determine which speed is higher when exotic speeds are added to the bitmap. Please extend this conversion function to give three output parameters: speed, full/half duplex, auto negotiation/non-auto negotiation, or add two separate functions to get the duplex and auto-negotiation.

Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my doubts on using a bit for all speeds. I would suggest to define (unroll) 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was suggesting some mails ago.

This was done in v4 (implicitely 100M == 100M_FD). See below.
 
MB> I didn't intend two bits to be allocated in the bitmap for all speeds to support full/half duplex, only for the relevant speeds. Since full duplex is dominant, I agree with the previous decision (originally suggested by Thomas, I think) to make full duplex implicit unless half duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD), 100M_HD, 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.


> I haven't read the suggested code, but there should be some means in 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the bitmap to indicate if the speed/duplex-indicating bits in the bitmap means forced speed/duplex (in which case only a single speed/duplex-bit should be set) or auto negotiation advertised speed/duplex (in which case multiple speed/duplex-bits can be set). 

Agree.

v3/4 of this patch adds the bitmap in the advertised, as per discussed, to select a group of speeds This is not implemented by drivers yet (!).

So, as of v4 of this patch, there could be: a) autoneg any supported speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than one bit set in the bitmap) c) forced speed (one and only one set in the bitmap).

I think this is precisely what you meant + b) as a bonus

MB> This was not what I meant, but it wasn't very clearly written, so I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever you want to name it) to the 2/ (advertisements) bitmap that explicitly turns off auto negotiation and tries to force the selected speed/duplex (i.e. only one other bit can be set in the bitmap when the NO_AUTONEG bit is set). Your c) makes it impossible to use auto negotiation to advertise a specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can also be used in 3/ (result) to indicate that the speed was a result of Parallel Detection, i.e. that auto negotiation failed or was disabled in either end of the link.

MB> However, I like your suggestion a).

 
> And some means in 3/ (result) and maybe 2/ (advertisements) to select and/or indicate physical interface in dual-personality ports (e.g. ports where the PHY has both an SFP and a RJ45 connector, but only one of the two can be used at any time).

For rte_eth_link_get() I don't have such a strong opinion. You either

* encode the link speed and duplex as of now, separating duplex and numeric speed. I would suggest to add the encoded speed+duplex bitmap flag for consistency (although redundant).
* or you return a single value, the bitmap with a single flag set of the unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int val_bm) and bool rte_eth_duplex_from_bm(int val_bm).

MB> I prefer the latter of the two, only because it makes 3/ (result) consistent with 1/ (capabilities) and 2/ (advertisements).


Marc


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15  8:48                           ` Marc Sune
@ 2015-09-15  9:39                             ` Morten Brørup
  2015-09-15 10:04                             ` Adrien Mazarguil
  1 sibling, 0 replies; 64+ messages in thread
From: Morten Brørup @ 2015-09-15  9:39 UTC (permalink / raw)
  To: Marc Sune, Nélio Laranjeiro; +Cc: dev

Nelio, Marc,

 

I think Marc is on the right track here: You should design the API based on requirements and usefulness, not based on what is already implemented in some drivers. And as Marc pointed out, this is control plane stuff, so performance should not be an issue.

 

Let me throw in another detail. Read clause 22.2.4.2.13 in the IEEE 802.3 standard very carefully. It says that the Link Status register in the PHY latches a link failure until the Link Status bit has been read. The purpose of this is to make it possible for slowly polling software to detect that the link has been temporarily down, even though it has come up again. Why would the application need to know that the link has been temporarily down, when it is already up again? Because the link might have come up in another speed/duplex, auto negotiation or flow control mode than it was before.

 

And while I’m at it: Remember the flow control (PAUSE) operations. It is important to be able to enable/disable flow control – even cheap “web managed” switches have the ability to disable flow control.

 

 

Med venlig hilsen / kind regards

- Morten Brørup

 

From: Marc Sune [mailto:marcdevel@gmail.com] 
Sent: 15. september 2015 10:48
To: Nélio Laranjeiro
Cc: Morten Brørup; Thomas Monjalon; dev@dpdk.org; Olga Shern; Adrien Mazarguil
Subject: Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap

 

I will answer Morten in another mail, because I got his point on the AUTONEG as a separate bit, and it _makes_ sense to me.

 

But Neilo,

 

2015-09-15 10:25 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:

On Tue, Sep 15, 2015 at 12:50:11AM +0200, Morten Brørup wrote:
> Comments inline, marked MB>.
>
> Med venlig hilsen / kind regards
> - Morten Brørup
>
> Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:
>
> 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > It is important to consider that a multipath link (bonding etc.) is not a physical link, but a logical link (built on top of multiple physical links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad, Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3 multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it doesn't make sense trying to impose physical link properties on a purely logical link. Likewise, it doesn't make sense to impose logical link properties on physical links. In other words: Don't consider bonding or any other logical link types when designing the PHY API.
>
> +1

+1.

>  
>
> > I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY advertisements) should use the same definitions, specifically a bitmap field. And when you disregard bonding, I don't see any reason to use different definitions for 3/ (PHY negotiation result). This makes it one unified API for all three purposes.
>
> Agree.

I don't agree with this one, some PMDs don't use the advertise of
autoneg result to get the speed or the duplex.  You make a
generality from your case above all PMDs.

 

can you please explain how a particular PMD is recovering the actual link speed and the duplex has to do with the design of the (general) API?

 

	
	Mellanox get the speed, duplex and status information from IOCTLs
	which are not related to your bitmap.  So at least for this PMD, there
	is already a conversion from 3 fields to a bitmap, knowing that it will
	use the speed as an integer after.  What is the benefit of your solution?

 

I said already I don't have a strong preference for 3/. But steering the design of an API through a "minimum common denominator" principle is not a good idea, specially since we are talking about a super simple mapping issue for this specific PMD.

 

	
	> > Nelio suggested adding a support function to convert the bitmap field to a speed value as an integer. I strongly support this, because you cannot expect the bitmap to be ordered by speed.
	>
	> Agree with Nelio&you. This is useful.
	
	It was exactly the extreme opposite, a function which takes a
	rte_eth_link to a bitmap i.e. speed_to_bm (rte_eth_link link) because,
	the speed is mostly used as an integer and not some kind of bitmap.
	
	> > This support function will be able to determine which speed is higher when exotic speeds are added to the bitmap. Please extend this conversion function to give three output parameters: speed, full/half duplex, auto negotiation/non-auto negotiation, or add two separate functions to get the duplex and auto-negotiation.
	>
	> Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my doubts on using a bit for all speeds. I would suggest to define (unroll) 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was suggesting some mails ago.
	>
	> This was done in v4 (implicitely 100M == 100M_FD). See below.
	>  
	> MB> I didn't intend two bits to be allocated in the bitmap for all speeds to support full/half duplex, only for the relevant speeds. Since full duplex is dominant, I agree with the previous decision (originally suggested by Thomas, I think) to make full duplex implicit unless half duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD), 100M_HD, 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.
	>
	>
	> > I haven't read the suggested code, but there should be some means in 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the bitmap to indicate if the speed/duplex-indicating bits in the bitmap means forced speed/duplex (in which case only a single speed/duplex-bit should be set) or auto negotiation advertised speed/duplex (in which case multiple speed/duplex-bits can be set).
	>
	> Agree.
	>
	> v3/4 of this patch adds the bitmap in the advertised, as per discussed, to select a group of speeds This is not implemented by drivers yet (!).
	>
	> So, as of v4 of this patch, there could be: a) autoneg any supported speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than one bit set in the bitmap) c) forced speed (one and only one set in the bitmap).
	>
	> I think this is precisely what you meant + b) as a bonus
	>
	> MB> This was not what I meant, but it wasn't very clearly written, so I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever you want to name it) to the 2/ (advertisements) bitmap that explicitly turns off auto negotiation and tries to force the selected speed/duplex (i.e. only one other bit can be set in the bitmap when the NO_AUTONEG bit is set). Your c) makes it impossible to use auto negotiation to advertise a specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can also be used in 3/ (result) to indicate that the speed was a result of Parallel Detection, i.e. that auto negotiation failed or was disabled in either end of the link.
	>
	> MB> However, I like your suggestion a).
	>
	>  
	> > And some means in 3/ (result) and maybe 2/ (advertisements) to select and/or indicate physical interface in dual-personality ports (e.g. ports where the PHY has both an SFP and a RJ45 connector, but only one of the two can be used at any time).
	>
	> For rte_eth_link_get() I don't have such a strong opinion. You either
	>
	> * encode the link speed and duplex as of now, separating duplex and numeric speed. I would suggest to add the encoded speed+duplex bitmap flag for consistency (although redundant).
	> * or you return a single value, the bitmap with a single flag set of the unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int val_bm) and bool rte_eth_duplex_from_bm(int val_bm).
	>
	> MB> I prefer the latter of the two, only because it makes 3/ (result) consistent with 1/ (capabilities) and 2/ (advertisements).
	
	So I agree for 1/ capabilities and 2/ advertisements.
	
	But, I don't agree to modify rte_eth_link_get API
	(and rte_eth_link structure) thus 3/ result.
	We don't need a "consistent" result, we need something usable.  This is
	not the case of the bitmap and using some conversion functions.
	Remember that the speed and duplex will not change until the next link
	down and there is a lot of code using speeds as integers.
	Your solution will just increase the number of instruction to get the
	same result, is that a benefit?

 

So do you think we should care about roughly 10cycles (at very most) which is what a unique switch case mapping will take? We are not talking about the dataplane here, Neilo.

 

The benefit that Morten is arguing here is to have a unified API, consistent for the user. Once more, I don't have a preference, though I see what he means. I am not sure if the bitmap for retrieving the link is really more usable than the current API, which is IMHO what should steer the discussion, not performance.

 

marc

 

	
	In addition, some PMDs need the speed to make some stuff with it,
	so this structure will be replicated all over DPDK.
	
	--
	Nélio Laranjeiro
	6WIND

 


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15  8:48                           ` Marc Sune
  2015-09-15  9:39                             ` Morten Brørup
@ 2015-09-15 10:04                             ` Adrien Mazarguil
  2015-09-15 10:24                               ` Morten Brørup
  2015-09-15 21:20                               ` Marc Sune
  1 sibling, 2 replies; 64+ messages in thread
From: Adrien Mazarguil @ 2015-09-15 10:04 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev, Morten Brørup

Hi Marc,

Adding my thoughts to the discussion, see below.

On Tue, Sep 15, 2015 at 10:48:03AM +0200, Marc Sune wrote:
> I will answer Morten in another mail, because I got his point on the
> AUTONEG as a separate bit, and it _makes_ sense to me.
> 
> But Neilo,
> 
> 2015-09-15 10:25 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:
> 
> > On Tue, Sep 15, 2015 at 12:50:11AM +0200, Morten Brørup wrote:
> > > Comments inline, marked MB>.
> > >
> > > Med venlig hilsen / kind regards
> > > - Morten Brørup
> > >
> > > Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:
> > >
> > > 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > > > It is important to consider that a multipath link (bonding etc.) is
> > not a physical link, but a logical link (built on top of multiple physical
> > links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad,
> > Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3
> > multipath link (e.g. simultaneously using Wi-Fi and mobile networks). So it
> > doesn't make sense trying to impose physical link properties on a purely
> > logical link. Likewise, it doesn't make sense to impose logical link
> > properties on physical links. In other words: Don't consider bonding or any
> > other logical link types when designing the PHY API.
> > >
> > > +1
> >
> > +1.

I agree with the fact that physical link properties do not make sense for
logical links, however in the case of the bonding PMD, the aggregated link
speed can be actually useful for applications (assuming it is kept up to
date, I think it's the case). The current API certainly allows this.

> > > > I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY
> > advertisements) should use the same definitions, specifically a bitmap
> > field. And when you disregard bonding, I don't see any reason to use
> > different definitions for 3/ (PHY negotiation result). This makes it one
> > unified API for all three purposes.
> > >
> > > Agree.
> >
> > I don't agree with this one, some PMDs don't use the advertise of
> > autoneg result to get the speed or the duplex.  You make a
> > generality from your case above all PMDs.
> >
> 
> can you please explain how a particular PMD is recovering the actual link
> speed and the duplex has to do with the design of the (general) API?

It's not so much about the way PMDs recover link information, rather about
the amount of changes required to switch to a bit-field API for the current
link speed with no clear advantage. All PMDs must be modified, the initial
set of patches isn't complete in this regard.

> > Mellanox get the speed, duplex and status information from IOCTLs
> > which are not related to your bitmap.  So at least for this PMD, there
> > is already a conversion from 3 fields to a bitmap, knowing that it will
> > use the speed as an integer after.  What is the benefit of your solution?
> >
> 
> I said already I don't have a strong preference for 3/. But steering the
> design of an API through a "minimum common denominator" principle is not a
> good idea, specially since we are talking about a super simple mapping
> issue for this specific PMD.

I think Nelio was using mlx4 as an example, all PMDs have their own
particular method to recover it and several must perform calculations to get
the final value. Using integers for this task is certainly easier than going
through bit-field conversions.

> > > > Nelio suggested adding a support function to convert the bitmap field
> > to a speed value as an integer. I strongly support this, because you cannot
> > expect the bitmap to be ordered by speed.
> > >
> > > Agree with Nelio&you. This is useful.
> >
> > It was exactly the extreme opposite, a function which takes a
> > rte_eth_link to a bitmap i.e. speed_to_bm (rte_eth_link link) because,
> > the speed is mostly used as an integer and not some kind of bitmap.
> >
> > > > This support function will be able to determine which speed is higher
> > when exotic speeds are added to the bitmap. Please extend this conversion
> > function to give three output parameters: speed, full/half duplex, auto
> > negotiation/non-auto negotiation, or add two separate functions to get the
> > duplex and auto-negotiation.
> > >
> > > Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I have my
> > doubts on using a bit for all speeds. I would suggest to define (unroll)
> > 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was
> > suggesting some mails ago.
> > >
> > > This was done in v4 (implicitely 100M == 100M_FD). See below.
> > >
> > > MB> I didn't intend two bits to be allocated in the bitmap for all
> > speeds to support full/half duplex, only for the relevant speeds. Since
> > full duplex is dominant, I agree with the previous decision (originally
> > suggested by Thomas, I think) to make full duplex implicit unless half
> > duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD), 100M_HD,
> > 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.
> > >
> > >
> > > > I haven't read the suggested code, but there should be some means in
> > 2/ (advertisements) to disable auto negotiation, e.g. a single bit in the
> > bitmap to indicate if the speed/duplex-indicating bits in the bitmap means
> > forced speed/duplex (in which case only a single speed/duplex-bit should be
> > set) or auto negotiation advertised speed/duplex (in which case multiple
> > speed/duplex-bits can be set).
> > >
> > > Agree.
> > >
> > > v3/4 of this patch adds the bitmap in the advertised, as per discussed,
> > to select a group of speeds This is not implemented by drivers yet (!).
> > >
> > > So, as of v4 of this patch, there could be: a) autoneg any supported
> > speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than one
> > bit set in the bitmap) c) forced speed (one and only one set in the bitmap).
> > >
> > > I think this is precisely what you meant + b) as a bonus
> > >
> > > MB> This was not what I meant, but it wasn't very clearly written, so
> > I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever you
> > want to name it) to the 2/ (advertisements) bitmap that explicitly turns
> > off auto negotiation and tries to force the selected speed/duplex (i.e.
> > only one other bit can be set in the bitmap when the NO_AUTONEG bit is
> > set). Your c) makes it impossible to use auto negotiation to advertise a
> > specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can also
> > be used in 3/ (result) to indicate that the speed was a result of Parallel
> > Detection, i.e. that auto negotiation failed or was disabled in either end
> > of the link.
> > >
> > > MB> However, I like your suggestion a).
> > >
> > >
> > > > And some means in 3/ (result) and maybe 2/ (advertisements) to select
> > and/or indicate physical interface in dual-personality ports (e.g. ports
> > where the PHY has both an SFP and a RJ45 connector, but only one of the two
> > can be used at any time).
> > >
> > > For rte_eth_link_get() I don't have such a strong opinion. You either
> > >
> > > * encode the link speed and duplex as of now, separating duplex and
> > numeric speed. I would suggest to add the encoded speed+duplex bitmap flag
> > for consistency (although redundant).
> > > * or you return a single value, the bitmap with a single flag set of the
> > unrolled speeds, and then have the helpers int rte_eth_speed_from_bm(int
> > val_bm) and bool rte_eth_duplex_from_bm(int val_bm).
> > >
> > > MB> I prefer the latter of the two, only because it makes 3/ (result)
> > consistent with 1/ (capabilities) and 2/ (advertisements).
> >
> > So I agree for 1/ capabilities and 2/ advertisements.
> >
> > But, I don't agree to modify rte_eth_link_get API
> > (and rte_eth_link structure) thus 3/ result.
> > We don't need a "consistent" result, we need something usable.  This is
> > not the case of the bitmap and using some conversion functions.
> > Remember that the speed and duplex will not change until the next link
> > down and there is a lot of code using speeds as integers.
> > Your solution will just increase the number of instruction to get the
> > same result, is that a benefit?
> >
> 
> So do you think we should care about roughly 10cycles (at very most) which
> is what a unique switch case mapping will take? We are not talking about
> the dataplane here, Neilo.

He wasn't arguing about the number of CPU cycles but the amount of code
required to go back and forth between actual link status speed and its
bit-field counterpart for no apparent benefit.

> The benefit that Morten is arguing here is to have a unified API,
> consistent for the user. Once more, I don't have a preference, though I see
> what he means. I am not sure if the bitmap for retrieving the link is
> really more usable than the current API, which is IMHO what should steer
> the discussion, not performance.

Everyone agrees that a link speed bit-field is useful as an input value to
advertise, request and allow a set of speeds. We do not agree with its usage
as the current link speed which is often the result of a computation. We
aren't talking about performance.

A given link cannot be simultaneously at 10 Gbps and 1 Gbps right? Using a
bit-field for the current link speed is confusing at best. Output values do
not need to be included in the unified API, they are never converted back
into enum values.

I'm stressing again the fact that doing so would require a changes in all
applications that use the current speed and in PMDs for no good reason.

Regards,

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15 10:04                             ` Adrien Mazarguil
@ 2015-09-15 10:24                               ` Morten Brørup
  2015-09-15 21:20                               ` Marc Sune
  1 sibling, 0 replies; 64+ messages in thread
From: Morten Brørup @ 2015-09-15 10:24 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: dev

Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com] on 15. september 2015 12:05:

> A given link cannot be simultaneously at 10 Gbps and 1 Gbps right? Using a bit-field for the current link speed is confusing at best. Output values do not need to be included in the unified API, they are never converted back into enum values.

A given link can only use one speed at any given time, correct. However, other link properties must be output too, such as link status, duplex status, auto negotiation status, flow control status, media status, etc..  Using a bitfield provides all this information in an atomic operation.

> I'm stressing again the fact that doing so would require a changes in all applications that use the current speed and in PMDs for no good reason.

Correct, it requires a lot of changes in all the PMDs. I think a good PHY API with the appropriate features is a good reason. If there is no consensus to put in the work to update the PHY API and PMDs accordingly, just leave it at its former state.


I recently saw an interesting presentation about TCP optimization, and the last slide has a very good point. It says (slightly paraphrased): "You can't sell just the traffic handling, you need the support infrastructure for O&M, such as CLI, Web UI, Historical counter database, SNMP, RADIUS, Analytics and so on." So related to our PHY API discussion, I would add that proper handling of the physical interfaces is one of those things that just need to be in order when you sell network appliances.


Med venlig hilsen / kind regards
- Morten Brørup

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15 10:04                             ` Adrien Mazarguil
  2015-09-15 10:24                               ` Morten Brørup
@ 2015-09-15 21:20                               ` Marc Sune
  2015-09-16 14:41                                 ` Adrien Mazarguil
  1 sibling, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-09-15 21:20 UTC (permalink / raw)
  To: Marc Sune, Nélio Laranjeiro, Morten Brørup,
	Thomas Monjalon, dev, Olga Shern

Adrien,

2015-09-15 12:04 GMT+02:00 Adrien Mazarguil <adrien.mazarguil@6wind.com>:

> Hi Marc,
>
> Adding my thoughts to the discussion, see below.
>
> On Tue, Sep 15, 2015 at 10:48:03AM +0200, Marc Sune wrote:
> > I will answer Morten in another mail, because I got his point on the
> > AUTONEG as a separate bit, and it _makes_ sense to me.
> >
> > But Neilo,
> >
> > 2015-09-15 10:25 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com
> >:
> >
> > > On Tue, Sep 15, 2015 at 12:50:11AM +0200, Morten Brørup wrote:
> > > > Comments inline, marked MB>.
> > > >
> > > > Med venlig hilsen / kind regards
> > > > - Morten Brørup
> > > >
> > > > Marc Sune <marcdevel@gmail.com> on 14. september 2015 23:34 wrote:
> > > >
> > > > 2015-09-14 12:52 GMT+02:00 Morten Brørup <mb@smartsharesystems.com>:
> > > > > It is important to consider that a multipath link (bonding etc.) is
> > > not a physical link, but a logical link (built on top of multiple
> physical
> > > links). Regardless whether it is a Layer2 link aggregate (IEEE 802.1ad,
> > > Ethernet bonding, EtherChannel, DSL pair bonding, etc.) or a Layer3
> > > multipath link (e.g. simultaneously using Wi-Fi and mobile networks).
> So it
> > > doesn't make sense trying to impose physical link properties on a
> purely
> > > logical link. Likewise, it doesn't make sense to impose logical link
> > > properties on physical links. In other words: Don't consider bonding
> or any
> > > other logical link types when designing the PHY API.
> > > >
> > > > +1
> > >
> > > +1.
>
> I agree with the fact that physical link properties do not make sense for
> logical links, however in the case of the bonding PMD, the aggregated link
> speed can be actually useful for applications (assuming it is kept up to
> date, I think it's the case). The current API certainly allows this.
>
> > > > > I think there is consensus that 1/ (PHY capabilities) and 2/ (PHY
> > > advertisements) should use the same definitions, specifically a bitmap
> > > field. And when you disregard bonding, I don't see any reason to use
> > > different definitions for 3/ (PHY negotiation result). This makes it
> one
> > > unified API for all three purposes.
> > > >
> > > > Agree.
> > >
> > > I don't agree with this one, some PMDs don't use the advertise of
> > > autoneg result to get the speed or the duplex.  You make a
> > > generality from your case above all PMDs.
> > >
> >
> > can you please explain how a particular PMD is recovering the actual link
> > speed and the duplex has to do with the design of the (general) API?
>
> It's not so much about the way PMDs recover link information, rather about
> the amount of changes required to switch to a bit-field API for the current
> link speed with no clear advantage.


See below; these are trivial changes.


> All PMDs must be modified, the initial
> set of patches isn't complete in this regard.
>

Thanks for pointing out this. There are a couple missing.


>
> > > Mellanox get the speed, duplex and status information from IOCTLs
> > > which are not related to your bitmap.  So at least for this PMD, there
> > > is already a conversion from 3 fields to a bitmap, knowing that it will
> > > use the speed as an integer after.  What is the benefit of your
> solution?
> > >
> >
> > I said already I don't have a strong preference for 3/. But steering the
> > design of an API through a "minimum common denominator" principle is not
> a
> > good idea, specially since we are talking about a super simple mapping
> > issue for this specific PMD.
>
> I think Nelio was using mlx4 as an example, all PMDs have their own
> particular method to recover it and several must perform calculations to
> get
> the final value. Using integers for this task is certainly easier than
> going
> through bit-field conversions.
>

Drivers have their *own* way to extract the link speed from the HW, because
the way is stored is anyway HW specific. That a driver encodes their link
speed as a numeric value is just a coincidence, and the exception.

Specifically, and putting an example of e1000 (which you are right it is
buggy in v4, see below):

dpdk/drivers/net/e1000/base/e1000_mac.c

1651 s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16
*speed,
1652                                               u16 *duplex)

1653 {

1654         u32 status;

1655

1656         DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic");

1657

1658         status = E1000_READ_REG(hw, E1000_STATUS);

1659         if (status & E1000_STATUS_SPEED_1000) {

1660                 *speed = SPEED_1000;

1661                 DEBUGOUT("1000 Mbs, ");

1662         } else if (status & E1000_STATUS_SPEED_100) {

1663                 *speed = SPEED_100;

1664                 DEBUGOUT("100 Mbs, ");

1665         } else {

1666                 *speed = SPEED_10;

1667                 DEBUGOUT("10 Mbs, ");

1668         }

1669

1670         if (status & E1000_STATUS_FD) {

1671                 *duplex = FULL_DUPLEX;

1672                 DEBUGOUT("Full Duplex\n");

1673         } else {

1674                 *duplex = HALF_DUPLEX;

1675                 DEBUGOUT("Half Duplex\n");

1676         }

1677

1678         return E1000_SUCCESS;

1679 }

Can you please tell me which exact extra conversions are needed on the PMD
side? It only needs to be fixed:

1662         } else if (status & E1000_STATUS_SPEED_100) {

1663                 *speed = ETH_LINK_SPEED_100;

1664                 DEBUGOUT("100 Mbs, ");

Other drivers, like i40 are already ooing it correctly:

1191 int

1192 i40e_dev_link_update(struct rte_eth_dev *dev,

1193                      int wait_to_complete)

1194 {
/* ... */
1231         /* Parse the link status */

1232         switch (link_status.link_speed) {

1233         case I40E_LINK_SPEED_100MB:

1234                 link.link_speed = ETH_LINK_SPEED_100;

1235                 break;

1236         case I40E_LINK_SPEED_1GB:

1237                 link.link_speed = ETH_LINK_SPEED_1000;

1238                 break;

1239         case I40E_LINK_SPEED_10GB:

1240                 link.link_speed = ETH_LINK_SPEED_10G;

1241                 break;

1242         case I40E_LINK_SPEED_20GB:

1243                 link.link_speed = ETH_LINK_SPEED_20G;

1244                 break;

1245         case I40E_LINK_SPEED_40GB:

1246                 link.link_speed = ETH_LINK_SPEED_40G;

1247                 break;

1248         default:

1249                 link.link_speed = ETH_LINK_SPEED_100;

1250                 break;

1251         }


> > > > > Nelio suggested adding a support function to convert the bitmap
> field
> > > to a speed value as an integer. I strongly support this, because you
> cannot
> > > expect the bitmap to be ordered by speed.
> > > >
> > > > Agree with Nelio&you. This is useful.
> > >
> > > It was exactly the extreme opposite, a function which takes a
> > > rte_eth_link to a bitmap i.e. speed_to_bm (rte_eth_link link) because,
> > > the speed is mostly used as an integer and not some kind of bitmap.
> > >
> > > > > This support function will be able to determine which speed is
> higher
> > > when exotic speeds are added to the bitmap. Please extend this
> conversion
> > > function to give three output parameters: speed, full/half duplex, auto
> > > negotiation/non-auto negotiation, or add two separate functions to get
> the
> > > duplex and auto-negotiation.
> > > >
> > > > Since, Full/Half duplex is for legacy 10/100Mbps only (afaik), I
> have my
> > > doubts on using a bit for all speeds. I would suggest to define
> (unroll)
> > > 100M (or 100M_FD) and 100M_HD, and the same 10Mbps/1gbps, as Thomas was
> > > suggesting some mails ago.
> > > >
> > > > This was done in v4 (implicitely 100M == 100M_FD). See below.
> > > >
> > > > MB> I didn't intend two bits to be allocated in the bitmap for all
> > > speeds to support full/half duplex, only for the relevant speeds. Since
> > > full duplex is dominant, I agree with the previous decision (originally
> > > suggested by Thomas, I think) to make full duplex implicit unless half
> > > duplex is explicitly specified. E.g. 10M_HD, 10M (alias 10M_FD),
> 100M_HD,
> > > 100M (alias 100M_FD), 1000M (or 1G), 2500M, 10G, 40G, 100G, etc.
> > > >
> > > >
> > > > > I haven't read the suggested code, but there should be some means
> in
> > > 2/ (advertisements) to disable auto negotiation, e.g. a single bit in
> the
> > > bitmap to indicate if the speed/duplex-indicating bits in the bitmap
> means
> > > forced speed/duplex (in which case only a single speed/duplex-bit
> should be
> > > set) or auto negotiation advertised speed/duplex (in which case
> multiple
> > > speed/duplex-bits can be set).
> > > >
> > > > Agree.
> > > >
> > > > v3/4 of this patch adds the bitmap in the advertised, as per
> discussed,
> > > to select a group of speeds This is not implemented by drivers yet (!).
> > > >
> > > > So, as of v4 of this patch, there could be: a) autoneg any supported
> > > speed (=> bitmap == 0) b) autoneg over group of speeds (=> more than
> one
> > > bit set in the bitmap) c) forced speed (one and only one set in the
> bitmap).
> > > >
> > > > I think this is precisely what you meant + b) as a bonus
> > > >
> > > > MB> This was not what I meant, but it wasn't very clearly written, so
> > > I'll try again: Add an additional single bit "NO_AUTONEG" (or whatever
> you
> > > want to name it) to the 2/ (advertisements) bitmap that explicitly
> turns
> > > off auto negotiation and tries to force the selected speed/duplex (i.e.
> > > only one other bit can be set in the bitmap when the NO_AUTONEG bit is
> > > set). Your c) makes it impossible to use auto negotiation to advertise
> a
> > > specific speed/duplex, e.g. 100M_FD. My suggested NO_AUTONEG bit can
> also
> > > be used in 3/ (result) to indicate that the speed was a result of
> Parallel
> > > Detection, i.e. that auto negotiation failed or was disabled in either
> end
> > > of the link.
> > > >
> > > > MB> However, I like your suggestion a).
> > > >
> > > >
> > > > > And some means in 3/ (result) and maybe 2/ (advertisements) to
> select
> > > and/or indicate physical interface in dual-personality ports (e.g.
> ports
> > > where the PHY has both an SFP and a RJ45 connector, but only one of
> the two
> > > can be used at any time).
> > > >
> > > > For rte_eth_link_get() I don't have such a strong opinion. You either
> > > >
> > > > * encode the link speed and duplex as of now, separating duplex and
> > > numeric speed. I would suggest to add the encoded speed+duplex bitmap
> flag
> > > for consistency (although redundant).
> > > > * or you return a single value, the bitmap with a single flag set of
> the
> > > unrolled speeds, and then have the helpers int
> rte_eth_speed_from_bm(int
> > > val_bm) and bool rte_eth_duplex_from_bm(int val_bm).
> > > >
> > > > MB> I prefer the latter of the two, only because it makes 3/ (result)
> > > consistent with 1/ (capabilities) and 2/ (advertisements).
> > >
> > > So I agree for 1/ capabilities and 2/ advertisements.
> > >
> > > But, I don't agree to modify rte_eth_link_get API
> > > (and rte_eth_link structure) thus 3/ result.
> > > We don't need a "consistent" result, we need something usable.  This is
> > > not the case of the bitmap and using some conversion functions.
> > > Remember that the speed and duplex will not change until the next link
> > > down and there is a lot of code using speeds as integers.
> > > Your solution will just increase the number of instruction to get the
> > > same result, is that a benefit?
> > >
> >
> > So do you think we should care about roughly 10cycles (at very most)
> which
> > is what a unique switch case mapping will take? We are not talking about
> > the dataplane here, Neilo.
>
> He wasn't arguing about the number of CPU cycles but the amount of code
> required to go back and forth between actual link status speed and its
> bit-field counterpart for no apparent benefit.
>

Already covered.


>
> > The benefit that Morten is arguing here is to have a unified API,
> > consistent for the user. Once more, I don't have a preference, though I
> see
> > what he means. I am not sure if the bitmap for retrieving the link is
> > really more usable than the current API, which is IMHO what should steer
> > the discussion, not performance.
>
> Everyone agrees that a link speed bit-field is useful as an input value to
> advertise, request and allow a set of speeds. We do not agree with its
> usage
> as the current link speed which is often the result of a computation. We
> aren't talking about performance.
>
> A given link cannot be simultaneously at 10 Gbps and 1 Gbps right? Using a
> bit-field for the current link speed is confusing at best. Output values do
> not need to be included in the unified API, they are never converted back
> into enum values.
>

Although I agree it is unlikely that this would happen, we shouldn't
anticipate what users will do, so in either approach you would need utility
functions to translate from numerical to bitmap and viceversa.


>
> I'm stressing again the fact that doing so would require a changes in all
> applications that use the current speed and in PMDs for no good reason.


Well any change in the API will. This patch (v1,v2) started as speed caps
only, and now we are refactoring the link API. How much code has to be
changed or how is easier for PMDs is irrelevant IMHO. What matters is if
the API makes sense for the user.

And for that you are probably right; it might be more comprehensible to
have "a" speed value as a result of rte_eth_get_link(), provided that we
give utility functions to go back and forth from numerical constants and
bitmap constants (both have to be defined then in rte_eth.h).

Marc



>
> Regards,
>
> --
> Adrien Mazarguil
> 6WIND
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap
  2015-09-15 21:20                               ` Marc Sune
@ 2015-09-16 14:41                                 ` Adrien Mazarguil
  0 siblings, 0 replies; 64+ messages in thread
From: Adrien Mazarguil @ 2015-09-16 14:41 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev, Morten Brørup

On Tue, Sep 15, 2015 at 11:20:03PM +0200, Marc Sune wrote:
> Adrien,
> 
> 2015-09-15 12:04 GMT+02:00 Adrien Mazarguil <adrien.mazarguil@6wind.com>:
[...]
> > It's not so much about the way PMDs recover link information, rather about
> > the amount of changes required to switch to a bit-field API for the current
> > link speed with no clear advantage.
> 
> 
> See below; these are trivial changes.
> 
> > All PMDs must be modified, the initial
> > set of patches isn't complete in this regard.
> >
> 
> Thanks for pointing out this. There are a couple missing.
> 
[...]
> > I think Nelio was using mlx4 as an example, all PMDs have their own
> > particular method to recover it and several must perform calculations to
> > get
> > the final value. Using integers for this task is certainly easier than
> > going
> > through bit-field conversions.
> >
> 
> Drivers have their *own* way to extract the link speed from the HW, because
> the way is stored is anyway HW specific. That a driver encodes their link
> speed as a numeric value is just a coincidence, and the exception.

I concede that most non-virtual drivers (including all Intel drivers) only
perform conversions between bit-field values, for those it's just a matter
of updating a macro name in a succession of if/else or switch/case
statements which is indeed trivial.

Exceptions are currently af_packet, bnx2x, bonding (does not care actually),
enic, mlx4, null, pcap, ring, xenvirt (these last four are purely virtual
and use hard-coded values, no calculations involved but still).

> Specifically, and putting an example of e1000 (which you are right it is
> buggy in v4, see below):
[...]
> Can you please tell me which exact extra conversions are needed on the PMD
> side? It only needs to be fixed:
[...]
> Other drivers, like i40 are already ooing it correctly:

Sure, I was only pointing out the extra work required to make sure all of
them were behaving as expected.

[...]
> > Everyone agrees that a link speed bit-field is useful as an input value to
> > advertise, request and allow a set of speeds. We do not agree with its
> > usage
> > as the current link speed which is often the result of a computation. We
> > aren't talking about performance.
> >
> > A given link cannot be simultaneously at 10 Gbps and 1 Gbps right? Using a
> > bit-field for the current link speed is confusing at best. Output values do
> > not need to be included in the unified API, they are never converted back
> > into enum values.
> >
> 
> Although I agree it is unlikely that this would happen, we shouldn't
> anticipate what users will do, so in either approach you would need utility
> functions to translate from numerical to bitmap and viceversa.

Yes, obviously.

> > I'm stressing again the fact that doing so would require a changes in all
> > applications that use the current speed and in PMDs for no good reason.
> 
> Well any change in the API will. This patch (v1,v2) started as speed caps
> only, and now we are refactoring the link API. How much code has to be
> changed or how is easier for PMDs is irrelevant IMHO. What matters is if
> the API makes sense for the user.
> 
> And for that you are probably right; it might be more comprehensible to
> have "a" speed value as a result of rte_eth_get_link(), provided that we
> give utility functions to go back and forth from numerical constants and
> bitmap constants (both have to be defined then in rte_eth.h).

I fully agree with this.

Which means ETH_LINK_SPEED_* macros can be dropped (as in your patchset) and
replaced with a function or a macro that simply converts their ETH_SPEED_*
counterparts to integer values. That way we don't have to keep two confusing
sets of macros.

Probably obvious but in the reverse function, I suggest returning
ETH_SPEED_UNKNOWN for invalid values instead of the nearest match.

About struct rte_eth_link, Nelio intends to submit a patch to store
link_speed in a uint32_t for 100+Gbps links and update a few PMDs affected
by the change. Perhaps his patch should be included in your patchset?

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API
  2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
                         ` (2 preceding siblings ...)
  2015-09-07 20:52       ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
@ 2015-10-04 21:12       ` Marc Sune
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 1/4] ethdev: Added ETH_SPEED_CAP bitmap for ports Marc Sune
                           ` (4 more replies)
  3 siblings, 5 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-04 21:12 UTC (permalink / raw)
  To: dev

The current rte_eth_dev_info abstraction does not provide any mechanism to
get the supported speed(s) of an ethdev.

For some drivers (e.g. ixgbe), an educated guess could be done based on the
driver's name (driver_name in rte_eth_dev_info), see:

http://dpdk.org/ml/archives/dev/2013-August/000412.html

However, i) doing string comparisons is annoying, and can silently
break existing applications if PMDs change their names ii) it does not
provide all the supported capabilities of the ethdev iii) for some drivers it
is impossible determine correctly the (max) speed by the application
(e.g. in i40, distinguish between XL710 and X710).

In addition, the link APIs do not allow to define a set of advertised link
speeds for autonegociation.

This series of patches adds the following capabilities:

* speed_capa bitmap in rte_eth_dev_info, which is filled by the PMDs
  according to the physical device capabilities.
* refactors link API in ethdev to allow the definition of the advertised
  link speeds, fix speed (no auto-negociation) or advertise all supported
  speeds (default).

WARNING: this patch series, specifically 3/4, is NOT tested for most of the
PMDs, due to the lack of hardware. Only generic EM is tested (VM).
Minor bugs expected.

* * * * *

v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
(checkpatch).

v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into ETH_SPEED.
    Converted field speed in struct rte_eth_conf to speed, to allow a bitmap
    for defining the announced speeds, as suggested M. Brorup. Fixed spelling
    issues.

v4: fixed errata in the documentation of field speeds of rte_eth_conf, and
    commit 1/2 message. rebased to v2.1.0. v3 was incorrectly based on
    ~2.1.0-rc1.

v5: revert to v2 speed capabilities patch. Fixed MLX4 speed capabilities
    (thanks N. Laranjeiro). Refactored link speed API to allow setting
    advertised speeds (3/4). Added NO_AUTONEG option to explicitely disable
    auto-negociation. Updated 2.2 rel. notes (4/4). Rebased to current HEAD.


Marc Sune (4):
  ethdev: Added ETH_SPEED_CAP bitmap for ports
  ethdev: Fill speed capability bitmaps in the PMDs
  ethdev: redesign link speed config API
  doc: update with link changes

 app/test-pmd/cmdline.c                     | 124 +++++++++++++++--------------
 app/test/virtual_pmd.c                     |   4 +-
 doc/guides/rel_notes/release_2_2.rst       |  22 ++++-
 drivers/net/af_packet/rte_eth_af_packet.c  |   5 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c  |  14 ++--
 drivers/net/cxgbe/base/t4_hw.c             |   8 +-
 drivers/net/e1000/base/e1000_80003es2lan.c |   6 +-
 drivers/net/e1000/base/e1000_82541.c       |   8 +-
 drivers/net/e1000/base/e1000_82543.c       |   4 +-
 drivers/net/e1000/base/e1000_82575.c       |  11 +--
 drivers/net/e1000/base/e1000_api.c         |   2 +-
 drivers/net/e1000/base/e1000_api.h         |   2 +-
 drivers/net/e1000/base/e1000_defines.h     |   4 +-
 drivers/net/e1000/base/e1000_hw.h          |   2 +-
 drivers/net/e1000/base/e1000_ich8lan.c     |   4 +-
 drivers/net/e1000/base/e1000_mac.c         |   9 ++-
 drivers/net/e1000/base/e1000_mac.h         |   6 +-
 drivers/net/e1000/base/e1000_vf.c          |   4 +-
 drivers/net/e1000/base/e1000_vf.h          |   2 +-
 drivers/net/e1000/em_ethdev.c              | 104 ++++++++++++------------
 drivers/net/e1000/igb_ethdev.c             |  99 ++++++++++++-----------
 drivers/net/fm10k/fm10k_ethdev.c           |   5 +-
 drivers/net/i40e/i40e_ethdev.c             |  75 +++++++++--------
 drivers/net/i40e/i40e_ethdev_vf.c          |  11 +--
 drivers/net/ixgbe/ixgbe_ethdev.c           |  74 ++++++++---------
 drivers/net/mlx4/mlx4.c                    |   6 ++
 drivers/net/mpipe/mpipe_tilegx.c           |   6 +-
 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/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              |  97 +++++++++++++++++-----
 35 files changed, 481 insertions(+), 318 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v5 1/4] ethdev: Added ETH_SPEED_CAP bitmap for ports
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
@ 2015-10-04 21:12         ` Marc Sune
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 2/4] ethdev: Fill speed capability bitmaps in the PMDs Marc Sune
                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-04 21:12 UTC (permalink / raw)
  To: dev

Added constants and bitmap to struct rte_eth_dev_info to be used by PMDs.

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 lib/librte_ether/rte_ethdev.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 8a8c82b..951a423 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -811,6 +811,29 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */
 #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 {
 	struct rte_pci_device *pci_dev; /**< Device PCI information. */
 	const char *driver_name; /**< Device Driver name. */
@@ -837,6 +860,7 @@ struct rte_eth_dev_info {
 	uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */
 	uint16_t vmdq_queue_num;  /**< Queue number for VMDQ pools. */
 	uint16_t vmdq_pool_base;  /**< First ID of VMDQ pools. */
+	uint32_t speed_capa;  /**< Supported speeds bitmap (ETH_SPEED_CAP_). */
 };
 
 /** Maximum name length for extended statistics counters */
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v5 2/4] ethdev: Fill speed capability bitmaps in the PMDs
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 1/4] ethdev: Added ETH_SPEED_CAP bitmap for ports Marc Sune
@ 2015-10-04 21:12         ` Marc Sune
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API Marc Sune
                           ` (2 subsequent siblings)
  4 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-04 21:12 UTC (permalink / raw)
  To: dev

Added speed capabilities to all pmds supporting physical NICs:

* e1000
* ixgbe
* i40
* mlx4
* fm10k

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 drivers/net/e1000/em_ethdev.c    |  6 ++++++
 drivers/net/e1000/igb_ethdev.c   |  6 ++++++
 drivers/net/fm10k/fm10k_ethdev.c |  3 +++
 drivers/net/i40e/i40e_ethdev.c   |  9 +++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 drivers/net/mlx4/mlx4.c          |  4 ++++
 6 files changed, 38 insertions(+)

diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 912f5dd..72f792c 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -933,6 +933,12 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	dev_info->max_rx_queues = 1;
 	dev_info->max_tx_queues = 1;
+
+	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;
 }
 
 /* return 0 means link status changed, -1 means not changed */
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 848ef6e..927f5d9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1570,6 +1570,12 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		},
 		.txq_flags = 0,
 	};
+
+	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;
 }
 
 static void
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index a69c990..ca6357c 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -964,6 +964,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
 				ETH_TXQ_FLAGS_NOOFFLOADS,
 	};
 
+	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;
 }
 
 static int
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..8a5dfbf 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1624,6 +1624,7 @@ static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vsi *vsi = pf->main_vsi;
 
 	dev_info->max_rx_queues = vsi->nb_qps;
@@ -1683,6 +1684,14 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		dev_info->max_rx_queues += dev_info->vmdq_queue_num;
 		dev_info->max_tx_queues += dev_info->vmdq_queue_num;
 	}
+
+	if (i40e_is_40G_device(hw->device_id))
+		/* For XL710 */
+		dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_10G;
+	else
+		/* For X710 */
+		dev_info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G;
+
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ec2918c..053c77e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -2399,6 +2399,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->hash_key_size = IXGBE_HKEY_MAX_INDEX * sizeof(uint32_t);
 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
 	dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
+
+	dev_info->speed_capa = ETH_SPEED_CAP_1G | ETH_SPEED_CAP_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)
+
+		dev_info->speed_capa |= ETH_SPEED_CAP_100M_FD
+					/*| ETH_SPEED_CAP_100M_HD*/;
 }
 
 static void
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 2f49ed5..88f95e5 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -3847,6 +3847,10 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 		  DEV_TX_OFFLOAD_UDP_CKSUM |
 		  DEV_TX_OFFLOAD_TCP_CKSUM) :
 		 0);
+
+	info->speed_capa = ETH_SPEED_CAP_10G | ETH_SPEED_CAP_40G |
+					ETH_SPEED_CAP_56G;
+
 	priv_unlock(priv);
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 1/4] ethdev: Added ETH_SPEED_CAP bitmap for ports Marc Sune
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 2/4] ethdev: Fill speed capability bitmaps in the PMDs Marc Sune
@ 2015-10-04 21:12         ` Marc Sune
  2015-10-05 10:59           ` Neil Horman
                             ` (2 more replies)
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 4/4] doc: update with link changes Marc Sune
  2015-10-04 21:21         ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
  4 siblings, 3 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-04 21:12 UTC (permalink / raw)
  To: dev

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
  (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.
* Adapted testpmd to the new link API.

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 app/test-pmd/cmdline.c                     | 124 +++++++++++++++--------------
 app/test/virtual_pmd.c                     |   4 +-
 drivers/net/af_packet/rte_eth_af_packet.c  |   5 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c  |  14 ++--
 drivers/net/cxgbe/base/t4_hw.c             |   8 +-
 drivers/net/e1000/base/e1000_80003es2lan.c |   6 +-
 drivers/net/e1000/base/e1000_82541.c       |   8 +-
 drivers/net/e1000/base/e1000_82543.c       |   4 +-
 drivers/net/e1000/base/e1000_82575.c       |  11 +--
 drivers/net/e1000/base/e1000_api.c         |   2 +-
 drivers/net/e1000/base/e1000_api.h         |   2 +-
 drivers/net/e1000/base/e1000_defines.h     |   4 +-
 drivers/net/e1000/base/e1000_hw.h          |   2 +-
 drivers/net/e1000/base/e1000_ich8lan.c     |   4 +-
 drivers/net/e1000/base/e1000_mac.c         |   9 ++-
 drivers/net/e1000/base/e1000_mac.h         |   6 +-
 drivers/net/e1000/base/e1000_vf.c          |   4 +-
 drivers/net/e1000/base/e1000_vf.h          |   2 +-
 drivers/net/e1000/em_ethdev.c              | 108 ++++++++++++-------------
 drivers/net/e1000/igb_ethdev.c             | 103 ++++++++++++------------
 drivers/net/fm10k/fm10k_ethdev.c           |   8 +-
 drivers/net/i40e/i40e_ethdev.c             |  70 ++++++++--------
 drivers/net/i40e/i40e_ethdev_vf.c          |  11 +--
 drivers/net/ixgbe/ixgbe_ethdev.c           |  72 ++++++++---------
 drivers/net/mlx4/mlx4.c                    |   2 +
 drivers/net/mpipe/mpipe_tilegx.c           |   6 +-
 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/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 ++++++++++++++++----------
 34 files changed, 437 insertions(+), 356 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0f8f48f..c62f5be 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -897,14 +897,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()) {
@@ -912,40 +963,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 =
@@ -1000,8 +1029,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");
@@ -1011,36 +1039,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/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 bdd9628..a5d689d 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -115,9 +115,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/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index c0f0b99..f375f95 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/e1000/base/e1000_80003es2lan.c b/drivers/net/e1000/base/e1000_80003es2lan.c
index 72692d9..8ca66c4 100644
--- a/drivers/net/e1000/base/e1000_80003es2lan.c
+++ b/drivers/net/e1000/base/e1000_80003es2lan.c
@@ -52,7 +52,7 @@ STATIC s32  e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
 STATIC s32  e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
 STATIC s32  e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
 STATIC s32  e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+STATIC s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u32 *speed,
 					       u16 *duplex);
 STATIC s32  e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
 STATIC s32  e1000_init_hw_80003es2lan(struct e1000_hw *hw);
@@ -789,7 +789,7 @@ STATIC s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
  *
  *  Retrieve the current speed and duplex configuration.
  **/
-STATIC s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u32 *speed,
 					      u16 *duplex)
 {
 	s32 ret_val;
@@ -1236,7 +1236,7 @@ STATIC s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
 STATIC s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
 {
 	s32 ret_val = E1000_SUCCESS;
-	u16 speed;
+	u32 speed;
 	u16 duplex;
 
 	DEBUGFUNC("e1000_configure_on_link_up");
diff --git a/drivers/net/e1000/base/e1000_82541.c b/drivers/net/e1000/base/e1000_82541.c
index 952aea2..707b317 100644
--- a/drivers/net/e1000/base/e1000_82541.c
+++ b/drivers/net/e1000/base/e1000_82541.c
@@ -47,7 +47,7 @@ STATIC s32  e1000_init_nvm_params_82541(struct e1000_hw *hw);
 STATIC s32  e1000_init_mac_params_82541(struct e1000_hw *hw);
 STATIC s32  e1000_reset_hw_82541(struct e1000_hw *hw);
 STATIC s32  e1000_init_hw_82541(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+STATIC s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u32 *speed,
 					 u16 *duplex);
 STATIC s32  e1000_phy_hw_reset_82541(struct e1000_hw *hw);
 STATIC s32  e1000_setup_copper_link_82541(struct e1000_hw *hw);
@@ -437,7 +437,7 @@ out:
  *
  * Retrieve the current speed and duplex configuration.
  **/
-STATIC s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u32 *speed,
 					u16 *duplex)
 {
 	struct e1000_phy_info *phy = &hw->phy;
@@ -667,8 +667,8 @@ STATIC s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
 	struct e1000_phy_info *phy = &hw->phy;
 	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
 	s32 ret_val;
-	u32 idle_errs = 0;
-	u16 phy_data, phy_saved_data, speed, duplex, i;
+	u32 idle_errs = 0, speed;
+	u16 phy_data, phy_saved_data, duplex, i;
 	u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
 	u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
 						IGP01E1000_PHY_AGC_PARAM_A,
diff --git a/drivers/net/e1000/base/e1000_82543.c b/drivers/net/e1000/base/e1000_82543.c
index 36335ba..9ef3d80 100644
--- a/drivers/net/e1000/base/e1000_82543.c
+++ b/drivers/net/e1000/base/e1000_82543.c
@@ -1192,9 +1192,9 @@ out:
 STATIC s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
 {
 	struct e1000_mac_info *mac = &hw->mac;
-	u32 icr, rctl;
+	u32 icr, rctl, speed;
 	s32 ret_val;
-	u16 speed, duplex;
+	u16 duplex;
 	bool link;
 
 	DEBUGFUNC("e1000_check_for_copper_link_82543");
diff --git a/drivers/net/e1000/base/e1000_82575.c b/drivers/net/e1000/base/e1000_82575.c
index 25fa672..386f058 100644
--- a/drivers/net/e1000/base/e1000_82575.c
+++ b/drivers/net/e1000/base/e1000_82575.c
@@ -53,7 +53,7 @@ STATIC void e1000_release_nvm_82575(struct e1000_hw *hw);
 STATIC s32  e1000_check_for_link_82575(struct e1000_hw *hw);
 STATIC s32  e1000_check_for_link_media_swap(struct e1000_hw *hw);
 STATIC s32  e1000_get_cfg_done_82575(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
+STATIC s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u32 *speed,
 					 u16 *duplex);
 STATIC s32  e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
 STATIC s32  e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
@@ -80,7 +80,7 @@ STATIC s32  e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
 STATIC void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
 STATIC s32  e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
 STATIC s32  e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
-						 u16 *speed, u16 *duplex);
+						 u32 *speed, u16 *duplex);
 STATIC s32  e1000_get_phy_id_82575(struct e1000_hw *hw);
 STATIC void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
 STATIC bool e1000_sgmii_active_82575(struct e1000_hw *hw);
@@ -1165,7 +1165,7 @@ STATIC s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
  *  interface, use PCS to retrieve the link speed and duplex information.
  *  Otherwise, use the generic function to get the link speed and duplex info.
  **/
-STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u32 *speed,
 					u16 *duplex)
 {
 	s32 ret_val;
@@ -1192,7 +1192,8 @@ STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
 STATIC s32 e1000_check_for_link_82575(struct e1000_hw *hw)
 {
 	s32 ret_val;
-	u16 speed, duplex;
+	u32 speed;
+	u16 duplex;
 
 	DEBUGFUNC("e1000_check_for_link_82575");
 
@@ -1316,7 +1317,7 @@ STATIC void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
  *  duplex, then store the values in the pointers provided.
  **/
 STATIC s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
-						u16 *speed, u16 *duplex)
+						u32 *speed, u16 *duplex)
 {
 	struct e1000_mac_info *mac = &hw->mac;
 	u32 pcs;
diff --git a/drivers/net/e1000/base/e1000_api.c b/drivers/net/e1000/base/e1000_api.c
index a064565..08e103a 100644
--- a/drivers/net/e1000/base/e1000_api.c
+++ b/drivers/net/e1000/base/e1000_api.c
@@ -669,7 +669,7 @@ s32 e1000_setup_link(struct e1000_hw *hw)
  *  variables passed in. This is a function pointer entry point called
  *  by drivers.
  **/
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u32 *speed, u16 *duplex)
 {
 	if (hw->mac.ops.get_link_up_info)
 		return hw->mac.ops.get_link_up_info(hw, speed, duplex);
diff --git a/drivers/net/e1000/base/e1000_api.h b/drivers/net/e1000/base/e1000_api.h
index 02b16da..39579e0 100644
--- a/drivers/net/e1000/base/e1000_api.h
+++ b/drivers/net/e1000/base/e1000_api.h
@@ -65,7 +65,7 @@ s32 e1000_check_for_link(struct e1000_hw *hw);
 s32 e1000_reset_hw(struct e1000_hw *hw);
 s32 e1000_init_hw(struct e1000_hw *hw);
 s32 e1000_setup_link(struct e1000_hw *hw);
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u32 *speed, u16 *duplex);
 s32 e1000_disable_pcie_master(struct e1000_hw *hw);
 void e1000_config_collision_dist(struct e1000_hw *hw);
 void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
diff --git a/drivers/net/e1000/base/e1000_defines.h b/drivers/net/e1000/base/e1000_defines.h
index 278c507..20c4153 100644
--- a/drivers/net/e1000/base/e1000_defines.h
+++ b/drivers/net/e1000/base/e1000_defines.h
@@ -347,8 +347,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define SPEED_100	100
 #define SPEED_1000	1000
 #define SPEED_2500	2500
-#define HALF_DUPLEX	1
-#define FULL_DUPLEX	2
+#define HALF_DUPLEX	0
+#define FULL_DUPLEX	1
 
 #define PHY_FORCE_TIME	20
 
diff --git a/drivers/net/e1000/base/e1000_hw.h b/drivers/net/e1000/base/e1000_hw.h
index 4dd92a3..b48a759 100644
--- a/drivers/net/e1000/base/e1000_hw.h
+++ b/drivers/net/e1000/base/e1000_hw.h
@@ -682,7 +682,7 @@ struct e1000_mac_operations {
 	void (*clear_vfta)(struct e1000_hw *);
 	s32  (*get_bus_info)(struct e1000_hw *);
 	void (*set_lan_id)(struct e1000_hw *);
-	s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+	s32  (*get_link_up_info)(struct e1000_hw *, u32 *, u16 *);
 	s32  (*led_on)(struct e1000_hw *);
 	s32  (*led_off)(struct e1000_hw *);
 	void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
diff --git a/drivers/net/e1000/base/e1000_ich8lan.c b/drivers/net/e1000/base/e1000_ich8lan.c
index 3b1627b..7fe9955 100644
--- a/drivers/net/e1000/base/e1000_ich8lan.c
+++ b/drivers/net/e1000/base/e1000_ich8lan.c
@@ -104,7 +104,7 @@ STATIC s32  e1000_setup_link_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw);
 STATIC s32  e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
-					   u16 *speed, u16 *duplex);
+					   u32 *speed, u16 *duplex);
 STATIC s32  e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_led_on_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_led_off_ich8lan(struct e1000_hw *hw);
@@ -4561,7 +4561,7 @@ STATIC s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw)
  *  information and then calls the Kumeran lock loss workaround for links at
  *  gigabit speeds.
  **/
-STATIC s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u32 *speed,
 					  u16 *duplex)
 {
 	s32 ret_val;
diff --git a/drivers/net/e1000/base/e1000_mac.c b/drivers/net/e1000/base/e1000_mac.c
index c8ec049..6703a17 100644
--- a/drivers/net/e1000/base/e1000_mac.c
+++ b/drivers/net/e1000/base/e1000_mac.c
@@ -106,7 +106,7 @@ void e1000_null_mac_generic(struct e1000_hw E1000_UNUSEDARG *hw)
  *  @hw: pointer to the HW structure
  **/
 s32 e1000_null_link_info(struct e1000_hw E1000_UNUSEDARG *hw,
-			 u16 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d)
+			 u32 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d)
 {
 	DEBUGFUNC("e1000_null_link_info");
 	UNREFERENCED_3PARAMETER(hw, s, d);
@@ -1346,7 +1346,8 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
 	s32 ret_val = E1000_SUCCESS;
 	u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
 	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
-	u16 speed, duplex;
+	u32 speed;
+	u16 duplex;
 
 	DEBUGFUNC("e1000_config_fc_after_link_up_generic");
 
@@ -1648,7 +1649,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
  *  Read the status register for the current speed/duplex and store the current
  *  speed and duplex for copper connections.
  **/
-s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
+s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u32 *speed,
 					      u16 *duplex)
 {
 	u32 status;
@@ -1688,7 +1689,7 @@ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
  *  for fiber/serdes links.
  **/
 s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSEDARG *hw,
-						    u16 *speed, u16 *duplex)
+						    u32 *speed, u16 *duplex)
 {
 	DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
 	UNREFERENCED_1PARAMETER(hw);
diff --git a/drivers/net/e1000/base/e1000_mac.h b/drivers/net/e1000/base/e1000_mac.h
index 5a7ce4a..987df76 100644
--- a/drivers/net/e1000/base/e1000_mac.h
+++ b/drivers/net/e1000/base/e1000_mac.h
@@ -40,7 +40,7 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw);
 #endif /* E1000_REMOVED */
 void e1000_null_mac_generic(struct e1000_hw *hw);
 s32  e1000_null_ops_generic(struct e1000_hw *hw);
-s32  e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
+s32  e1000_null_link_info(struct e1000_hw *hw, u32 *s, u16 *d);
 bool e1000_null_mng_mode(struct e1000_hw *hw);
 void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a);
 void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
@@ -61,10 +61,10 @@ s32  e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
 void e1000_set_lan_id_single_port(struct e1000_hw *hw);
 void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
 s32  e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
-s32  e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
+s32  e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u32 *speed,
 					       u16 *duplex);
 s32  e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
-						     u16 *speed, u16 *duplex);
+						     u32 *speed, u16 *duplex);
 s32  e1000_id_led_init_generic(struct e1000_hw *hw);
 s32  e1000_led_on_generic(struct e1000_hw *hw);
 s32  e1000_led_off_generic(struct e1000_hw *hw);
diff --git a/drivers/net/e1000/base/e1000_vf.c b/drivers/net/e1000/base/e1000_vf.c
index 778561e..2221f1c 100644
--- a/drivers/net/e1000/base/e1000_vf.c
+++ b/drivers/net/e1000/base/e1000_vf.c
@@ -43,7 +43,7 @@ STATIC s32 e1000_setup_link_vf(struct e1000_hw *hw);
 STATIC s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw);
 STATIC s32 e1000_init_mac_params_vf(struct e1000_hw *hw);
 STATIC s32 e1000_check_for_link_vf(struct e1000_hw *hw);
-STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u32 *speed,
 				     u16 *duplex);
 STATIC s32 e1000_init_hw_vf(struct e1000_hw *hw);
 STATIC s32 e1000_reset_hw_vf(struct e1000_hw *hw);
@@ -220,7 +220,7 @@ STATIC s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw)
  *  Since we cannot read the PHY and get accurate link info, we must rely upon
  *  the status register's data which is often stale and inaccurate.
  **/
-STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u32 *speed,
 				     u16 *duplex)
 {
 	s32 status;
diff --git a/drivers/net/e1000/base/e1000_vf.h b/drivers/net/e1000/base/e1000_vf.h
index 6d5bd99..9d801ad 100644
--- a/drivers/net/e1000/base/e1000_vf.h
+++ b/drivers/net/e1000/base/e1000_vf.h
@@ -201,7 +201,7 @@ struct e1000_mac_operations {
 	s32  (*check_for_link)(struct e1000_hw *);
 	void (*clear_vfta)(struct e1000_hw *);
 	s32  (*get_bus_info)(struct e1000_hw *);
-	s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+	s32  (*get_link_up_info)(struct e1000_hw *, u32 *, u16 *);
 	void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
 	s32  (*reset_hw)(struct e1000_hw *);
 	s32  (*init_hw)(struct e1000_hw *);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 72f792c..19d774f 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -493,6 +493,9 @@ eth_em_start(struct rte_eth_dev *dev)
 	struct e1000_hw *hw =
 		E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	int ret, mask;
+	uint32_t *speeds;
+	int num_speeds;
+	bool autoneg;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -547,56 +550,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);
 
 	/* check if lsc interrupt feature is enabled */
@@ -616,9 +609,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);
 }
@@ -934,11 +926,11 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->max_rx_queues = 1;
 	dev_info->max_tx_queues = 1;
 
-	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 */
@@ -989,11 +981,11 @@ eth_em_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 	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;
+		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 927f5d9..7d407f4 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -889,6 +889,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();
 
@@ -984,48 +987,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);
 
 	/* check if lsc interrupt feature is enabled */
@@ -1055,9 +1056,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);
 }
@@ -1571,11 +1571,11 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		.txq_flags = 0,
 	};
 
-	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
@@ -1683,11 +1683,14 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 	if (link_check) {
 		hw->mac.ops.get_link_up_info(hw, &link.link_speed,
 					  &link.link_duplex);
-		link.link_status = 1;
+		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 ca6357c..6e05355 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -862,7 +862,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;
 }
@@ -964,9 +964,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
 				ETH_TXQ_FLAGS_NOOFFLOADS,
 	};
 
-	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 8a5dfbf..c3b3b9e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -835,27 +835,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;
 }
@@ -924,9 +917,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;
@@ -944,10 +937,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;
 	}
@@ -995,6 +986,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");
@@ -1209,7 +1207,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;
@@ -1231,22 +1229,22 @@ 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;
 	}
 
@@ -1687,10 +1685,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;
 
 }
 
@@ -6195,15 +6193,15 @@ i40e_timesync_enable(struct rte_eth_dev *dev)
 	uint32_t tsync_inc_h;
 
 	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 b694400..8d3acae 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1635,13 +1635,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 053c77e..a1103f0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1676,14 +1676,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;
 	}
@@ -1769,32 +1768,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;
@@ -2400,15 +2389,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
 	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
@@ -2471,9 +2461,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);
 
@@ -2486,8 +2476,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;
@@ -2500,26 +2490,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);
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 88f95e5..41c0ad1 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -4207,6 +4207,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/mpipe/mpipe_tilegx.c b/drivers/net/mpipe/mpipe_tilegx.c
index 743feef..5875371 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/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index e244595..7704fa6 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -79,9 +79,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 f2e4634..ea7a28f 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 0ba36d5..626c381 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/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index a70be5c..6860360 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -697,9 +697,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 73e8bce..fb492ee 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 dummy 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 inline struct rte_mbuf *
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index c9b78f9..92e6a18 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -83,8 +83,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 f593f6e..29b2960 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1072,6 +1072,55 @@ rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 }
 
 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 951a423..bd333e4 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -238,26 +238,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 -> full duplex, 0 -> half duplex */
+	uint8_t link_autoneg : 1;  /**< 1 -> link speed has been autoneg */
+	uint8_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
@@ -747,10 +780,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
@@ -812,26 +849,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 {
@@ -1667,6 +1684,22 @@ struct eth_driver {
 extern 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
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v5 4/4] doc: update with link changes
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
                           ` (2 preceding siblings ...)
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API Marc Sune
@ 2015-10-04 21:12         ` Marc Sune
  2015-10-04 21:21         ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
  4 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-04 21:12 UTC (permalink / raw)
  To: dev

Add new features, ABI changes and resolved issues notice for
the refactored link patch.

Signed-off-by: Marc Sune <marcdevel@gmail.com>
---
 doc/guides/rel_notes/release_2_2.rst | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 5687676..e8bd4d6 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -4,6 +4,17 @@ DPDK Release 2.2
 New Features
 ------------
 
+* **ethdev: define a set of advertised link speeds.**
+
+  Allowing to define a set of advertised speeds for auto-negociation,
+  explicitely disable link auto-negociation (single speed) and full
+  auto-negociation.
+
+* **ethdev: add speed_cap bitmap to recover eth device link speed capabilities
+  define a set of advertised link speeds.**
+
+  ``struct rte_eth_dev_info`` has now speed_cap bitmap, which allows the
+  application to recover the supported speeds for that ethernet device.
 
 Resolved Issues
 ---------------
@@ -48,6 +59,11 @@ Libraries
   Fixed issue where an incorrect Cuckoo Hash key table size could be
   calculated limiting the size to 4GB.
 
+* **ethdev: Fixed link_speed overflow in rte_eth_link for 100Gbps.**
+
+  100Gbps in Mbps (100000) exceeds 16 bit max value of ``link_speed`` in
+  ``rte_eth_link``.
+
 
 Examples
 ~~~~~~~~
@@ -81,7 +97,6 @@ API Changes
 * The deprecated ring PMD functions are removed:
   rte_eth_ring_pair_create() and rte_eth_ring_pair_attach().
 
-
 ABI Changes
 -----------
 
@@ -91,6 +106,11 @@ ABI Changes
 * The ethdev flow director entries for SCTP were changed.
   It was already done in 2.1 for CONFIG_RTE_NEXT_ABI.
 
+* The ethdev rte_eth_link and rte_eth_conf structures were changes to
+  support the new link API.
+
+* The ethdev rte_eth_dev_info was changed to support device speed capabilities.
+
 * The mbuf structure was changed to support unified packet type.
   It was already done in 2.1 for CONFIG_RTE_NEXT_ABI.
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API
  2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
                           ` (3 preceding siblings ...)
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 4/4] doc: update with link changes Marc Sune
@ 2015-10-04 21:21         ` Marc Sune
  4 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-04 21:21 UTC (permalink / raw)
  To: dev

2015-10-04 23:12 GMT+02:00 Marc Sune <marcdevel@gmail.com>:

> The current rte_eth_dev_info abstraction does not provide any mechanism to
> get the supported speed(s) of an ethdev.
>
> For some drivers (e.g. ixgbe), an educated guess could be done based on the
> driver's name (driver_name in rte_eth_dev_info), see:
>
> http://dpdk.org/ml/archives/dev/2013-August/000412.html
>
> However, i) doing string comparisons is annoying, and can silently
> break existing applications if PMDs change their names ii) it does not
> provide all the supported capabilities of the ethdev iii) for some drivers
> it
> is impossible determine correctly the (max) speed by the application
> (e.g. in i40, distinguish between XL710 and X710).
>
> In addition, the link APIs do not allow to define a set of advertised link
> speeds for autonegociation.
>
> This series of patches adds the following capabilities:
>
> * speed_capa bitmap in rte_eth_dev_info, which is filled by the PMDs
>   according to the physical device capabilities.
> * refactors link API in ethdev to allow the definition of the advertised
>   link speeds, fix speed (no auto-negociation) or advertise all supported
>   speeds (default).
>
> WARNING: this patch series, specifically 3/4, is NOT tested for most of the
> PMDs, due to the lack of hardware. Only generic EM is tested (VM).
> Minor bugs expected.
>

Please mind this.

I do not have access currently to my usual testbed (several 1000/igb +
XL710). It may take some time to be rearmed, so in the meantime I've
circulated it now to make sure I've correctly captured the conclusions of
the discussion and to ask for some help on those PMDs I can anyway not test
due to the lack of HW.

Regards
Marc


>
> * * * * *
>
> v2: rebase, converted speed_capa into 32 bits bitmap, fixed alignment
> (checkpatch).
>
> v3: rebase to v2.1. unified ETH_LINK_SPEED and ETH_SPEED_CAP into
> ETH_SPEED.
>     Converted field speed in struct rte_eth_conf to speed, to allow a
> bitmap
>     for defining the announced speeds, as suggested M. Brorup. Fixed
> spelling
>     issues.
>
> v4: fixed errata in the documentation of field speeds of rte_eth_conf, and
>     commit 1/2 message. rebased to v2.1.0. v3 was incorrectly based on
>     ~2.1.0-rc1.
>
> v5: revert to v2 speed capabilities patch. Fixed MLX4 speed capabilities
>     (thanks N. Laranjeiro). Refactored link speed API to allow setting
>     advertised speeds (3/4). Added NO_AUTONEG option to explicitely disable
>     auto-negociation. Updated 2.2 rel. notes (4/4). Rebased to current
> HEAD.
>
>
> Marc Sune (4):
>   ethdev: Added ETH_SPEED_CAP bitmap for ports
>   ethdev: Fill speed capability bitmaps in the PMDs
>   ethdev: redesign link speed config API
>   doc: update with link changes
>
>  app/test-pmd/cmdline.c                     | 124
> +++++++++++++++--------------
>  app/test/virtual_pmd.c                     |   4 +-
>  doc/guides/rel_notes/release_2_2.rst       |  22 ++++-
>  drivers/net/af_packet/rte_eth_af_packet.c  |   5 +-
>  drivers/net/bonding/rte_eth_bond_8023ad.c  |  14 ++--
>  drivers/net/cxgbe/base/t4_hw.c             |   8 +-
>  drivers/net/e1000/base/e1000_80003es2lan.c |   6 +-
>  drivers/net/e1000/base/e1000_82541.c       |   8 +-
>  drivers/net/e1000/base/e1000_82543.c       |   4 +-
>  drivers/net/e1000/base/e1000_82575.c       |  11 +--
>  drivers/net/e1000/base/e1000_api.c         |   2 +-
>  drivers/net/e1000/base/e1000_api.h         |   2 +-
>  drivers/net/e1000/base/e1000_defines.h     |   4 +-
>  drivers/net/e1000/base/e1000_hw.h          |   2 +-
>  drivers/net/e1000/base/e1000_ich8lan.c     |   4 +-
>  drivers/net/e1000/base/e1000_mac.c         |   9 ++-
>  drivers/net/e1000/base/e1000_mac.h         |   6 +-
>  drivers/net/e1000/base/e1000_vf.c          |   4 +-
>  drivers/net/e1000/base/e1000_vf.h          |   2 +-
>  drivers/net/e1000/em_ethdev.c              | 104 ++++++++++++------------
>  drivers/net/e1000/igb_ethdev.c             |  99 ++++++++++++-----------
>  drivers/net/fm10k/fm10k_ethdev.c           |   5 +-
>  drivers/net/i40e/i40e_ethdev.c             |  75 +++++++++--------
>  drivers/net/i40e/i40e_ethdev_vf.c          |  11 +--
>  drivers/net/ixgbe/ixgbe_ethdev.c           |  74 ++++++++---------
>  drivers/net/mlx4/mlx4.c                    |   6 ++
>  drivers/net/mpipe/mpipe_tilegx.c           |   6 +-
>  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/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              |  97 +++++++++++++++++-----
>  35 files changed, 481 insertions(+), 318 deletions(-)
>
> --
> 2.1.4
>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API Marc Sune
@ 2015-10-05 10:59           ` Neil Horman
  2015-10-07 13:31             ` Marc Sune
  2015-10-06 13:48           ` Nélio Laranjeiro
  2016-01-28 17:33           ` Harish Patil
  2 siblings, 1 reply; 64+ messages in thread
From: Neil Horman @ 2015-10-05 10:59 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

On Sun, Oct 04, 2015 at 11:12:46PM +0200, Marc Sune wrote:
> 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
>   (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.
> * Adapted testpmd to the new link API.
> 
> Signed-off-by: Marc Sune <marcdevel@gmail.com>
>  
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index f593f6e..29b2960 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -1072,6 +1072,55 @@ rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
>  }
>  
>  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;
> +}
> +

This nees to go in the appropriate version.map file for shared library building.

> +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 951a423..bd333e4 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -238,26 +238,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 -> full duplex, 0 -> half duplex */
> +	uint8_t link_autoneg : 1;  /**< 1 -> link speed has been autoneg */
> +	uint8_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
> @@ -747,10 +780,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.
> +				*/
This structure is allocated by applications, and the link_speed/duplex field may
be accessed by them.  As such this is an ABI change and should go through the
ABI process.  Arguably, while its not really supposed to be done, given that
there are so many changes comming to rte_eth_dev for 2.2, I could see an
argument for sliding this in with those changes, so we didn't have to wait for
an additional relelase cycle.

The removal of the Speed/Duplex macros should also be noted.

 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API Marc Sune
  2015-10-05 10:59           ` Neil Horman
@ 2015-10-06 13:48           ` Nélio Laranjeiro
  2015-10-07 13:37             ` Marc Sune
  2016-01-28 17:33           ` Harish Patil
  2 siblings, 1 reply; 64+ messages in thread
From: Nélio Laranjeiro @ 2015-10-06 13:48 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev

Hi Marc,

On Sun, Oct 04, 2015 at 11:12:46PM +0200, Marc Sune wrote:
>[...]
>  /**
> + * 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 -> full duplex, 0 -> half duplex */
> +	uint8_t link_autoneg : 1;  /**< 1 -> link speed has been autoneg */
> +	uint8_t link_status  : 1;  /**< 1 -> link up, 0 -> link down */
> +} __attribute__((aligned(8)));      /**< aligned for atomic64 read/write */
>[...]

Pretty good.  One question, why did you not merge link_duplex, autoneg,
and status like:

	struct rte_eth_link {
		uint32_t link_speed;
		uint32_t link_duplex:1;
		uint32_t link_autoneg:1;
		uint32_t link_status:1;
	};

is it really useful to keep a uint16_t for the duplex alone?

Another point, the comment about link_duplex field should point to the
defines you have changed i.e. ETH_LINK_HALF_DUPLEX, ETH_LINK_FULL_DUPLEX.

Regards,

-- 
Nélio Laranjeiro
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2015-10-05 10:59           ` Neil Horman
@ 2015-10-07 13:31             ` Marc Sune
  0 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-07 13:31 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev

2015-10-05 12:59 GMT+02:00 Neil Horman <nhorman@tuxdriver.com>:

> On Sun, Oct 04, 2015 at 11:12:46PM +0200, Marc Sune wrote:
> > 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
> >   (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.
> > * Adapted testpmd to the new link API.
> >
> > Signed-off-by: Marc Sune <marcdevel@gmail.com>
> >
> > diff --git a/lib/librte_ether/rte_ethdev.c
> b/lib/librte_ether/rte_ethdev.c
> > index f593f6e..29b2960 100644
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -1072,6 +1072,55 @@ rte_eth_dev_check_mq_mode(uint8_t port_id,
> uint16_t nb_rx_q, uint16_t nb_tx_q,
> >  }
> >
> >  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;
> > +}
> > +
>
> This nees to go in the appropriate version.map file for shared library
> building.
>
> > +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 951a423..bd333e4 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -238,26 +238,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 -> full duplex, 0 -> half duplex
> */
> > +     uint8_t link_autoneg : 1;  /**< 1 -> link speed has been autoneg */
> > +     uint8_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
> > @@ -747,10 +780,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.
> > +                             */
> This structure is allocated by applications, and the link_speed/duplex
> field may
> be accessed by them.  As such this is an ABI change and should go through
> the
> ABI process.  Arguably, while its not really supposed to be done, given
> that
> there are so many changes comming to rte_eth_dev for 2.2, I could see an
> argument for sliding this in with those changes, so we didn't have to wait
> for
> an additional relelase cycle.
>

If I understand you correctly you are arguing that this patch should go
through the process of NEXT_ABI -> unique implementation. I keep saying I
do not understand what is the benefit of doing so when the ABI for 2.2 is
going to change anyway (even other patches will modify ethdev ABI).

Having a strict rule for ABI changes between minor releases (e.g. 2.1.0 and
2.1.1) is a must or if the next release is announced to be ABI compatible.
Other than that I don't see it, specially since users have to recompile
anyway their binaries due to (other) ABI changes.

But maybe I am missing something?


> The removal of the Speed/Duplex macros should also be noted.
>

Agree. I will add it into the doc

Marc

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2015-10-06 13:48           ` Nélio Laranjeiro
@ 2015-10-07 13:37             ` Marc Sune
  0 siblings, 0 replies; 64+ messages in thread
From: Marc Sune @ 2015-10-07 13:37 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: dev

2015-10-06 15:48 GMT+02:00 Nélio Laranjeiro <nelio.laranjeiro@6wind.com>:

> Hi Marc,
>
> On Sun, Oct 04, 2015 at 11:12:46PM +0200, Marc Sune wrote:
> >[...]
> >  /**
> > + * 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 -> full duplex, 0 -> half duplex
> */
> > +     uint8_t link_autoneg : 1;  /**< 1 -> link speed has been autoneg */
> > +     uint8_t link_status  : 1;  /**< 1 -> link up, 0 -> link down */
> > +} __attribute__((aligned(8)));      /**< aligned for atomic64
> read/write */
> >[...]
>
> Pretty good.  One question, why did you not merge link_duplex, autoneg,
> and status like:
>
>         struct rte_eth_link {
>                 uint32_t link_speed;
>                 uint32_t link_duplex:1;
>                 uint32_t link_autoneg:1;
>                 uint32_t link_status:1;
>         };
>
> is it really useful to keep a uint16_t for the duplex alone?
>

You are right, I've missed this one. Will be fixed in v6.


>
> Another point, the comment about link_duplex field should point to the
> defines you have changed i.e. ETH_LINK_HALF_DUPLEX, ETH_LINK_FULL_DUPLEX.
>

Right. Will do that as part of v6 + comments of Neil.

Marc


> Regards,
>
> --
> Nélio Laranjeiro
> 6WIND
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API Marc Sune
  2015-10-05 10:59           ` Neil Horman
  2015-10-06 13:48           ` Nélio Laranjeiro
@ 2016-01-28 17:33           ` Harish Patil
  2016-02-02  2:20             ` Stephen Hemminger
  2 siblings, 1 reply; 64+ messages in thread
From: Harish Patil @ 2016-01-28 17:33 UTC (permalink / raw)
  To: Marc Sune, dev



From: Marc Sune <marcdevel@gmail.com<mailto:marcdevel@gmail.com>>
Date: Sunday, October 4, 2015 at 2:12 PM
To: "dev@dpdk.org<mailto:dev@dpdk.org>" <dev@dpdk.org<mailto:dev@dpdk.org>>
Subject: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API

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
  (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.
* Adapted testpmd to the new link API.

Signed-off-by: Marc Sune <marcdevel@gmail.com<mailto:marcdevel@gmail.com>>
---
 app/test-pmd/cmdline.c                     | 124 +++++++++++++++--------------
 app/test/virtual_pmd.c                     |   4 +-
 drivers/net/af_packet/rte_eth_af_packet.c  |   5 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c  |  14 ++--
 drivers/net/cxgbe/base/t4_hw.c             |   8 +-
 drivers/net/e1000/base/e1000_80003es2lan.c |   6 +-
 drivers/net/e1000/base/e1000_82541.c       |   8 +-
 drivers/net/e1000/base/e1000_82543.c       |   4 +-
 drivers/net/e1000/base/e1000_82575.c       |  11 +--
 drivers/net/e1000/base/e1000_api.c         |   2 +-
 drivers/net/e1000/base/e1000_api.h         |   2 +-
 drivers/net/e1000/base/e1000_defines.h     |   4 +-
 drivers/net/e1000/base/e1000_hw.h          |   2 +-
 drivers/net/e1000/base/e1000_ich8lan.c     |   4 +-
 drivers/net/e1000/base/e1000_mac.c         |   9 ++-
 drivers/net/e1000/base/e1000_mac.h         |   6 +-
 drivers/net/e1000/base/e1000_vf.c          |   4 +-
 drivers/net/e1000/base/e1000_vf.h          |   2 +-
 drivers/net/e1000/em_ethdev.c              | 108 ++++++++++++-------------
 drivers/net/e1000/igb_ethdev.c             | 103 ++++++++++++------------
 drivers/net/fm10k/fm10k_ethdev.c           |   8 +-
 drivers/net/i40e/i40e_ethdev.c             |  70 ++++++++--------
 drivers/net/i40e/i40e_ethdev_vf.c          |  11 +--
 drivers/net/ixgbe/ixgbe_ethdev.c           |  72 ++++++++---------
 drivers/net/mlx4/mlx4.c                    |   2 +
 drivers/net/mpipe/mpipe_tilegx.c           |   6 +-
 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/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 ++++++++++++++++----------
 34 files changed, 437 insertions(+), 356 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0f8f48f..c62f5be 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -897,14 +897,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()) {
@@ -912,40 +963,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 =
@@ -1000,8 +1029,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");
@@ -1011,36 +1039,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/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 bdd9628..a5d689d 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -115,9 +115,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/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index c0f0b99..f375f95 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/e1000/base/e1000_80003es2lan.c b/drivers/net/e1000/base/e1000_80003es2lan.c
index 72692d9..8ca66c4 100644
--- a/drivers/net/e1000/base/e1000_80003es2lan.c
+++ b/drivers/net/e1000/base/e1000_80003es2lan.c
@@ -52,7 +52,7 @@ STATIC s32  e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
 STATIC s32  e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
 STATIC s32  e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
 STATIC s32  e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+STATIC s32  e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u32 *speed,
                            u16 *duplex);
 STATIC s32  e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
 STATIC s32  e1000_init_hw_80003es2lan(struct e1000_hw *hw);
@@ -789,7 +789,7 @@ STATIC s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
  *
  *  Retrieve the current speed and duplex configuration.
  **/
-STATIC s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u32 *speed,
                           u16 *duplex)
 {
     s32 ret_val;
@@ -1236,7 +1236,7 @@ STATIC s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
 STATIC s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
 {
     s32 ret_val = E1000_SUCCESS;
-    u16 speed;
+    u32 speed;
     u16 duplex;

     DEBUGFUNC("e1000_configure_on_link_up");
diff --git a/drivers/net/e1000/base/e1000_82541.c b/drivers/net/e1000/base/e1000_82541.c
index 952aea2..707b317 100644
--- a/drivers/net/e1000/base/e1000_82541.c
+++ b/drivers/net/e1000/base/e1000_82541.c
@@ -47,7 +47,7 @@ STATIC s32  e1000_init_nvm_params_82541(struct e1000_hw *hw);
 STATIC s32  e1000_init_mac_params_82541(struct e1000_hw *hw);
 STATIC s32  e1000_reset_hw_82541(struct e1000_hw *hw);
 STATIC s32  e1000_init_hw_82541(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+STATIC s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u32 *speed,
                      u16 *duplex);
 STATIC s32  e1000_phy_hw_reset_82541(struct e1000_hw *hw);
 STATIC s32  e1000_setup_copper_link_82541(struct e1000_hw *hw);
@@ -437,7 +437,7 @@ out:
  *
  * Retrieve the current speed and duplex configuration.
  **/
-STATIC s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u32 *speed,
                     u16 *duplex)
 {
     struct e1000_phy_info *phy = &hw->phy;
@@ -667,8 +667,8 @@ STATIC s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
     struct e1000_phy_info *phy = &hw->phy;
     struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
     s32 ret_val;
-    u32 idle_errs = 0;
-    u16 phy_data, phy_saved_data, speed, duplex, i;
+    u32 idle_errs = 0, speed;
+    u16 phy_data, phy_saved_data, duplex, i;
     u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
     u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
                         IGP01E1000_PHY_AGC_PARAM_A,
diff --git a/drivers/net/e1000/base/e1000_82543.c b/drivers/net/e1000/base/e1000_82543.c
index 36335ba..9ef3d80 100644
--- a/drivers/net/e1000/base/e1000_82543.c
+++ b/drivers/net/e1000/base/e1000_82543.c
@@ -1192,9 +1192,9 @@ out:
 STATIC s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
 {
     struct e1000_mac_info *mac = &hw->mac;
-    u32 icr, rctl;
+    u32 icr, rctl, speed;
     s32 ret_val;
-    u16 speed, duplex;
+    u16 duplex;
     bool link;

     DEBUGFUNC("e1000_check_for_copper_link_82543");
diff --git a/drivers/net/e1000/base/e1000_82575.c b/drivers/net/e1000/base/e1000_82575.c
index 25fa672..386f058 100644
--- a/drivers/net/e1000/base/e1000_82575.c
+++ b/drivers/net/e1000/base/e1000_82575.c
@@ -53,7 +53,7 @@ STATIC void e1000_release_nvm_82575(struct e1000_hw *hw);
 STATIC s32  e1000_check_for_link_82575(struct e1000_hw *hw);
 STATIC s32  e1000_check_for_link_media_swap(struct e1000_hw *hw);
 STATIC s32  e1000_get_cfg_done_82575(struct e1000_hw *hw);
-STATIC s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
+STATIC s32  e1000_get_link_up_info_82575(struct e1000_hw *hw, u32 *speed,
                      u16 *duplex);
 STATIC s32  e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
 STATIC s32  e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
@@ -80,7 +80,7 @@ STATIC s32  e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
 STATIC void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
 STATIC s32  e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
 STATIC s32  e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
-                         u16 *speed, u16 *duplex);
+                         u32 *speed, u16 *duplex);
 STATIC s32  e1000_get_phy_id_82575(struct e1000_hw *hw);
 STATIC void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
 STATIC bool e1000_sgmii_active_82575(struct e1000_hw *hw);
@@ -1165,7 +1165,7 @@ STATIC s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
  *  interface, use PCS to retrieve the link speed and duplex information.
  *  Otherwise, use the generic function to get the link speed and duplex info.
  **/
-STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u32 *speed,
                     u16 *duplex)
 {
     s32 ret_val;
@@ -1192,7 +1192,8 @@ STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
 STATIC s32 e1000_check_for_link_82575(struct e1000_hw *hw)
 {
     s32 ret_val;
-    u16 speed, duplex;
+    u32 speed;
+    u16 duplex;

     DEBUGFUNC("e1000_check_for_link_82575");

@@ -1316,7 +1317,7 @@ STATIC void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
  *  duplex, then store the values in the pointers provided.
  **/
 STATIC s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
-                        u16 *speed, u16 *duplex)
+                        u32 *speed, u16 *duplex)
 {
     struct e1000_mac_info *mac = &hw->mac;
     u32 pcs;
diff --git a/drivers/net/e1000/base/e1000_api.c b/drivers/net/e1000/base/e1000_api.c
index a064565..08e103a 100644
--- a/drivers/net/e1000/base/e1000_api.c
+++ b/drivers/net/e1000/base/e1000_api.c
@@ -669,7 +669,7 @@ s32 e1000_setup_link(struct e1000_hw *hw)
  *  variables passed in. This is a function pointer entry point called
  *  by drivers.
  **/
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u32 *speed, u16 *duplex)
 {
     if (hw->mac.ops.get_link_up_info)
         return hw->mac.ops.get_link_up_info(hw, speed, duplex);
diff --git a/drivers/net/e1000/base/e1000_api.h b/drivers/net/e1000/base/e1000_api.h
index 02b16da..39579e0 100644
--- a/drivers/net/e1000/base/e1000_api.h
+++ b/drivers/net/e1000/base/e1000_api.h
@@ -65,7 +65,7 @@ s32 e1000_check_for_link(struct e1000_hw *hw);
 s32 e1000_reset_hw(struct e1000_hw *hw);
 s32 e1000_init_hw(struct e1000_hw *hw);
 s32 e1000_setup_link(struct e1000_hw *hw);
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u32 *speed, u16 *duplex);
 s32 e1000_disable_pcie_master(struct e1000_hw *hw);
 void e1000_config_collision_dist(struct e1000_hw *hw);
 void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
diff --git a/drivers/net/e1000/base/e1000_defines.h b/drivers/net/e1000/base/e1000_defines.h
index 278c507..20c4153 100644
--- a/drivers/net/e1000/base/e1000_defines.h
+++ b/drivers/net/e1000/base/e1000_defines.h
@@ -347,8 +347,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define SPEED_100    100
 #define SPEED_1000    1000
 #define SPEED_2500    2500
-#define HALF_DUPLEX    1
-#define FULL_DUPLEX    2
+#define HALF_DUPLEX    0
+#define FULL_DUPLEX    1

 #define PHY_FORCE_TIME    20

diff --git a/drivers/net/e1000/base/e1000_hw.h b/drivers/net/e1000/base/e1000_hw.h
index 4dd92a3..b48a759 100644
--- a/drivers/net/e1000/base/e1000_hw.h
+++ b/drivers/net/e1000/base/e1000_hw.h
@@ -682,7 +682,7 @@ struct e1000_mac_operations {
     void (*clear_vfta)(struct e1000_hw *);
     s32  (*get_bus_info)(struct e1000_hw *);
     void (*set_lan_id)(struct e1000_hw *);
-    s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+    s32  (*get_link_up_info)(struct e1000_hw *, u32 *, u16 *);
     s32  (*led_on)(struct e1000_hw *);
     s32  (*led_off)(struct e1000_hw *);
     void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
diff --git a/drivers/net/e1000/base/e1000_ich8lan.c b/drivers/net/e1000/base/e1000_ich8lan.c
index 3b1627b..7fe9955 100644
--- a/drivers/net/e1000/base/e1000_ich8lan.c
+++ b/drivers/net/e1000/base/e1000_ich8lan.c
@@ -104,7 +104,7 @@ STATIC s32  e1000_setup_link_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw);
 STATIC s32  e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
-                       u16 *speed, u16 *duplex);
+                       u32 *speed, u16 *duplex);
 STATIC s32  e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_led_on_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_led_off_ich8lan(struct e1000_hw *hw);
@@ -4561,7 +4561,7 @@ STATIC s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw)
  *  information and then calls the Kumeran lock loss workaround for links at
  *  gigabit speeds.
  **/
-STATIC s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u32 *speed,
                       u16 *duplex)
 {
     s32 ret_val;
diff --git a/drivers/net/e1000/base/e1000_mac.c b/drivers/net/e1000/base/e1000_mac.c
index c8ec049..6703a17 100644
--- a/drivers/net/e1000/base/e1000_mac.c
+++ b/drivers/net/e1000/base/e1000_mac.c
@@ -106,7 +106,7 @@ void e1000_null_mac_generic(struct e1000_hw E1000_UNUSEDARG *hw)
  *  @hw: pointer to the HW structure
  **/
 s32 e1000_null_link_info(struct e1000_hw E1000_UNUSEDARG *hw,
-             u16 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d)
+             u32 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d)
 {
     DEBUGFUNC("e1000_null_link_info");
     UNREFERENCED_3PARAMETER(hw, s, d);
@@ -1346,7 +1346,8 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
     s32 ret_val = E1000_SUCCESS;
     u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
     u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
-    u16 speed, duplex;
+    u32 speed;
+    u16 duplex;

     DEBUGFUNC("e1000_config_fc_after_link_up_generic");

@@ -1648,7 +1649,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
  *  Read the status register for the current speed/duplex and store the current
  *  speed and duplex for copper connections.
  **/
-s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
+s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u32 *speed,
                           u16 *duplex)
 {
     u32 status;
@@ -1688,7 +1689,7 @@ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
  *  for fiber/serdes links.
  **/
 s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSEDARG *hw,
-                            u16 *speed, u16 *duplex)
+                            u32 *speed, u16 *duplex)
 {
     DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
     UNREFERENCED_1PARAMETER(hw);
diff --git a/drivers/net/e1000/base/e1000_mac.h b/drivers/net/e1000/base/e1000_mac.h
index 5a7ce4a..987df76 100644
--- a/drivers/net/e1000/base/e1000_mac.h
+++ b/drivers/net/e1000/base/e1000_mac.h
@@ -40,7 +40,7 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw);
 #endif /* E1000_REMOVED */
 void e1000_null_mac_generic(struct e1000_hw *hw);
 s32  e1000_null_ops_generic(struct e1000_hw *hw);
-s32  e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
+s32  e1000_null_link_info(struct e1000_hw *hw, u32 *s, u16 *d);
 bool e1000_null_mng_mode(struct e1000_hw *hw);
 void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a);
 void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
@@ -61,10 +61,10 @@ s32  e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
 void e1000_set_lan_id_single_port(struct e1000_hw *hw);
 void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
 s32  e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
-s32  e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
+s32  e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u32 *speed,
                            u16 *duplex);
 s32  e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
-                             u16 *speed, u16 *duplex);
+                             u32 *speed, u16 *duplex);
 s32  e1000_id_led_init_generic(struct e1000_hw *hw);
 s32  e1000_led_on_generic(struct e1000_hw *hw);
 s32  e1000_led_off_generic(struct e1000_hw *hw);
diff --git a/drivers/net/e1000/base/e1000_vf.c b/drivers/net/e1000/base/e1000_vf.c
index 778561e..2221f1c 100644
--- a/drivers/net/e1000/base/e1000_vf.c
+++ b/drivers/net/e1000/base/e1000_vf.c
@@ -43,7 +43,7 @@ STATIC s32 e1000_setup_link_vf(struct e1000_hw *hw);
 STATIC s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw);
 STATIC s32 e1000_init_mac_params_vf(struct e1000_hw *hw);
 STATIC s32 e1000_check_for_link_vf(struct e1000_hw *hw);
-STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u32 *speed,
                      u16 *duplex);
 STATIC s32 e1000_init_hw_vf(struct e1000_hw *hw);
 STATIC s32 e1000_reset_hw_vf(struct e1000_hw *hw);
@@ -220,7 +220,7 @@ STATIC s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw)
  *  Since we cannot read the PHY and get accurate link info, we must rely upon
  *  the status register's data which is often stale and inaccurate.
  **/
-STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u32 *speed,
                      u16 *duplex)
 {
     s32 status;
diff --git a/drivers/net/e1000/base/e1000_vf.h b/drivers/net/e1000/base/e1000_vf.h
index 6d5bd99..9d801ad 100644
--- a/drivers/net/e1000/base/e1000_vf.h
+++ b/drivers/net/e1000/base/e1000_vf.h
@@ -201,7 +201,7 @@ struct e1000_mac_operations {
     s32  (*check_for_link)(struct e1000_hw *);
     void (*clear_vfta)(struct e1000_hw *);
     s32  (*get_bus_info)(struct e1000_hw *);
-    s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+    s32  (*get_link_up_info)(struct e1000_hw *, u32 *, u16 *);
     void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
     s32  (*reset_hw)(struct e1000_hw *);
     s32  (*init_hw)(struct e1000_hw *);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 72f792c..19d774f 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -493,6 +493,9 @@ eth_em_start(struct rte_eth_dev *dev)
     struct e1000_hw *hw =
         E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     int ret, mask;
+    uint32_t *speeds;
+    int num_speeds;
+    bool autoneg;

     PMD_INIT_FUNC_TRACE();

@@ -547,56 +550,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);

     /* check if lsc interrupt feature is enabled */
@@ -616,9 +609,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);
 }
@@ -934,11 +926,11 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
     dev_info->max_rx_queues = 1;
     dev_info->max_tx_queues = 1;

-    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 */
@@ -989,11 +981,11 @@ eth_em_link_update(struct rte_eth_dev *dev, int wait_to_complete)
     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;
+        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 927f5d9..7d407f4 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -889,6 +889,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();

@@ -984,48 +987,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);

     /* check if lsc interrupt feature is enabled */
@@ -1055,9 +1056,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);
 }
@@ -1571,11 +1571,11 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
         .txq_flags = 0,
     };

-    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
@@ -1683,11 +1683,14 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete)
     if (link_check) {
         hw->mac.ops.get_link_up_info(hw, &link.link_speed,
                       &link.link_duplex);
-        link.link_status = 1;
+        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 ca6357c..6e05355 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -862,7 +862,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;
 }
@@ -964,9 +964,9 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
                 ETH_TXQ_FLAGS_NOOFFLOADS,
     };

-    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 8a5dfbf..c3b3b9e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -835,27 +835,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;
 }
@@ -924,9 +917,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;
@@ -944,10 +937,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;
     }
@@ -995,6 +986,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");
@@ -1209,7 +1207,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;
@@ -1231,22 +1229,22 @@ 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;
     }

@@ -1687,10 +1685,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;

 }

@@ -6195,15 +6193,15 @@ i40e_timesync_enable(struct rte_eth_dev *dev)
     uint32_t tsync_inc_h;

     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 b694400..8d3acae 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1635,13 +1635,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 053c77e..a1103f0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1676,14 +1676,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;
     }
@@ -1769,32 +1768,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;
@@ -2400,15 +2389,16 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
     dev_info->reta_size = ETH_RSS_RETA_SIZE_128;
     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
@@ -2471,9 +2461,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);

@@ -2486,8 +2476,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;
@@ -2500,26 +2490,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);
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 88f95e5..41c0ad1 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -4207,6 +4207,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/mpipe/mpipe_tilegx.c b/drivers/net/mpipe/mpipe_tilegx.c
index 743feef..5875371 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/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index e244595..7704fa6 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -79,9 +79,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 f2e4634..ea7a28f 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 0ba36d5..626c381 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/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index a70be5c..6860360 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -697,9 +697,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 73e8bce..fb492ee 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 dummy 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 inline struct rte_mbuf *
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index c9b78f9..92e6a18 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -83,8 +83,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 f593f6e..29b2960 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1072,6 +1072,55 @@ rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 }

 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 951a423..bd333e4 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -238,26 +238,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 ->  full duplex, 0 ->  half duplex */
+    uint8_t link_autoneg : 1;  /**<  1 ->  link speed has been autoneg */
+    uint8_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
@@ -747,10 +780,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
@@ -812,26 +849,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 {
@@ -1667,6 +1684,22 @@ struct eth_driver {
 extern 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
--
2.1.4


Acked-by: Harish Patil <harish.patil@qlogic.com<mailto:harish.patil@qlogic.com>>

Hi Marc,
When can we expect it to be merged to the latest DPDK?

Thanks,
Harish




________________________________

This message and any attached documents contain information from the sending company or its parent company(s), subsidiaries, divisions or branch offices that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2016-01-28 17:33           ` Harish Patil
@ 2016-02-02  2:20             ` Stephen Hemminger
  2016-02-02 22:30               ` Marc
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Hemminger @ 2016-02-02  2:20 UTC (permalink / raw)
  To: Harish Patil; +Cc: dev

On Thu, 28 Jan 2016 17:33:20 +0000
Harish Patil <harish.patil@qlogic.com> wrote:

> * Added utility MACROs ETH_SPEED_NUM_XXX with the numeric
>   values of all supported link speeds, in Mbps.

I would prefer that there were no speed value macros.
Linux used to have these, but people kept adding new hardware speeds
and it soon gets out of date.

If you are going to redo it, then just increase speed to 64 bit, and allow
any non-zero value.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2016-02-02  2:20             ` Stephen Hemminger
@ 2016-02-02 22:30               ` Marc
  2016-02-11 15:27                 ` Nélio Laranjeiro
  0 siblings, 1 reply; 64+ messages in thread
From: Marc @ 2016-02-02 22:30 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On 2 February 2016 at 03:20, Stephen Hemminger <stephen@networkplumber.org>
wrote:

> On Thu, 28 Jan 2016 17:33:20 +0000
> Harish Patil <harish.patil@qlogic.com> wrote:
>
> > * Added utility MACROs ETH_SPEED_NUM_XXX with the numeric
> >   values of all supported link speeds, in Mbps.
>
> I would prefer that there were no speed value macros.
> Linux used to have these, but people kept adding new hardware speeds
> and it soon gets out of date.
>

I see what you mean, but I am not sure I agree. Link speeds are generally a
reduced amount of items (~20). Though it is true it can eventually grow,
but at small rate. Having numeric constants all over the source seems less
readable and less maintainable (e.g. less "grepable"/"sedable") to me.


>
> If you are going to redo it, then just increase speed to 64 bit, and allow
> any non-zero value.
>

Value is now 32 bits, which I think is enough for future rates in mbps.
Since these constants were there, and before doing something to have to
revert it, can someone else give his/her opinion on this?

If there is consensus, I've no problem on removing it for v8

Thanks
marc

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2016-02-02 22:30               ` Marc
@ 2016-02-11 15:27                 ` Nélio Laranjeiro
  2016-02-11 23:23                   ` Marc
  0 siblings, 1 reply; 64+ messages in thread
From: Nélio Laranjeiro @ 2016-02-11 15:27 UTC (permalink / raw)
  To: Marc; +Cc: dev

On Tue, Feb 02, 2016 at 11:30:59PM +0100, Marc wrote:
> On 2 February 2016 at 03:20, Stephen Hemminger <stephen@networkplumber.org>
> wrote:
> 
> > On Thu, 28 Jan 2016 17:33:20 +0000
> > Harish Patil <harish.patil@qlogic.com> wrote:
> >
> > > * Added utility MACROs ETH_SPEED_NUM_XXX with the numeric
> > >   values of all supported link speeds, in Mbps.
> >
> > I would prefer that there were no speed value macros.
> > Linux used to have these, but people kept adding new hardware speeds
> > and it soon gets out of date.
> >
> 
> I see what you mean, but I am not sure I agree. Link speeds are generally a
> reduced amount of items (~20). Though it is true it can eventually grow,
> but at small rate. Having numeric constants all over the source seems less
> readable and less maintainable (e.g. less "grepable"/"sedable") to me.
> 
> 
> >
> > If you are going to redo it, then just increase speed to 64 bit, and allow
> > any non-zero value.
> >
> 
> Value is now 32 bits, which I think is enough for future rates in mbps.
> Since these constants were there, and before doing something to have to
> revert it, can someone else give his/her opinion on this?

For non 64bit architecture it is better to keep it on 32 bit but, if this
field is only used on control plane we can afford 64 bit field and avoid
another ABI breakage (in a far future).

Even if this 32 bit field seems large enough you can already find on
Internet some reports of transmission of petabit/s [1], we can imagine a
NIC which provide this possibility by aggregating a lot of optical links
and DPDK only will see it as single one.

> If there is consensus, I've no problem on removing it for v8
> 
> Thanks
> marc

[1] http://optics.org/news/4/1/29

-- 
Nélio Laranjeiro
6WIND

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API
  2016-02-11 15:27                 ` Nélio Laranjeiro
@ 2016-02-11 23:23                   ` Marc
  0 siblings, 0 replies; 64+ messages in thread
From: Marc @ 2016-02-11 23:23 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: dev

On 11 February 2016 at 16:27, Nélio Laranjeiro <nelio.laranjeiro@6wind.com>
wrote:

> On Tue, Feb 02, 2016 at 11:30:59PM +0100, Marc wrote:
> > On 2 February 2016 at 03:20, Stephen Hemminger <
> stephen@networkplumber.org>
> > wrote:
> >
> > > On Thu, 28 Jan 2016 17:33:20 +0000
> > > Harish Patil <harish.patil@qlogic.com> wrote:
> > >
> > > > * Added utility MACROs ETH_SPEED_NUM_XXX with the numeric
> > > >   values of all supported link speeds, in Mbps.
> > >
> > > I would prefer that there were no speed value macros.
> > > Linux used to have these, but people kept adding new hardware speeds
> > > and it soon gets out of date.
> > >
> >
> > I see what you mean, but I am not sure I agree. Link speeds are
> generally a
> > reduced amount of items (~20). Though it is true it can eventually grow,
> > but at small rate. Having numeric constants all over the source seems
> less
> > readable and less maintainable (e.g. less "grepable"/"sedable") to me.
> >
> >
> > >
> > > If you are going to redo it, then just increase speed to 64 bit, and
> allow
> > > any non-zero value.
> > >
> >
> > Value is now 32 bits, which I think is enough for future rates in mbps.
> > Since these constants were there, and before doing something to have to
> > revert it, can someone else give his/her opinion on this?
>
> For non 64bit architecture it is better to keep it on 32 bit but, if this
> field is only used on control plane we can afford 64 bit field and avoid
> another ABI breakage (in a far future).
>
> Even if this 32 bit field seems large enough you can already find on
> Internet some reports of transmission of petabit/s [1], we can imagine a
> NIC which provide this possibility by aggregating a lot of optical links
> and DPDK only will see it as single one.
>

OK, since it is not performance critical I will change it to 64 bit value.


>
> > If there is consensus, I've no problem on removing it for v8
>

Still the question about numeric speed MACROs is open.

best
marc




> >
> > Thanks
> > marc
>
> [1] http://optics.org/news/4/1/29
>
> --
> Nélio Laranjeiro
> 6WIND
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-06-18 15:06 ` Marc Sune
@ 2015-06-18 15:33   ` Thomas Monjalon
  0 siblings, 0 replies; 64+ messages in thread
From: Thomas Monjalon @ 2015-06-18 15:33 UTC (permalink / raw)
  To: Marc Sune; +Cc: dev, Morten Brørup

2015-06-18 17:06, Marc Sune:
> On 18/06/15 16:43, Morten Brørup wrote:
> > Regarding the PHY speed ABI:
> >
> > 1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)
> 
> Thomas was sending a similar comment and I agreed to do a unified speed 
> bitmap for both capabilities and link negotiation/link info (v3, waiting 
> for 2.2 merge window):
> 
> http://dpdk.org/ml/archives/dev/2015-June/019207.html

It would be better to try merging it in 2.1 while keeping an ABI backward
compatibility.

> > 2. The auto-negotiation standard allows the PHY to announce (to its link
> > partner) any subset of its capabilities to its link partner. E.g. a
> > standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s
> > in both half and full duplex and 1 Gbit/s full duplex) can be configured
> > to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities
> > to its link partner. (Of course, more useful combinations are normally
> > announced, but the purpose of the example is to show that any combination
> > is possible.)
> >
> > The ABI for auto-negotiation should include options to select the list of
> > capabilities to announce to the link partner. The Linux PHY ABI only
> > allows forcing a selected speed and duplex (thereby disabling
> > auto-negotiation) or enabling auto-negotiation (thereby announcing all
> > possible speeds and duplex combinations the PHY is capable of). Don't make
> > the same mistake in DPDK.
> 
> I see what you mean, and you are probably right. In any case this is for 
> a separate patch, if we think it is a necessary feature to implement.
> 
> Nevertheless, this makes me rethink about the proposal from Thomas about 
> unifying _100_HD/_100_FD to 100M, because you will need this 
> granularity, eventually. @Thomas: opinions?

I think Morten's advice is good.
Are we going to have half duplex links for PHY faster than 100M?
If not, we can manage them with a hackish define 100M_HD and a 100M
which implicitly means full duplex.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
  2015-06-18 14:43 [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Morten Brørup
@ 2015-06-18 15:06 ` Marc Sune
  2015-06-18 15:33   ` Thomas Monjalon
  0 siblings, 1 reply; 64+ messages in thread
From: Marc Sune @ 2015-06-18 15:06 UTC (permalink / raw)
  To: dev, Thomas Monjalon



On 18/06/15 16:43, Morten Brørup wrote:
> Regarding the PHY speed ABI:
>
>   
>
> 1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)

Thomas was sending a similar comment and I agreed to do a unified speed 
bitmap for both capabilities and link negotiation/link info (v3, waiting 
for 2.2 merge window):

http://dpdk.org/ml/archives/dev/2015-June/019207.html

>
>   
>
> 2. The auto-negotiation standard allows the PHY to announce (to its link partner) any subset of its capabilities to its link partner. E.g. a standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s in both half and full duplex and 1 Gbit/s full duplex) can be configured to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities to its link partner. (Of course, more useful combinations are normally announced, but the purpose of the example is to show that any combination is possible.)
>
>   
>
> The ABI for auto-negotiation should include options to select the list of capabilities to announce to the link partner. The Linux PHY ABI only allows forcing a selected speed and duplex (thereby disabling auto-negotiation) or enabling auto-negotiation (thereby announcing all possible speeds and duplex combinations the PHY is capable of). Don't make the same mistake in DPDK.

I see what you mean, and you are probably right. In any case this is for 
a separate patch, if we think it is a necessary feature to implement.

Nevertheless, this makes me rethink about the proposal from Thomas about 
unifying _100_HD/_100_FD to 100M, because you will need this 
granularity, eventually. @Thomas: opinions?

Thanks
Marc

p.s. Please configure your email client to reply using "In-Reply-To:" to 
allow clients and ML archives to use threading.

>   
>
> PS: While working for Vitesse Semiconductors (an Ethernet chip company) a long time ago, I actually wrote the API for their line of Ethernet PHYs. So I have hands on experience in this area.
>
>   
>
>   
>
> Med venlig hilsen / kind regards
>
>   
>
> Morten Brørup
>
> CTO
>
>   
>
>   
>
>   
>
> SmartShare Systems A/S
>
> Tonsbakken 16-18
>
> DK-2740 Skovlunde
>
> Denmark
>
>   
>
> Office      +45 70 20 00 93
>
> Direct      +45 89 93 50 22
>
> Mobile      +45 25 40 82 12
>
>   
>
> mb@smartsharesystems.com <mailto:mb@smartsharesystems.com>
>
> www.smartsharesystems.com <http://www.smartsharesystems.com/>
>
>   
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
@ 2015-06-18 14:43 Morten Brørup
  2015-06-18 15:06 ` Marc Sune
  0 siblings, 1 reply; 64+ messages in thread
From: Morten Brørup @ 2015-06-18 14:43 UTC (permalink / raw)
  To: dev

Regarding the PHY speed ABI:

 

1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)

 

2. The auto-negotiation standard allows the PHY to announce (to its link partner) any subset of its capabilities to its link partner. E.g. a standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s in both half and full duplex and 1 Gbit/s full duplex) can be configured to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities to its link partner. (Of course, more useful combinations are normally announced, but the purpose of the example is to show that any combination is possible.)

 

The ABI for auto-negotiation should include options to select the list of capabilities to announce to the link partner. The Linux PHY ABI only allows forcing a selected speed and duplex (thereby disabling auto-negotiation) or enabling auto-negotiation (thereby announcing all possible speeds and duplex combinations the PHY is capable of). Don't make the same mistake in DPDK.

 

PS: While working for Vitesse Semiconductors (an Ethernet chip company) a long time ago, I actually wrote the API for their line of Ethernet PHYs. So I have hands on experience in this area.

 

 

Med venlig hilsen / kind regards

 

Morten Brørup

CTO

 

 

 

SmartShare Systems A/S

Tonsbakken 16-18

DK-2740 Skovlunde

Denmark

 

Office      +45 70 20 00 93

Direct      +45 89 93 50 22

Mobile      +45 25 40 82 12

 

mb@smartsharesystems.com <mailto:mb@smartsharesystems.com> 

www.smartsharesystems.com <http://www.smartsharesystems.com/> 

 

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2016-02-11 23:24 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-11 23:45 [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
2015-05-25 17:46   ` Stephen Hemminger
2015-05-26  8:41     ` Marc Sune
2015-05-26 15:03   ` Stephen Hemminger
2015-05-26 15:09     ` Marc Sune
2015-05-11 23:45 ` [dpdk-dev] [RFC PATCH 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
2015-05-25 16:32 ` [dpdk-dev] [RFC PATCH 0/2] ethdev: add port speed capability bitmap Marc Sune
2015-05-26 19:50 ` [dpdk-dev] [PATCH v2 " Marc Sune
2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Marc Sune
2015-05-27  4:02     ` Thomas Monjalon
2015-05-27  9:15       ` Marc Sune
2015-05-29 18:23         ` Thomas Monjalon
2015-06-08  8:50           ` Marc Sune
2015-06-11  9:08             ` Thomas Monjalon
2015-06-11 14:35               ` Marc Sune
2015-05-26 19:50   ` [dpdk-dev] [PATCH v2 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
2015-05-26 21:20     ` Igor Ryzhov
2015-05-27  8:59       ` Marc Sune
2015-08-28 23:20   ` [dpdk-dev] [PATCH v3 0/2] ethdev: add port speed capability bitmap Marc Sune
2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
2015-08-28 23:20     ` [dpdk-dev] [PATCH v3 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
2015-08-29  0:16     ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 1/2] Added ETH_SPEED_ bitmap in rte_eth_dev_info Marc Sune
2015-08-29  0:16       ` [dpdk-dev] [PATCH v4 2/2] Filling speed capability bitmaps in the PMDs Marc Sune
2015-09-07 20:52       ` [dpdk-dev] [PATCH v4 0/2] ethdev: add port speed capability bitmap Marc Sune
2015-09-08 10:03         ` Nélio Laranjeiro
2015-09-08 20:26           ` Marc Sune
2015-09-09 13:10           ` Nélio Laranjeiro
2015-09-09 13:33             ` Thomas Monjalon
2015-09-13 19:14               ` Marc Sune
2015-09-13 21:18                 ` Thomas Monjalon
2015-09-14 10:02                   ` Nélio Laranjeiro
2015-09-14 10:52                   ` Morten Brørup
2015-09-14 21:33                     ` Marc Sune
2015-09-14 22:50                       ` Morten Brørup
2015-09-15  8:25                         ` Nélio Laranjeiro
2015-09-15  8:48                           ` Marc Sune
2015-09-15  9:39                             ` Morten Brørup
2015-09-15 10:04                             ` Adrien Mazarguil
2015-09-15 10:24                               ` Morten Brørup
2015-09-15 21:20                               ` Marc Sune
2015-09-16 14:41                                 ` Adrien Mazarguil
2015-09-15  7:05                       ` Thomas Monjalon
2015-09-15  7:33                         ` Morten Brørup
2015-09-15  9:06                       ` Morten Brørup
2015-10-04 21:12       ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 1/4] ethdev: Added ETH_SPEED_CAP bitmap for ports Marc Sune
2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 2/4] ethdev: Fill speed capability bitmaps in the PMDs Marc Sune
2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 3/4] ethdev: redesign link speed config API Marc Sune
2015-10-05 10:59           ` Neil Horman
2015-10-07 13:31             ` Marc Sune
2015-10-06 13:48           ` Nélio Laranjeiro
2015-10-07 13:37             ` Marc Sune
2016-01-28 17:33           ` Harish Patil
2016-02-02  2:20             ` Stephen Hemminger
2016-02-02 22:30               ` Marc
2016-02-11 15:27                 ` Nélio Laranjeiro
2016-02-11 23:23                   ` Marc
2015-10-04 21:12         ` [dpdk-dev] [PATCH v5 4/4] doc: update with link changes Marc Sune
2015-10-04 21:21         ` [dpdk-dev] [PATCH v5 0/4] ethdev: add speed capabilities and refactor link API Marc Sune
2015-06-18 14:43 [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Morten Brørup
2015-06-18 15:06 ` Marc Sune
2015-06-18 15:33   ` Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).