[v5,1/2] ethdev: Add link_speed lanes support

Message ID 20240904175151.47780-2-damodharam.ammepalli@broadcom.com (mailing list archive)
State Changes Requested
Delegated to: Ferruh Yigit
Headers
Series Add link_speed lanes support |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Damodharam Ammepalli Sept. 4, 2024, 5:50 p.m. UTC
Update the eth_dev_ops structure with new function vectors
to get, get capabilities and set ethernet link speed lanes.
Update the testpmd to provide required config and information
display infrastructure.

The supporting ethernet controller driver will register callbacks
to avail link speed lanes config and get services. This lanes
configuration is applicable only when the nic is forced to fixed
speeds. In Autonegiation mode, the hardware automatically
negotiates the number of lanes.

These are the new commands.

testpmd> show port 0 speed_lanes capabilities

 Supported speeds         Valid lanes
-----------------------------------
 10 Gbps                  1
 25 Gbps                  1
 40 Gbps                  4
 50 Gbps                  1 2
 100 Gbps                 1 2 4
 200 Gbps                 2 4
 400 Gbps                 4 8
testpmd>

testpmd>
testpmd> port stop 0
testpmd> port config 0 speed_lanes 4
testpmd> port config 0 speed 200000 duplex full
testpmd> port start 0
testpmd>
testpmd> show port info 0

********************* Infos for port 0  *********************
MAC address: 14:23:F2:C3:BA:D2
Device name: 0000:b1:00.0
Driver name: net_bnxt
Firmware-version: 228.9.115.0
Connect to socket: 2
memory allocation on the socket: 2
Link status: up
Link speed: 200 Gbps
Active Lanes: 4
Link duplex: full-duplex
Autoneg status: Off

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
---
 app/test-pmd/cmdline.c     | 248 ++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c      |   4 +
 lib/ethdev/ethdev_driver.h |  91 ++++++++++++++
 lib/ethdev/rte_ethdev.c    |  52 ++++++++
 lib/ethdev/rte_ethdev.h    |  95 ++++++++++++++
 lib/ethdev/version.map     |   5 +
 6 files changed, 494 insertions(+), 1 deletion(-)
  

Comments

Ferruh Yigit Sept. 22, 2024, 5:02 p.m. UTC | #1
On 9/4/2024 6:50 PM, Damodharam Ammepalli wrote:
> Update the eth_dev_ops structure with new function vectors
> to get, get capabilities and set ethernet link speed lanes.
> Update the testpmd to provide required config and information
> display infrastructure.
> 
> The supporting ethernet controller driver will register callbacks
> to avail link speed lanes config and get services. This lanes
> configuration is applicable only when the nic is forced to fixed
> speeds. In Autonegiation mode, the hardware automatically
> negotiates the number of lanes.
> 
> These are the new commands.
> 
> testpmd> show port 0 speed_lanes capabilities
> 
>  Supported speeds         Valid lanes
> -----------------------------------
>  10 Gbps                  1
>  25 Gbps                  1
>  40 Gbps                  4
>  50 Gbps                  1 2
>  100 Gbps                 1 2 4
>  200 Gbps                 2 4
>  400 Gbps                 4 8
> testpmd>
> 
> testpmd>
> testpmd> port stop 0
> testpmd> port config 0 speed_lanes 4
> testpmd> port config 0 speed 200000 duplex full
> testpmd> port start 0
> testpmd>
> testpmd> show port info 0
> 
> ********************* Infos for port 0  *********************
> MAC address: 14:23:F2:C3:BA:D2
> Device name: 0000:b1:00.0
> Driver name: net_bnxt
> Firmware-version: 228.9.115.0
> Connect to socket: 2
> memory allocation on the socket: 2
> Link status: up
> Link speed: 200 Gbps
> Active Lanes: 4
> Link duplex: full-duplex
> Autoneg status: Off
> 
> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> ---
>  app/test-pmd/cmdline.c     | 248 ++++++++++++++++++++++++++++++++++++-
>  app/test-pmd/config.c      |   4 +
>  lib/ethdev/ethdev_driver.h |  91 ++++++++++++++
>  lib/ethdev/rte_ethdev.c    |  52 ++++++++
>  lib/ethdev/rte_ethdev.h    |  95 ++++++++++++++
>  lib/ethdev/version.map     |   5 +
>  6 files changed, 494 insertions(+), 1 deletion(-)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index b7759e38a8..643102032e 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>  
>  			"dump_log_types\n"
>  			"    Dumps the log level for all the dpdk modules\n\n"
> +
> +			"show port (port_id) speed_lanes capabilities"
> +			"	Show speed lanes capabilities of a port.\n\n"
>  		);
>  	}
>  
> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>  			"port config (port_id) txq (queue_id) affinity (value)\n"
>  			"    Map a Tx queue with an aggregated port "
>  			"of the DPDK port\n\n"
> +
> +			"port config (port_id|all) speed_lanes (0|1|4|8)\n"
>

This help string, and the implementation, implies there has to be fixed
lane values, like 1, 4, 8. Why not leave this part to the capability
reporting, and not limit (and worry) those values in the command, so
from command's perspective it can be only <lane number>.

> +			"    Set number of lanes for all ports or port_id for a forced speed\n\n"
>  		);
>  	}
>  
> @@ -1560,6 +1566,244 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
>  	},
>  };
>  
> +static int
> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
> +{
> +	int ret;
> +
> +	ret = rte_eth_speed_lanes_set(pid, lanes);
>

As a sample application usage, I think it is better if it gets the
capability and verify that 'lanes' is withing the capability and later
set it, what do you think?

<...>

> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h> index
548fada1c7..9444e0a836 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -357,6 +357,27 @@ struct rte_eth_link {
>  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
>  /**@}*/
>  
> +/**
> + * Constants used to indicate the possible link speed lanes of an ethdev port.
> + */
> +#define RTE_ETH_SPEED_LANE_UNKNOWN  0  /**< speed lanes unsupported mode or default */
> +#define RTE_ETH_SPEED_LANE_1  1        /**< Link speed lane  1 */
> +#define RTE_ETH_SPEED_LANE_2  2        /**< Link speed lanes 2 */
> +#define RTE_ETH_SPEED_LANE_4  4        /**< Link speed lanes 4 */
> +#define RTE_ETH_SPEED_LANE_8  8        /**< Link speed lanes 8 */
> +
> +/* Translate from link speed lanes to speed lanes capa */
> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> +
> +/* This macro indicates link speed lanes capa mask */
> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> +
>

I am not clear why we need these macros, why not use lane number as
unsigned integer, instead of macro (RTE_ETH_SPEED_LANE_2), it will be
more flexible.

Probably all we need is 'RTE_ETH_SPEED_LANES_TO_CAPA' one to use as
helper in drivers.
Again not sure about the ..CAPA_MASK one, does it actually produce a
mask value?
  
Damodharam Ammepalli Sept. 24, 2024, 10:59 p.m. UTC | #2
On Sun, Sep 22, 2024 at 10:02 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 9/4/2024 6:50 PM, Damodharam Ammepalli wrote:
> > Update the eth_dev_ops structure with new function vectors
> > to get, get capabilities and set ethernet link speed lanes.
> > Update the testpmd to provide required config and information
> > display infrastructure.
> >
> > The supporting ethernet controller driver will register callbacks
> > to avail link speed lanes config and get services. This lanes
> > configuration is applicable only when the nic is forced to fixed
> > speeds. In Autonegiation mode, the hardware automatically
> > negotiates the number of lanes.
> >
> > These are the new commands.
> >
> > testpmd> show port 0 speed_lanes capabilities
> >
> >  Supported speeds         Valid lanes
> > -----------------------------------
> >  10 Gbps                  1
> >  25 Gbps                  1
> >  40 Gbps                  4
> >  50 Gbps                  1 2
> >  100 Gbps                 1 2 4
> >  200 Gbps                 2 4
> >  400 Gbps                 4 8
> > testpmd>
> >
> > testpmd>
> > testpmd> port stop 0
> > testpmd> port config 0 speed_lanes 4
> > testpmd> port config 0 speed 200000 duplex full
> > testpmd> port start 0
> > testpmd>
> > testpmd> show port info 0
> >
> > ********************* Infos for port 0  *********************
> > MAC address: 14:23:F2:C3:BA:D2
> > Device name: 0000:b1:00.0
> > Driver name: net_bnxt
> > Firmware-version: 228.9.115.0
> > Connect to socket: 2
> > memory allocation on the socket: 2
> > Link status: up
> > Link speed: 200 Gbps
> > Active Lanes: 4
> > Link duplex: full-duplex
> > Autoneg status: Off
> >
> > Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> > ---
> >  app/test-pmd/cmdline.c     | 248 ++++++++++++++++++++++++++++++++++++-
> >  app/test-pmd/config.c      |   4 +
> >  lib/ethdev/ethdev_driver.h |  91 ++++++++++++++
> >  lib/ethdev/rte_ethdev.c    |  52 ++++++++
> >  lib/ethdev/rte_ethdev.h    |  95 ++++++++++++++
> >  lib/ethdev/version.map     |   5 +
> >  6 files changed, 494 insertions(+), 1 deletion(-)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> > index b7759e38a8..643102032e 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> >
> >                       "dump_log_types\n"
> >                       "    Dumps the log level for all the dpdk modules\n\n"
> > +
> > +                     "show port (port_id) speed_lanes capabilities"
> > +                     "       Show speed lanes capabilities of a port.\n\n"
> >               );
> >       }
> >
> > @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> >                       "port config (port_id) txq (queue_id) affinity (value)\n"
> >                       "    Map a Tx queue with an aggregated port "
> >                       "of the DPDK port\n\n"
> > +
> > +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
> >
>
> This help string, and the implementation, implies there has to be fixed
> lane values, like 1, 4, 8. Why not leave this part to the capability
> reporting, and not limit (and worry) those values in the command, so
> from command's perspective it can be only <lane number>.
>

ok, will update the help string to <lane number>

> > +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
> >               );
> >       }
> >
> > @@ -1560,6 +1566,244 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
> >       },
> >  };
> >
> > +static int
> > +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
> > +{
> > +     int ret;
> > +
> > +     ret = rte_eth_speed_lanes_set(pid, lanes);
> >
>
> As a sample application usage, I think it is better if it gets the
> capability and verify that 'lanes' is withing the capability and later
> set it, what do you think?
>
> <...>

Makes sense, will try out and get back to you soon.


> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h> index
> 548fada1c7..9444e0a836 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -357,6 +357,27 @@ struct rte_eth_link {
> >  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
> >  /**@}*/
> >
> > +/**
> > + * Constants used to indicate the possible link speed lanes of an ethdev port.
> > + */
> > +#define RTE_ETH_SPEED_LANE_UNKNOWN  0  /**< speed lanes unsupported mode or default */
> > +#define RTE_ETH_SPEED_LANE_1  1        /**< Link speed lane  1 */
> > +#define RTE_ETH_SPEED_LANE_2  2        /**< Link speed lanes 2 */
> > +#define RTE_ETH_SPEED_LANE_4  4        /**< Link speed lanes 4 */
> > +#define RTE_ETH_SPEED_LANE_8  8        /**< Link speed lanes 8 */
> > +
> > +/* Translate from link speed lanes to speed lanes capa */
> > +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> > +
> > +/* This macro indicates link speed lanes capa mask */
> > +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> > +
> >
>
> I am not clear why we need these macros, why not use lane number as
> unsigned integer, instead of macro (RTE_ETH_SPEED_LANE_2), it will be
> more flexible.
>

ok, I can replace the macros with unsigned integers

> Probably all we need is 'RTE_ETH_SPEED_LANES_TO_CAPA' one to use as
> helper in drivers.
> Again not sure about the ..CAPA_MASK one, does it actually produce a
> mask value?
>
>
once replacing the LANE_xx to unsigned integers, then I don't need x_CAPA_MASK.
In the driver, I can call RTE_32(lane number) while populating the table.
EG:

        { RTE_ETH_SPEED_NUM_100G, RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_1) |
                                RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_2) |
                                RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_4) },
will become

        { RTE_ETH_SPEED_NUM_100G, RTE_BIT32(1) |
                                RTE_BIT32(2) |
                                RTE_BIT32(4) },
  
Damodharam Ammepalli Sept. 25, 2024, 3 p.m. UTC | #3
On Tue, Sep 24, 2024 at 3:59 PM Damodharam Ammepalli
<damodharam.ammepalli@broadcom.com> wrote:
>
> On Sun, Sep 22, 2024 at 10:02 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
> >
> > On 9/4/2024 6:50 PM, Damodharam Ammepalli wrote:
> > > Update the eth_dev_ops structure with new function vectors
> > > to get, get capabilities and set ethernet link speed lanes.
> > > Update the testpmd to provide required config and information
> > > display infrastructure.
> > >
> > > The supporting ethernet controller driver will register callbacks
> > > to avail link speed lanes config and get services. This lanes
> > > configuration is applicable only when the nic is forced to fixed
> > > speeds. In Autonegiation mode, the hardware automatically
> > > negotiates the number of lanes.
> > >
> > > These are the new commands.
> > >
> > > testpmd> show port 0 speed_lanes capabilities
> > >
> > >  Supported speeds         Valid lanes
> > > -----------------------------------
> > >  10 Gbps                  1
> > >  25 Gbps                  1
> > >  40 Gbps                  4
> > >  50 Gbps                  1 2
> > >  100 Gbps                 1 2 4
> > >  200 Gbps                 2 4
> > >  400 Gbps                 4 8
> > > testpmd>
> > >
> > > testpmd>
> > > testpmd> port stop 0
> > > testpmd> port config 0 speed_lanes 4
> > > testpmd> port config 0 speed 200000 duplex full
> > > testpmd> port start 0
> > > testpmd>
> > > testpmd> show port info 0
> > >
> > > ********************* Infos for port 0  *********************
> > > MAC address: 14:23:F2:C3:BA:D2
> > > Device name: 0000:b1:00.0
> > > Driver name: net_bnxt
> > > Firmware-version: 228.9.115.0
> > > Connect to socket: 2
> > > memory allocation on the socket: 2
> > > Link status: up
> > > Link speed: 200 Gbps
> > > Active Lanes: 4
> > > Link duplex: full-duplex
> > > Autoneg status: Off
> > >
> > > Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> > > ---
> > >  app/test-pmd/cmdline.c     | 248 ++++++++++++++++++++++++++++++++++++-
> > >  app/test-pmd/config.c      |   4 +
> > >  lib/ethdev/ethdev_driver.h |  91 ++++++++++++++
> > >  lib/ethdev/rte_ethdev.c    |  52 ++++++++
> > >  lib/ethdev/rte_ethdev.h    |  95 ++++++++++++++
> > >  lib/ethdev/version.map     |   5 +
> > >  6 files changed, 494 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> > > index b7759e38a8..643102032e 100644
> > > --- a/app/test-pmd/cmdline.c
> > > +++ b/app/test-pmd/cmdline.c
> > > @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> > >
> > >                       "dump_log_types\n"
> > >                       "    Dumps the log level for all the dpdk modules\n\n"
> > > +
> > > +                     "show port (port_id) speed_lanes capabilities"
> > > +                     "       Show speed lanes capabilities of a port.\n\n"
> > >               );
> > >       }
> > >
> > > @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> > >                       "port config (port_id) txq (queue_id) affinity (value)\n"
> > >                       "    Map a Tx queue with an aggregated port "
> > >                       "of the DPDK port\n\n"
> > > +
> > > +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
> > >
> >
> > This help string, and the implementation, implies there has to be fixed
> > lane values, like 1, 4, 8. Why not leave this part to the capability
> > reporting, and not limit (and worry) those values in the command, so
> > from command's perspective it can be only <lane number>.
> >
>
> ok, will update the help string to <lane number>
>
> > > +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
> > >               );
> > >       }
> > >
> > > @@ -1560,6 +1566,244 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
> > >       },
> > >  };
> > >
> > > +static int
> > > +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
> > > +{
> > > +     int ret;
> > > +
> > > +     ret = rte_eth_speed_lanes_set(pid, lanes);
> > >
> >
> > As a sample application usage, I think it is better if it gets the
> > capability and verify that 'lanes' is withing the capability and later
> > set it, what do you think?
> >
> > <...>
>
> Makes sense, will try out and get back to you soon.
>
I guess a similar comment was discussed in the past, slipped my mind
to mention in my last response.
These are the reasons for this logic.
-  same lane number can be supported by any speed (eg: 4 Lanes
supported in 100,200,400 etc)
so, which speed row should app check against, since the user has not
configured fixed speed yet.
If the link is already up in AN mode, this lane config doesn't have
any significance.
- one approach would be to validate lanes in
parse_and_check_speed_duplex(), but in this case, the app should
already have non-default lanes value. We also need to consider the
case, if the user wants default lanes.
- In the ethtool, the driver does the validation of the speed x lanes
combo. Tried to match similar behaviour.

Let me know your thoughts.

>
> > > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h> index
> > 548fada1c7..9444e0a836 100644
> > > --- a/lib/ethdev/rte_ethdev.h
> > > +++ b/lib/ethdev/rte_ethdev.h
> > > @@ -357,6 +357,27 @@ struct rte_eth_link {
> > >  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
> > >  /**@}*/
> > >
> > > +/**
> > > + * Constants used to indicate the possible link speed lanes of an ethdev port.
> > > + */
> > > +#define RTE_ETH_SPEED_LANE_UNKNOWN  0  /**< speed lanes unsupported mode or default */
> > > +#define RTE_ETH_SPEED_LANE_1  1        /**< Link speed lane  1 */
> > > +#define RTE_ETH_SPEED_LANE_2  2        /**< Link speed lanes 2 */
> > > +#define RTE_ETH_SPEED_LANE_4  4        /**< Link speed lanes 4 */
> > > +#define RTE_ETH_SPEED_LANE_8  8        /**< Link speed lanes 8 */
> > > +
> > > +/* Translate from link speed lanes to speed lanes capa */
> > > +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> > > +
> > > +/* This macro indicates link speed lanes capa mask */
> > > +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> > > +
> > >
> >
> > I am not clear why we need these macros, why not use lane number as
> > unsigned integer, instead of macro (RTE_ETH_SPEED_LANE_2), it will be
> > more flexible.
> >
>
> ok, I can replace the macros with unsigned integers
>
> > Probably all we need is 'RTE_ETH_SPEED_LANES_TO_CAPA' one to use as
> > helper in drivers.
> > Again not sure about the ..CAPA_MASK one, does it actually produce a
> > mask value?
> >
> >
> once replacing the LANE_xx to unsigned integers, then I don't need x_CAPA_MASK.
> In the driver, I can call RTE_32(lane number) while populating the table.
> EG:
>
>         { RTE_ETH_SPEED_NUM_100G, RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_1) |
>                                 RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_2) |
>                                 RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_4) },
> will become
>
>         { RTE_ETH_SPEED_NUM_100G, RTE_BIT32(1) |
>                                 RTE_BIT32(2) |
>                                 RTE_BIT32(4) },
  
Ferruh Yigit Sept. 25, 2024, 9:35 p.m. UTC | #4
On 9/25/2024 4:00 PM, Damodharam Ammepalli wrote:
> On Tue, Sep 24, 2024 at 3:59 PM Damodharam Ammepalli
> <damodharam.ammepalli@broadcom.com> wrote:
>>
>> On Sun, Sep 22, 2024 at 10:02 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>>
>>> On 9/4/2024 6:50 PM, Damodharam Ammepalli wrote:
>>>> Update the eth_dev_ops structure with new function vectors
>>>> to get, get capabilities and set ethernet link speed lanes.
>>>> Update the testpmd to provide required config and information
>>>> display infrastructure.
>>>>
>>>> The supporting ethernet controller driver will register callbacks
>>>> to avail link speed lanes config and get services. This lanes
>>>> configuration is applicable only when the nic is forced to fixed
>>>> speeds. In Autonegiation mode, the hardware automatically
>>>> negotiates the number of lanes.
>>>>
>>>> These are the new commands.
>>>>
>>>> testpmd> show port 0 speed_lanes capabilities
>>>>
>>>>  Supported speeds         Valid lanes
>>>> -----------------------------------
>>>>  10 Gbps                  1
>>>>  25 Gbps                  1
>>>>  40 Gbps                  4
>>>>  50 Gbps                  1 2
>>>>  100 Gbps                 1 2 4
>>>>  200 Gbps                 2 4
>>>>  400 Gbps                 4 8
>>>> testpmd>
>>>>
>>>> testpmd>
>>>> testpmd> port stop 0
>>>> testpmd> port config 0 speed_lanes 4
>>>> testpmd> port config 0 speed 200000 duplex full
>>>> testpmd> port start 0
>>>> testpmd>
>>>> testpmd> show port info 0
>>>>
>>>> ********************* Infos for port 0  *********************
>>>> MAC address: 14:23:F2:C3:BA:D2
>>>> Device name: 0000:b1:00.0
>>>> Driver name: net_bnxt
>>>> Firmware-version: 228.9.115.0
>>>> Connect to socket: 2
>>>> memory allocation on the socket: 2
>>>> Link status: up
>>>> Link speed: 200 Gbps
>>>> Active Lanes: 4
>>>> Link duplex: full-duplex
>>>> Autoneg status: Off
>>>>
>>>> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
>>>> ---
>>>>  app/test-pmd/cmdline.c     | 248 ++++++++++++++++++++++++++++++++++++-
>>>>  app/test-pmd/config.c      |   4 +
>>>>  lib/ethdev/ethdev_driver.h |  91 ++++++++++++++
>>>>  lib/ethdev/rte_ethdev.c    |  52 ++++++++
>>>>  lib/ethdev/rte_ethdev.h    |  95 ++++++++++++++
>>>>  lib/ethdev/version.map     |   5 +
>>>>  6 files changed, 494 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
>>>> index b7759e38a8..643102032e 100644
>>>> --- a/app/test-pmd/cmdline.c
>>>> +++ b/app/test-pmd/cmdline.c
>>>> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>>>>
>>>>                       "dump_log_types\n"
>>>>                       "    Dumps the log level for all the dpdk modules\n\n"
>>>> +
>>>> +                     "show port (port_id) speed_lanes capabilities"
>>>> +                     "       Show speed lanes capabilities of a port.\n\n"
>>>>               );
>>>>       }
>>>>
>>>> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>>>>                       "port config (port_id) txq (queue_id) affinity (value)\n"
>>>>                       "    Map a Tx queue with an aggregated port "
>>>>                       "of the DPDK port\n\n"
>>>> +
>>>> +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
>>>>
>>>
>>> This help string, and the implementation, implies there has to be fixed
>>> lane values, like 1, 4, 8. Why not leave this part to the capability
>>> reporting, and not limit (and worry) those values in the command, so
>>> from command's perspective it can be only <lane number>.
>>>
>>
>> ok, will update the help string to <lane number>
>>
>>>> +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
>>>>               );
>>>>       }
>>>>
>>>> @@ -1560,6 +1566,244 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
>>>>       },
>>>>  };
>>>>
>>>> +static int
>>>> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
>>>> +{
>>>> +     int ret;
>>>> +
>>>> +     ret = rte_eth_speed_lanes_set(pid, lanes);
>>>>
>>>
>>> As a sample application usage, I think it is better if it gets the
>>> capability and verify that 'lanes' is withing the capability and later
>>> set it, what do you think?
>>>
>>> <...>
>>
>> Makes sense, will try out and get back to you soon.
>>
> I guess a similar comment was discussed in the past, slipped my mind
> to mention in my last response.
> These are the reasons for this logic.
> -  same lane number can be supported by any speed (eg: 4 Lanes
> supported in 100,200,400 etc)
> so, which speed row should app check against, since the user has not
> configured fixed speed yet.
> If the link is already up in AN mode, this lane config doesn't have
> any significance.
> - one approach would be to validate lanes in
> parse_and_check_speed_duplex(), but in this case, the app should
> already have non-default lanes value. We also need to consider the
> case, if the user wants default lanes.
> - In the ethtool, the driver does the validation of the speed x lanes
> combo. Tried to match similar behaviour.
> 
> Let me know your thoughts.
> 

Hi Damodharam,

You are right, we can't verify the capability because of missing fixed
link speed. This is the affect of separating speed and lane.
Please scratch the ask, lets continue with the function as it is.

>>
>>>> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h> index
>>> 548fada1c7..9444e0a836 100644
>>>> --- a/lib/ethdev/rte_ethdev.h
>>>> +++ b/lib/ethdev/rte_ethdev.h
>>>> @@ -357,6 +357,27 @@ struct rte_eth_link {
>>>>  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
>>>>  /**@}*/
>>>>
>>>> +/**
>>>> + * Constants used to indicate the possible link speed lanes of an ethdev port.
>>>> + */
>>>> +#define RTE_ETH_SPEED_LANE_UNKNOWN  0  /**< speed lanes unsupported mode or default */
>>>> +#define RTE_ETH_SPEED_LANE_1  1        /**< Link speed lane  1 */
>>>> +#define RTE_ETH_SPEED_LANE_2  2        /**< Link speed lanes 2 */
>>>> +#define RTE_ETH_SPEED_LANE_4  4        /**< Link speed lanes 4 */
>>>> +#define RTE_ETH_SPEED_LANE_8  8        /**< Link speed lanes 8 */
>>>> +
>>>> +/* Translate from link speed lanes to speed lanes capa */
>>>> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
>>>> +
>>>> +/* This macro indicates link speed lanes capa mask */
>>>> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
>>>> +
>>>>
>>>
>>> I am not clear why we need these macros, why not use lane number as
>>> unsigned integer, instead of macro (RTE_ETH_SPEED_LANE_2), it will be
>>> more flexible.
>>>
>>
>> ok, I can replace the macros with unsigned integers
>>
>>> Probably all we need is 'RTE_ETH_SPEED_LANES_TO_CAPA' one to use as
>>> helper in drivers.
>>> Again not sure about the ..CAPA_MASK one, does it actually produce a
>>> mask value?
>>>
>>>
>> once replacing the LANE_xx to unsigned integers, then I don't need x_CAPA_MASK.
>> In the driver, I can call RTE_32(lane number) while populating the table.
>> EG:
>>
>>         { RTE_ETH_SPEED_NUM_100G, RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_1) |
>>                                 RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_2) |
>>                                 RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_4) },
>> will become
>>
>>         { RTE_ETH_SPEED_NUM_100G, RTE_BIT32(1) |
>>                                 RTE_BIT32(2) |
>>                                 RTE_BIT32(4) },
>
  
Ferruh Yigit Sept. 25, 2024, 9:35 p.m. UTC | #5
On 9/24/2024 11:59 PM, Damodharam Ammepalli wrote:
> On Sun, Sep 22, 2024 at 10:02 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 9/4/2024 6:50 PM, Damodharam Ammepalli wrote:
>>> Update the eth_dev_ops structure with new function vectors
>>> to get, get capabilities and set ethernet link speed lanes.
>>> Update the testpmd to provide required config and information
>>> display infrastructure.
>>>
>>> The supporting ethernet controller driver will register callbacks
>>> to avail link speed lanes config and get services. This lanes
>>> configuration is applicable only when the nic is forced to fixed
>>> speeds. In Autonegiation mode, the hardware automatically
>>> negotiates the number of lanes.
>>>
>>> These are the new commands.
>>>
>>> testpmd> show port 0 speed_lanes capabilities
>>>
>>>  Supported speeds         Valid lanes
>>> -----------------------------------
>>>  10 Gbps                  1
>>>  25 Gbps                  1
>>>  40 Gbps                  4
>>>  50 Gbps                  1 2
>>>  100 Gbps                 1 2 4
>>>  200 Gbps                 2 4
>>>  400 Gbps                 4 8
>>> testpmd>
>>>
>>> testpmd>
>>> testpmd> port stop 0
>>> testpmd> port config 0 speed_lanes 4
>>> testpmd> port config 0 speed 200000 duplex full
>>> testpmd> port start 0
>>> testpmd>
>>> testpmd> show port info 0
>>>
>>> ********************* Infos for port 0  *********************
>>> MAC address: 14:23:F2:C3:BA:D2
>>> Device name: 0000:b1:00.0
>>> Driver name: net_bnxt
>>> Firmware-version: 228.9.115.0
>>> Connect to socket: 2
>>> memory allocation on the socket: 2
>>> Link status: up
>>> Link speed: 200 Gbps
>>> Active Lanes: 4
>>> Link duplex: full-duplex
>>> Autoneg status: Off
>>>
>>> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
>>> ---
>>>  app/test-pmd/cmdline.c     | 248 ++++++++++++++++++++++++++++++++++++-
>>>  app/test-pmd/config.c      |   4 +
>>>  lib/ethdev/ethdev_driver.h |  91 ++++++++++++++
>>>  lib/ethdev/rte_ethdev.c    |  52 ++++++++
>>>  lib/ethdev/rte_ethdev.h    |  95 ++++++++++++++
>>>  lib/ethdev/version.map     |   5 +
>>>  6 files changed, 494 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
>>> index b7759e38a8..643102032e 100644
>>> --- a/app/test-pmd/cmdline.c
>>> +++ b/app/test-pmd/cmdline.c
>>> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>>>
>>>                       "dump_log_types\n"
>>>                       "    Dumps the log level for all the dpdk modules\n\n"
>>> +
>>> +                     "show port (port_id) speed_lanes capabilities"
>>> +                     "       Show speed lanes capabilities of a port.\n\n"
>>>               );
>>>       }
>>>
>>> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>>>                       "port config (port_id) txq (queue_id) affinity (value)\n"
>>>                       "    Map a Tx queue with an aggregated port "
>>>                       "of the DPDK port\n\n"
>>> +
>>> +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
>>>
>>
>> This help string, and the implementation, implies there has to be fixed
>> lane values, like 1, 4, 8. Why not leave this part to the capability
>> reporting, and not limit (and worry) those values in the command, so
>> from command's perspective it can be only <lane number>.
>>
> 
> ok, will update the help string to <lane number>
> 
>>> +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
>>>               );
>>>       }
>>>
>>> @@ -1560,6 +1566,244 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
>>>       },
>>>  };
>>>
>>> +static int
>>> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
>>> +{
>>> +     int ret;
>>> +
>>> +     ret = rte_eth_speed_lanes_set(pid, lanes);
>>>
>>
>> As a sample application usage, I think it is better if it gets the
>> capability and verify that 'lanes' is withing the capability and later
>> set it, what do you think?
>>
>> <...>
> 
> Makes sense, will try out and get back to you soon.
> 
> 
>>> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h> index
>> 548fada1c7..9444e0a836 100644
>>> --- a/lib/ethdev/rte_ethdev.h
>>> +++ b/lib/ethdev/rte_ethdev.h
>>> @@ -357,6 +357,27 @@ struct rte_eth_link {
>>>  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
>>>  /**@}*/
>>>
>>> +/**
>>> + * Constants used to indicate the possible link speed lanes of an ethdev port.
>>> + */
>>> +#define RTE_ETH_SPEED_LANE_UNKNOWN  0  /**< speed lanes unsupported mode or default */
>>> +#define RTE_ETH_SPEED_LANE_1  1        /**< Link speed lane  1 */
>>> +#define RTE_ETH_SPEED_LANE_2  2        /**< Link speed lanes 2 */
>>> +#define RTE_ETH_SPEED_LANE_4  4        /**< Link speed lanes 4 */
>>> +#define RTE_ETH_SPEED_LANE_8  8        /**< Link speed lanes 8 */
>>> +
>>> +/* Translate from link speed lanes to speed lanes capa */
>>> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
>>> +
>>> +/* This macro indicates link speed lanes capa mask */
>>> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
>>> +
>>>
>>
>> I am not clear why we need these macros, why not use lane number as
>> unsigned integer, instead of macro (RTE_ETH_SPEED_LANE_2), it will be
>> more flexible.
>>
> 
> ok, I can replace the macros with unsigned integers
> 
>> Probably all we need is 'RTE_ETH_SPEED_LANES_TO_CAPA' one to use as
>> helper in drivers.
>> Again not sure about the ..CAPA_MASK one, does it actually produce a
>> mask value?
>>
>>
> once replacing the LANE_xx to unsigned integers, then I don't need x_CAPA_MASK.
> In the driver, I can call RTE_32(lane number) while populating the table.
> EG:
> 
>         { RTE_ETH_SPEED_NUM_100G, RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_1) |
>                                 RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_2) |
>                                 RTE_ETH_SPEED_LANES_CAPA_MASK(LANE_4) },
> will become
> 
>         { RTE_ETH_SPEED_NUM_100G, RTE_BIT32(1) |
>                                 RTE_BIT32(2) |
>                                 RTE_BIT32(4) },
> 

ack
  
Ferruh Yigit Sept. 27, 2024, 12:41 a.m. UTC | #6
On 9/26/2024 10:43 PM, Damodharam Ammepalli wrote:
> This patch series is a continuation of the patch set that supports configuring speed lanes.
> https://patchwork.dpdk.org/project/dpdk/patch/20240708232351.491529-1-
> damodharam.ammepalli@broadcom.com/
> 
> The patchset consists
> 1) rtelib/testpmd changes (Addressing the comments). Earlier comments are available here, 
> https://patchwork.dpdk.org/project/dpdk/list/?
> q=Add%20link_speed%20lanes%20support&archive=both&series=&submitter=&delegate=&state=*
> 
> 2) Driver implementation of bnxt PMD.
> 
> v2->v3 Consolidating the testpmd and rtelib patches into a single patch as requested.
> v3->v4 Addressed comments and fix help string and documentation.
> v4->v5 Addressed comments given in v4 and also driver implementation of bnxt PMD.
> v5->v6 Removed LANE_xx enums and updated driver source files. Minor help
> string fix.
> 
> Damodharam Ammepalli (2):
>   ethdev: Add link_speed lanes support
>   net/bnxt: code refactor for supporting speed lanes
>

Hi Ajit,

Can you please review the bnxt patch, if it is good I can progress with
the series.
  
Ferruh Yigit Sept. 27, 2024, 10:23 p.m. UTC | #7
On 9/26/2024 10:43 PM, Damodharam Ammepalli wrote:
> This patch series is a continuation of the patch set that supports configuring speed lanes.
> https://patchwork.dpdk.org/project/dpdk/patch/20240708232351.491529-1-
> damodharam.ammepalli@broadcom.com/
> 
> The patchset consists
> 1) rtelib/testpmd changes (Addressing the comments). Earlier comments are available here, 
> https://patchwork.dpdk.org/project/dpdk/list/?
> q=Add%20link_speed%20lanes%20support&archive=both&series=&submitter=&delegate=&state=*
> 
> 2) Driver implementation of bnxt PMD.
> 
> v2->v3 Consolidating the testpmd and rtelib patches into a single patch as requested.
> v3->v4 Addressed comments and fix help string and documentation.
> v4->v5 Addressed comments given in v4 and also driver implementation of bnxt PMD.
> v5->v6 Removed LANE_xx enums and updated driver source files. Minor help
> string fix.
> 
> Damodharam Ammepalli (2):
>   ethdev: Add link_speed lanes support
>   net/bnxt: code refactor for supporting speed lanes
>

Series applied to dpdk-next-net/main, thanks.
  

Patch

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b7759e38a8..643102032e 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -284,6 +284,9 @@  static void cmd_help_long_parsed(void *parsed_result,
 
 			"dump_log_types\n"
 			"    Dumps the log level for all the dpdk modules\n\n"
+
+			"show port (port_id) speed_lanes capabilities"
+			"	Show speed lanes capabilities of a port.\n\n"
 		);
 	}
 
@@ -823,6 +826,9 @@  static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id) txq (queue_id) affinity (value)\n"
 			"    Map a Tx queue with an aggregated port "
 			"of the DPDK port\n\n"
+
+			"port config (port_id|all) speed_lanes (0|1|4|8)\n"
+			"    Set number of lanes for all ports or port_id for a forced speed\n\n"
 		);
 	}
 
@@ -1560,6 +1566,244 @@  static cmdline_parse_inst_t cmd_config_speed_specific = {
 	},
 };
 
+static int
+parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
+{
+	int ret;
+
+	ret = rte_eth_speed_lanes_set(pid, lanes);
+	if (ret == -ENOTSUP) {
+		fprintf(stderr, "Function not implemented\n");
+		return -1;
+	} else if (ret < 0) {
+		fprintf(stderr, "Set speed lanes failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
+{
+	unsigned int i;
+	uint32_t capa;
+
+	printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
+	printf("\n-----------------------------------\n");
+	for (i = 0; i < num; i++) {
+		printf("%-17s ",
+		       rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
+		capa = speed_lanes_capa[i].capa;
+		int s = 0;
+
+		while (capa) {
+			if (capa & 0x1)
+				printf("%-2d ", s);
+			s++;
+			capa = capa >> 1;
+		}
+		printf("\n");
+	}
+}
+
+/* *** display speed lanes per port capabilities *** */
+struct cmd_show_speed_lanes_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_speed_lanes_parsed(void *parsed_result,
+			    __rte_unused struct cmdline *cl,
+			    __rte_unused void *data)
+{
+	struct cmd_show_speed_lanes_result *res = parsed_result;
+	struct rte_eth_speed_lanes_capa *speed_lanes_capa;
+	unsigned int num;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
+	if (ret == -ENOTSUP) {
+		fprintf(stderr, "Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
+		return;
+	}
+
+	num = (unsigned int)ret;
+	speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
+	if (speed_lanes_capa == NULL) {
+		fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
+		return;
+	}
+
+	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
+	if (ret < 0) {
+		fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
+		goto out;
+	}
+
+	show_speed_lanes_capability(num, speed_lanes_capa);
+out:
+	free(speed_lanes_capa);
+}
+
+static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_show, "show");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_port, "port");
+static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
+			      cmd_pid, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "speed_lanes");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "capabilities");
+
+static cmdline_parse_inst_t cmd_show_speed_lanes = {
+	.f = cmd_show_speed_lanes_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> speed_lanes capabilities",
+	.tokens = {
+		(void *)&cmd_show_speed_lanes_show,
+		(void *)&cmd_show_speed_lanes_port,
+		(void *)&cmd_show_speed_lanes_pid,
+		(void *)&cmd_show_speed_lanes_keyword,
+		(void *)&cmd_show_speed_lanes_cap_keyword,
+		NULL,
+	},
+};
+
+/* *** configure speed_lanes for all ports *** */
+struct cmd_config_speed_lanes_all {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_all_parsed(void *parsed_result,
+				  __rte_unused struct cmdline *cl,
+				  __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_all *res = parsed_result;
+	portid_t pid;
+
+	if (!all_ports_stopped()) {
+		fprintf(stderr, "Please stop all ports first\n");
+		return;
+	}
+
+	RTE_ETH_FOREACH_DEV(pid) {
+		if (parse_speed_lanes_cfg(pid, res->lanes))
+			return;
+	}
+
+	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
+				 "config");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
+	.f = cmd_config_speed_lanes_all_parsed,
+	.data = NULL,
+	.help_str = "port config all speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_all_port,
+		(void *)&cmd_config_speed_lanes_all_keyword,
+		(void *)&cmd_config_speed_lanes_all_all,
+		(void *)&cmd_config_speed_lanes_all_item,
+		(void *)&cmd_config_speed_lanes_all_lanes,
+		NULL,
+	},
+};
+
+/* *** configure speed_lanes for specific port *** */
+struct cmd_config_speed_lanes_specific {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	uint16_t port_id;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_specific_parsed(void *parsed_result,
+				       __rte_unused struct cmdline *cl,
+				       __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_specific *res = parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!port_is_stopped(res->port_id)) {
+		fprintf(stderr, "Please stop port %u first\n", res->port_id);
+		return;
+	}
+
+	if (parse_speed_lanes_cfg(res->port_id, res->lanes))
+		return;
+
+	cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
+				 "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
+				 "config");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
+			      RTE_UINT16);
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
+			      RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
+	.f = cmd_config_speed_lanes_specific_parsed,
+	.data = NULL,
+	.help_str = "port config <port_id> speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_specific_port,
+		(void *)&cmd_config_speed_lanes_specific_keyword,
+		(void *)&cmd_config_speed_lanes_specific_id,
+		(void *)&cmd_config_speed_lanes_specific_item,
+		(void *)&cmd_config_speed_lanes_specific_lanes,
+		NULL,
+	},
+};
+
 /* *** configure loopback for all ports *** */
 struct cmd_config_loopback_all {
 	cmdline_fixed_string_t port;
@@ -1645,7 +1889,6 @@  cmd_config_loopback_specific_parsed(void *parsed_result,
 	cmd_reconfig_device_queue(res->port_id, 1, 1);
 }
 
-
 static cmdline_parse_token_string_t cmd_config_loopback_specific_port =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_specific, port,
 								"port");
@@ -13238,6 +13481,9 @@  static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_port_setup_on,
 	(cmdline_parse_inst_t *)&cmd_config_speed_all,
 	(cmdline_parse_inst_t *)&cmd_config_speed_specific,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
+	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,
 	(cmdline_parse_inst_t *)&cmd_config_loopback_all,
 	(cmdline_parse_inst_t *)&cmd_config_loopback_specific,
 	(cmdline_parse_inst_t *)&cmd_config_rx_tx,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 6f0beafa27..43b3a02732 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -786,6 +786,7 @@  port_infos_display(portid_t port_id)
 	char name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 	char fw_version[ETHDEV_FWVERS_LEN];
+	uint32_t lanes;
 
 	if (port_id_is_invalid(port_id, ENABLED_WARN)) {
 		print_valid_ports();
@@ -828,6 +829,8 @@  port_infos_display(portid_t port_id)
 
 	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
 	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
+	if (rte_eth_speed_lanes_get(port_id, &lanes) == 0)
+		printf("Active Lanes: %d\n", lanes);
 	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
 	       ("full-duplex") : ("half-duplex"));
 	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
@@ -7244,3 +7247,4 @@  show_mcast_macs(portid_t port_id)
 		printf("  %s\n", buf);
 	}
 }
+
diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index 883e59a927..abed4784aa 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -339,6 +339,93 @@  typedef int (*eth_allmulticast_disable_t)(struct rte_eth_dev *dev);
 typedef int (*eth_link_update_t)(struct rte_eth_dev *dev,
 				int wait_to_complete);
 
+/**
+ * @internal
+ * Get number of current active lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes
+ *   Number of active lanes that the link has trained up. This information
+ *   is displayed for Autonegotiated or Fixed speed trained link.
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get speed_lanes data success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
+
+/**
+ * @internal
+ * Set speed lanes supported by the NIC. This configuration is applicable only when
+ * fix speed is already configured and or will be configured. This api requires the
+ * port be stopped, since driver has to re-configure PHY with fixed speed and lanes.
+ * If no lanes are configured prior or after "port config X speed Y duplex Z", the
+ * driver will choose the default lane for that speed to bring up the link.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes
+ *   Non-negative number of lanes
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set lanes success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported number of lanes for fixed speed requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
+
+/**
+ * @internal
+ * Get supported link speed lanes capability. The driver returns number of lanes
+ * supported per speed in the form of lanes capability bitmap per speed.
+ *
+ * @param speed_lanes_capa
+ *   A pointer to num of rte_eth_speed_lanes_capa struct array which carries the
+ *   bit map of lanes supported per speed. The number of supported speeds is the
+ *   size of this speed_lanes_capa table. In link up condition, only active supported
+ *   speeds lanes bitmap information will be displayed. In link down condition, all
+ *   the supported speeds and its supported lanes bitmap would be fetched and displayed.
+ *
+ *   This api is overloaded to fetch the size of the speed_lanes_capa array if
+ *   testpmd calls the driver with speed_lanes_capa = NULL and num = 0
+ *
+ * @param num
+ *   Number of elements in a speed_speed_lanes_capa array. This num is equal to the
+ *   number of supported speeds by the controller. This value will vary in link up
+ *   and link down condition. num is updated by the driver if speed_lanes_capa is NULL.
+ *
+ * @return
+ *   Negative errno value on error, positive value on success.
+ *
+ * @retval positive value
+ *   A non-negative value lower or equal to num: success. The return value
+ *   is the number of entries filled in the speed lanes array.
+ *   A non-negative value higher than num: error, the given speed lanes capa array
+ *   is too small. The return value corresponds to the num that should
+ *   be given to succeed. The entries in the speed lanes capa array are not valid
+ *   and shall not be used by the caller.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   *num* or *speed_lanes_capa* invalid.
+ */
+typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
+						struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+						unsigned int num);
+
 /** @internal Get global I/O statistics of an Ethernet device. */
 typedef int (*eth_stats_get_t)(struct rte_eth_dev *dev,
 				struct rte_eth_stats *igb_stats);
@@ -1247,6 +1334,10 @@  struct eth_dev_ops {
 	eth_dev_close_t            dev_close;     /**< Close device */
 	eth_dev_reset_t		   dev_reset;	  /**< Reset device */
 	eth_link_update_t          link_update;   /**< Get device link state */
+	eth_speed_lanes_get_t	   speed_lanes_get;	  /**<Get link speed active lanes */
+	eth_speed_lanes_set_t      speed_lanes_set;	  /**<set the link speeds supported lanes */
+	/** Get link speed lanes capability */
+	eth_speed_lanes_get_capability_t speed_lanes_get_capa;
 	/** Check if the device was physically removed */
 	eth_is_removed_t           is_removed;
 
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index f1c658f49e..36427183d5 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -1849,6 +1849,58 @@  rte_eth_dev_set_link_down(uint16_t port_id)
 	return ret;
 }
 
+int
+rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_get == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
+}
+
+int
+rte_eth_speed_lanes_get_capability(uint16_t port_id,
+				   struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+				   unsigned int num)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_get_capa == NULL)
+		return -ENOTSUP;
+
+	if (speed_lanes_capa == NULL && num > 0) {
+		RTE_ETHDEV_LOG_LINE(ERR,
+				    "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
+				    port_id);
+		return -EINVAL;
+	}
+
+	ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
+
+	return ret;
+}
+
+int
+rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_set == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
+}
+
 int
 rte_eth_dev_close(uint16_t port_id)
 {
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 548fada1c7..9444e0a836 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -357,6 +357,27 @@  struct rte_eth_link {
 #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
 /**@}*/
 
+/**
+ * Constants used to indicate the possible link speed lanes of an ethdev port.
+ */
+#define RTE_ETH_SPEED_LANE_UNKNOWN  0  /**< speed lanes unsupported mode or default */
+#define RTE_ETH_SPEED_LANE_1  1        /**< Link speed lane  1 */
+#define RTE_ETH_SPEED_LANE_2  2        /**< Link speed lanes 2 */
+#define RTE_ETH_SPEED_LANE_4  4        /**< Link speed lanes 4 */
+#define RTE_ETH_SPEED_LANE_8  8        /**< Link speed lanes 8 */
+
+/* Translate from link speed lanes to speed lanes capa */
+#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
+
+/* This macro indicates link speed lanes capa mask */
+#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
+
+/* A structure used to get and set lanes capabilities per link speed */
+struct rte_eth_speed_lanes_capa {
+	uint32_t speed;
+	uint32_t capa;
+};
+
 /**
  * A structure used to configure the ring threshold registers of an Rx/Tx
  * queue for an Ethernet port.
@@ -3114,6 +3135,80 @@  __rte_experimental
 int rte_eth_link_to_str(char *str, size_t len,
 			const struct rte_eth_link *eth_link);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get Active lanes.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param lanes
+ *   Driver updates lanes with the number of active lanes.
+ *   On a supported NIC on link up, lanes will be a non-zero value irrespective whether the
+ *   link is Autonegotiated or Fixed speed. No information is dispalyed for error.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes
+ *   A non-zero number of speed lanes, that will be applied to the ethernet PHY
+ *   along with the fixed speed configuration. Driver returns error if the user
+ *   lanes is not in speeds capability list.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *lanes* count not in speeds capability list.
+ */
+__rte_experimental
+int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes_capa
+ *   An array of supported speed and its supported lanes.
+ * @param num
+ *   Size of the speed_lanes_capa array. The size is equal to the supported speeds list size.
+ *   Value of num is derived by calling this api with speed_lanes_capa=NULL and num=0
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get_capability(uint16_t port_id,
+				       struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+				       unsigned int num);
+
 /**
  * Retrieve the general I/O statistics of an Ethernet device.
  *
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 1669055ca5..b5ffded6f1 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -325,6 +325,11 @@  EXPERIMENTAL {
 	rte_flow_template_table_resizable;
 	rte_flow_template_table_resize;
 	rte_flow_template_table_resize_complete;
+
+	# added in 24.11
+	rte_eth_speed_lanes_get;
+	rte_eth_speed_lanes_get_capability;
+	rte_eth_speed_lanes_set;
 };
 
 INTERNAL {