[3/3] app/testpmd: support setting lanes
Checks
Commit Message
Extended speed command for setting lane number and
Show info print lane number.
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
app/test-pmd/cmdline.c | 110 +++++++++++---------
app/test-pmd/config.c | 60 +++++++----
doc/guides/rel_notes/release_24_03.rst | 1 +
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 3 +-
4 files changed, 103 insertions(+), 71 deletions(-)
Comments
On Tue, Mar 12, 2024 at 12:52 AM Dengdui Huang <huangdengdui@huawei.com> wrote:
>
> Extended speed command for setting lane number and
> Show info print lane number.
>
> Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
> ---
> app/test-pmd/cmdline.c | 110 +++++++++++---------
> app/test-pmd/config.c | 60 +++++++----
> doc/guides/rel_notes/release_24_03.rst | 1 +
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 3 +-
> 4 files changed, 103 insertions(+), 71 deletions(-)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index f521a1fe9e..e66daf4bba 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -1356,15 +1356,20 @@ struct cmd_config_speed_all {
> cmdline_fixed_string_t keyword;
> cmdline_fixed_string_t all;
> cmdline_fixed_string_t item1;
> + cmdline_fixed_string_t lanes_item;
> cmdline_fixed_string_t item2;
> cmdline_fixed_string_t value1;
> + uint8_t lanes_value;
> cmdline_fixed_string_t value2;
> };
>
> static int
> -parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
> +parse_and_check_speed_duplex(char *speedstr, uint8_t lanes, char *duplexstr,
> + uint32_t *speed)
> {
>
We internally implemented a similar feature, without changing the
existing testpmd speed cmd.
Instead of modifying the existing command set we can have a separate
cmd for the lanes
configuration similar to FEC configuration. Our internal
implementation looks something like this,
without affecting existing implementations.
testpmd> port stop 0
testpmd> port config 0 speed_lanes 4
testpmd> port config 0 speed 200000 duplex full
testpmd> port start 0
testpmd> show port summary 0
Number of available ports: 2
Port MAC Address Name Driver Status Link Lanes
0 14:23:F2:C3:BA:D2 0000:b1:00.0 net_bnxt up 200 Gbps 4
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
Lanes: 4
Link duplex: full-duplex
Autoneg status: Off
> + uint32_t speed_num;
> + char *endptr;
> int duplex;
>
> if (!strcmp(duplexstr, "half")) {
> @@ -1378,47 +1383,22 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
> return -1;
> }
>
> - if (!strcmp(speedstr, "10")) {
> - *speed = (duplex == RTE_ETH_LINK_HALF_DUPLEX) ?
> - RTE_ETH_LINK_SPEED_10M_HD : RTE_ETH_LINK_SPEED_10M;
> - } else if (!strcmp(speedstr, "100")) {
> - *speed = (duplex == RTE_ETH_LINK_HALF_DUPLEX) ?
> - RTE_ETH_LINK_SPEED_100M_HD : RTE_ETH_LINK_SPEED_100M;
> - } else {
> - if (duplex != RTE_ETH_LINK_FULL_DUPLEX) {
> - fprintf(stderr, "Invalid speed/duplex parameters\n");
> - return -1;
> - }
> - if (!strcmp(speedstr, "1000")) {
> - *speed = RTE_ETH_LINK_SPEED_1G;
> - } else if (!strcmp(speedstr, "2500")) {
> - *speed = RTE_ETH_LINK_SPEED_2_5G;
> - } else if (!strcmp(speedstr, "5000")) {
> - *speed = RTE_ETH_LINK_SPEED_5G;
> - } else if (!strcmp(speedstr, "10000")) {
> - *speed = RTE_ETH_LINK_SPEED_10G;
> - } else if (!strcmp(speedstr, "25000")) {
> - *speed = RTE_ETH_LINK_SPEED_25G;
> - } else if (!strcmp(speedstr, "40000")) {
> - *speed = RTE_ETH_LINK_SPEED_40G;
> - } else if (!strcmp(speedstr, "50000")) {
> - *speed = RTE_ETH_LINK_SPEED_50G;
> - } else if (!strcmp(speedstr, "100000")) {
> - *speed = RTE_ETH_LINK_SPEED_100G;
> - } else if (!strcmp(speedstr, "200000")) {
> - *speed = RTE_ETH_LINK_SPEED_200G;
> - } else if (!strcmp(speedstr, "400000")) {
> - *speed = RTE_ETH_LINK_SPEED_400G;
> - } else if (!strcmp(speedstr, "auto")) {
> - *speed = RTE_ETH_LINK_SPEED_AUTONEG;
> - } else {
> - fprintf(stderr, "Unknown speed parameter\n");
> - return -1;
> - }
> + if (!strcmp(speedstr, "auto")) {
> + *speed = RTE_ETH_LINK_SPEED_AUTONEG;
> + return 0;
> }
>
> - if (*speed != RTE_ETH_LINK_SPEED_AUTONEG)
> - *speed |= RTE_ETH_LINK_SPEED_FIXED;
> + speed_num = strtol(speedstr, &endptr, 10);
> + if (*endptr != '\0') {
> + fprintf(stderr, "Unknown speed parameter\n");
> + return -1;
> + }
> +
> + *speed = rte_eth_speed_bitflag(speed_num, lanes, duplex);
> + if (*speed == 0) {
> + fprintf(stderr, "param error\n");
> + return -1;
> + }
>
> return 0;
> }
> @@ -1429,19 +1409,27 @@ cmd_config_speed_all_parsed(void *parsed_result,
> __rte_unused void *data)
> {
> struct cmd_config_speed_all *res = parsed_result;
> + struct rte_eth_dev_info dev_info;
> uint32_t link_speed;
> portid_t pid;
> + int ret;
>
> if (!all_ports_stopped()) {
> fprintf(stderr, "Please stop all ports first\n");
> return;
> }
>
> - if (parse_and_check_speed_duplex(res->value1, res->value2,
> - &link_speed) < 0)
> + if (parse_and_check_speed_duplex(res->value1, res->lanes_value,
> + res->value2, &link_speed) < 0)
> return;
>
> RTE_ETH_FOREACH_DEV(pid) {
> + ret = eth_dev_info_get_print_err(pid, &dev_info);
> + if (ret != 0)
> + return;
> + if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_SETTING_LANES) == 0)
> + fprintf(stderr, "The setting lane may not take effect because "
> + "the port (%u) does not support it\n", pid);
> ports[pid].dev_conf.link_speeds = link_speed;
> }
>
> @@ -1460,6 +1448,11 @@ static cmdline_parse_token_string_t cmd_config_speed_all_item1 =
> static cmdline_parse_token_string_t cmd_config_speed_all_value1 =
> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
> "10#100#1000#2500#5000#10000#25000#40000#50000#100000#200000#400000#auto");
> +static cmdline_parse_token_string_t cmd_config_speed_all_lanes_item =
> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, lanes_item, "lanes");
> +static cmdline_parse_token_num_t cmd_config_speed_all_lanes_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_all, lanes_value,
> + RTE_UINT8);
> static cmdline_parse_token_string_t cmd_config_speed_all_item2 =
> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
> static cmdline_parse_token_string_t cmd_config_speed_all_value2 =
> @@ -1470,14 +1463,16 @@ static cmdline_parse_inst_t cmd_config_speed_all = {
> .f = cmd_config_speed_all_parsed,
> .data = NULL,
> .help_str = "port config all speed "
> - "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto duplex "
> - "half|full|auto",
> + "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto"
> + " lanes 1|2|4|8 duplex half|full|auto",
> .tokens = {
> (void *)&cmd_config_speed_all_port,
> (void *)&cmd_config_speed_all_keyword,
> (void *)&cmd_config_speed_all_all,
> (void *)&cmd_config_speed_all_item1,
> (void *)&cmd_config_speed_all_value1,
> + (void *)&cmd_config_speed_all_lanes_item,
> + (void *)&cmd_config_speed_all_lanes_value,
> (void *)&cmd_config_speed_all_item2,
> (void *)&cmd_config_speed_all_value2,
> NULL,
> @@ -1490,8 +1485,10 @@ struct cmd_config_speed_specific {
> cmdline_fixed_string_t keyword;
> portid_t id;
> cmdline_fixed_string_t item1;
> + cmdline_fixed_string_t lanes_item;
> cmdline_fixed_string_t item2;
> cmdline_fixed_string_t value1;
> + uint8_t lanes_value;
> cmdline_fixed_string_t value2;
> };
>
> @@ -1501,7 +1498,9 @@ cmd_config_speed_specific_parsed(void *parsed_result,
> __rte_unused void *data)
> {
> struct cmd_config_speed_specific *res = parsed_result;
> + struct rte_eth_dev_info dev_info;
> uint32_t link_speed;
> + int ret;
>
> if (port_id_is_invalid(res->id, ENABLED_WARN))
> return;
> @@ -1511,8 +1510,15 @@ cmd_config_speed_specific_parsed(void *parsed_result,
> return;
> }
>
> - if (parse_and_check_speed_duplex(res->value1, res->value2,
> - &link_speed) < 0)
> + ret = eth_dev_info_get_print_err(res->id, &dev_info);
> + if (ret != 0)
> + return;
> + if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_SETTING_LANES) == 0)
> + fprintf(stderr, "The setting lane may not take effect because "
> + "the port (%d) does not support it\n", res->id);
> +
> + if (parse_and_check_speed_duplex(res->value1, res->lanes_value,
> + res->value2, &link_speed) < 0)
> return;
>
> ports[res->id].dev_conf.link_speeds = link_speed;
> @@ -1535,6 +1541,12 @@ static cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
> static cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
> "10#100#1000#2500#5000#10000#25000#40000#50000#100000#200000#400000#auto");
> +static cmdline_parse_token_string_t cmd_config_speed_specific_lanes_item =
> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, lanes_item,
> + "lanes");
> +static cmdline_parse_token_num_t cmd_config_speed_specific_lanes_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, lanes_value,
> + RTE_UINT8);
> static cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
> "duplex");
> @@ -1546,14 +1558,16 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
> .f = cmd_config_speed_specific_parsed,
> .data = NULL,
> .help_str = "port config <port_id> speed "
> - "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto duplex "
> - "half|full|auto",
> + "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto"
> + " lanes 1|2|4|8 duplex half|full|auto",
> .tokens = {
> (void *)&cmd_config_speed_specific_port,
> (void *)&cmd_config_speed_specific_keyword,
> (void *)&cmd_config_speed_specific_id,
> (void *)&cmd_config_speed_specific_item1,
> (void *)&cmd_config_speed_specific_value1,
> + (void *)&cmd_config_speed_specific_lanes_item,
> + (void *)&cmd_config_speed_specific_lanes_value,
> (void *)&cmd_config_speed_specific_item2,
> (void *)&cmd_config_speed_specific_value2,
> NULL,
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 968d2164ab..c104327878 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -587,39 +587,51 @@ device_infos_display_speeds(uint32_t speed_capa)
> if (speed_capa == RTE_ETH_LINK_SPEED_AUTONEG)
> printf(" Autonegotiate (all speeds)");
> if (speed_capa & RTE_ETH_LINK_SPEED_FIXED)
> - printf(" Disable autonegotiate (fixed speed) ");
> + printf(" Disable autonegotiate (fixed speed) /");
> if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
> - printf(" 10 Mbps half-duplex ");
> + printf(" 10Mbps_1lane_half-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_10M)
> - printf(" 10 Mbps full-duplex ");
> + printf(" 10Mbps_1lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
> - printf(" 100 Mbps half-duplex ");
> + printf(" 100Mbps_lane_half-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_100M)
> - printf(" 100 Mbps full-duplex ");
> + printf(" 100Mbps_1lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_1G)
> - printf(" 1 Gbps ");
> + printf(" 1Gbps_1lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
> - printf(" 2.5 Gbps ");
> + printf(" 2.5Gbps_1lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_5G)
> - printf(" 5 Gbps ");
> + printf(" 5Gbps_1lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_10G)
> - printf(" 10 Gbps ");
> - if (speed_capa & RTE_ETH_LINK_SPEED_20G)
> - printf(" 20 Gbps ");
> + printf(" 10Gbps_1lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_10G_4LANES)
> + printf(" 10Gbps_4lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_20G_2LANES)
> + printf(" 20Gbps_2lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_25G)
> - printf(" 25 Gbps ");
> - if (speed_capa & RTE_ETH_LINK_SPEED_40G)
> - printf(" 40 Gbps ");
> + printf(" 25Gbps_1lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_40G_4LANES)
> + printf(" 40Gbps_4lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_50G)
> - printf(" 50 Gbps ");
> - if (speed_capa & RTE_ETH_LINK_SPEED_56G)
> - printf(" 56 Gbps ");
> + printf(" 50Gbps_1lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_50G_2LANES)
> + printf(" 50Gbps_2lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_56G_4LANES)
> + printf(" 56Gbps_4lane_full-duplex /");
> if (speed_capa & RTE_ETH_LINK_SPEED_100G)
> - printf(" 100 Gbps ");
> - if (speed_capa & RTE_ETH_LINK_SPEED_200G)
> - printf(" 200 Gbps ");
> - if (speed_capa & RTE_ETH_LINK_SPEED_400G)
> - printf(" 400 Gbps ");
> + printf(" 100Gbps_1lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_100G_2LANES)
> + printf(" 100Gbps_2lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_100G_4LANES)
> + printf(" 100Gbps_4lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_200G_4LANES)
> + printf(" 200Gbps_4lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_200G_2LANES)
> + printf(" 200Gbps_2lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_400G_4LANES)
> + printf(" 400Gbps_4lane_full-duplex /");
> + if (speed_capa & RTE_ETH_LINK_SPEED_400G_8LANES)
> + printf(" 400Gbps_8lane_full-duplex /");
> }
>
> void
> @@ -828,6 +840,10 @@ 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 (link.link_lanes == 0)
> + printf("Link lanes: unknown\n");
> + else
> + printf("Link lanes: %u\n", link.link_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) ?
> diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
> index c17334ac25..46aceeee93 100644
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -79,6 +79,7 @@ New Features
> * **Support setting lanes for ethdev.**
> * Support setting lanes by extended ``RTE_ETH_LINK_SPEED_*``.
> * Added function to convert bitmap flag to the struct of link speed info.
> + ``rte_eth_speed_capa_to_info()``
>
> * **Added hash calculation of an encapsulated packet as done by the HW.**
>
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 2fbf9220d8..087f7fe853 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -190,6 +190,7 @@ For example:
> memory allocation on the socket: 0
> Link status: up
> Link speed: 40000 Mbps
> + Link lanes: 4
> Link duplex: full-duplex
> Promiscuous mode: enabled
> Allmulticast mode: disabled
> @@ -2065,7 +2066,7 @@ port config - speed
> Set the speed and duplex mode for all ports or a specific port::
>
> testpmd> port config (port_id|all) speed (10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto) \
> - duplex (half|full|auto)
> + lanes 1|2|4|8 duplex (half|full|auto)
>
> port config - queues/descriptors
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --
> 2.33.0
>
On 2024/3/16 5:47, Damodharam Ammepalli wrote:
> On Tue, Mar 12, 2024 at 12:52 AM Dengdui Huang <huangdengdui@huawei.com> wrote:
>>
>> Extended speed command for setting lane number and
>> Show info print lane number.
>>
>> Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
>> ---
>> app/test-pmd/cmdline.c | 110 +++++++++++---------
>> app/test-pmd/config.c | 60 +++++++----
>> doc/guides/rel_notes/release_24_03.rst | 1 +
>> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 3 +-
>> 4 files changed, 103 insertions(+), 71 deletions(-)
>>
>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
>> index f521a1fe9e..e66daf4bba 100644
>> --- a/app/test-pmd/cmdline.c
>> +++ b/app/test-pmd/cmdline.c
>> @@ -1356,15 +1356,20 @@ struct cmd_config_speed_all {
>> cmdline_fixed_string_t keyword;
>> cmdline_fixed_string_t all;
>> cmdline_fixed_string_t item1;
>> + cmdline_fixed_string_t lanes_item;
>> cmdline_fixed_string_t item2;
>> cmdline_fixed_string_t value1;
>> + uint8_t lanes_value;
>> cmdline_fixed_string_t value2;
>> };
>>
>> static int
>> -parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
>> +parse_and_check_speed_duplex(char *speedstr, uint8_t lanes, char *duplexstr,
>> + uint32_t *speed)
>> {
>>
> We internally implemented a similar feature, without changing the
> existing testpmd speed cmd.
> Instead of modifying the existing command set we can have a separate
> cmd for the lanes
> configuration similar to FEC configuration. Our internal
> implementation looks something like this,
> without affecting existing implementations.
> testpmd> port stop 0
> testpmd> port config 0 speed_lanes 4
Hi, Damodharam,
Thanks for your review.
I think the lanes should be configured with speed and duplex,
they will eventually map to Link speed capabilities(RTE_ETH_LINK_SPEED_*).
Would it be better to add the following new command?
testpmd> port config 0 speed 200000 lanes 4 duplex full
It can be used when the driver supports setting lanes;
It cannot be used when the driver does not support the setting lanes.
what do you think?
> testpmd> port config 0 speed 200000 duplex full
> testpmd> port start 0
> testpmd> show port summary 0
> Number of available ports: 2
> Port MAC Address Name Driver Status Link Lanes
> 0 14:23:F2:C3:BA:D2 0000:b1:00.0 net_bnxt up 200 Gbps 4
The summary command adds print of the number of lanes.
I will implement this in the next version.
> 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
> Lanes: 4
> Link duplex: full-duplex
> Autoneg status: Off
>
>> + uint32_t speed_num;
>> + char *endptr;
>> int duplex;
>>
>> if (!strcmp(duplexstr, "half")) {
>> @@ -1378,47 +1383,22 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
>> return -1;
>> }
>>
>> - if (!strcmp(speedstr, "10")) {
>> - *speed = (duplex == RTE_ETH_LINK_HALF_DUPLEX) ?
>> - RTE_ETH_LINK_SPEED_10M_HD : RTE_ETH_LINK_SPEED_10M;
>> - } else if (!strcmp(speedstr, "100")) {
>> - *speed = (duplex == RTE_ETH_LINK_HALF_DUPLEX) ?
>> - RTE_ETH_LINK_SPEED_100M_HD : RTE_ETH_LINK_SPEED_100M;
>> - } else {
>> - if (duplex != RTE_ETH_LINK_FULL_DUPLEX) {
>> - fprintf(stderr, "Invalid speed/duplex parameters\n");
>> - return -1;
>> - }
>> - if (!strcmp(speedstr, "1000")) {
>> - *speed = RTE_ETH_LINK_SPEED_1G;
>> - } else if (!strcmp(speedstr, "2500")) {
>> - *speed = RTE_ETH_LINK_SPEED_2_5G;
>> - } else if (!strcmp(speedstr, "5000")) {
>> - *speed = RTE_ETH_LINK_SPEED_5G;
>> - } else if (!strcmp(speedstr, "10000")) {
>> - *speed = RTE_ETH_LINK_SPEED_10G;
>> - } else if (!strcmp(speedstr, "25000")) {
>> - *speed = RTE_ETH_LINK_SPEED_25G;
>> - } else if (!strcmp(speedstr, "40000")) {
>> - *speed = RTE_ETH_LINK_SPEED_40G;
>> - } else if (!strcmp(speedstr, "50000")) {
>> - *speed = RTE_ETH_LINK_SPEED_50G;
>> - } else if (!strcmp(speedstr, "100000")) {
>> - *speed = RTE_ETH_LINK_SPEED_100G;
>> - } else if (!strcmp(speedstr, "200000")) {
>> - *speed = RTE_ETH_LINK_SPEED_200G;
>> - } else if (!strcmp(speedstr, "400000")) {
>> - *speed = RTE_ETH_LINK_SPEED_400G;
>> - } else if (!strcmp(speedstr, "auto")) {
>> - *speed = RTE_ETH_LINK_SPEED_AUTONEG;
>> - } else {
>> - fprintf(stderr, "Unknown speed parameter\n");
>> - return -1;
>> - }
>> + if (!strcmp(speedstr, "auto")) {
>> + *speed = RTE_ETH_LINK_SPEED_AUTONEG;
>> + return 0;
>> }
>>
>> - if (*speed != RTE_ETH_LINK_SPEED_AUTONEG)
>> - *speed |= RTE_ETH_LINK_SPEED_FIXED;
>> + speed_num = strtol(speedstr, &endptr, 10);
>> + if (*endptr != '\0') {
>> + fprintf(stderr, "Unknown speed parameter\n");
>> + return -1;
>> + }
>> +
>> + *speed = rte_eth_speed_bitflag(speed_num, lanes, duplex);
>> + if (*speed == 0) {
>> + fprintf(stderr, "param error\n");
>> + return -1;
>> + }
>>
>> return 0;
>> }
>> @@ -1429,19 +1409,27 @@ cmd_config_speed_all_parsed(void *parsed_result,
>> __rte_unused void *data)
>> {
>> struct cmd_config_speed_all *res = parsed_result;
>> + struct rte_eth_dev_info dev_info;
>> uint32_t link_speed;
>> portid_t pid;
>> + int ret;
>>
>> if (!all_ports_stopped()) {
>> fprintf(stderr, "Please stop all ports first\n");
>> return;
>> }
>>
>> - if (parse_and_check_speed_duplex(res->value1, res->value2,
>> - &link_speed) < 0)
>> + if (parse_and_check_speed_duplex(res->value1, res->lanes_value,
>> + res->value2, &link_speed) < 0)
>> return;
>>
>> RTE_ETH_FOREACH_DEV(pid) {
>> + ret = eth_dev_info_get_print_err(pid, &dev_info);
>> + if (ret != 0)
>> + return;
>> + if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_SETTING_LANES) == 0)
>> + fprintf(stderr, "The setting lane may not take effect because "
>> + "the port (%u) does not support it\n", pid);
>> ports[pid].dev_conf.link_speeds = link_speed;
>> }
>>
>> @@ -1460,6 +1448,11 @@ static cmdline_parse_token_string_t cmd_config_speed_all_item1 =
>> static cmdline_parse_token_string_t cmd_config_speed_all_value1 =
>> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
>> "10#100#1000#2500#5000#10000#25000#40000#50000#100000#200000#400000#auto");
>> +static cmdline_parse_token_string_t cmd_config_speed_all_lanes_item =
>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, lanes_item, "lanes");
>> +static cmdline_parse_token_num_t cmd_config_speed_all_lanes_value =
>> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_all, lanes_value,
>> + RTE_UINT8);
>> static cmdline_parse_token_string_t cmd_config_speed_all_item2 =
>> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
>> static cmdline_parse_token_string_t cmd_config_speed_all_value2 =
>> @@ -1470,14 +1463,16 @@ static cmdline_parse_inst_t cmd_config_speed_all = {
>> .f = cmd_config_speed_all_parsed,
>> .data = NULL,
>> .help_str = "port config all speed "
>> - "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto duplex "
>> - "half|full|auto",
>> + "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto"
>> + " lanes 1|2|4|8 duplex half|full|auto",
>> .tokens = {
>> (void *)&cmd_config_speed_all_port,
>> (void *)&cmd_config_speed_all_keyword,
>> (void *)&cmd_config_speed_all_all,
>> (void *)&cmd_config_speed_all_item1,
>> (void *)&cmd_config_speed_all_value1,
>> + (void *)&cmd_config_speed_all_lanes_item,
>> + (void *)&cmd_config_speed_all_lanes_value,
>> (void *)&cmd_config_speed_all_item2,
>> (void *)&cmd_config_speed_all_value2,
>> NULL,
>> @@ -1490,8 +1485,10 @@ struct cmd_config_speed_specific {
>> cmdline_fixed_string_t keyword;
>> portid_t id;
>> cmdline_fixed_string_t item1;
>> + cmdline_fixed_string_t lanes_item;
>> cmdline_fixed_string_t item2;
>> cmdline_fixed_string_t value1;
>> + uint8_t lanes_value;
>> cmdline_fixed_string_t value2;
>> };
>>
>> @@ -1501,7 +1498,9 @@ cmd_config_speed_specific_parsed(void *parsed_result,
>> __rte_unused void *data)
>> {
>> struct cmd_config_speed_specific *res = parsed_result;
>> + struct rte_eth_dev_info dev_info;
>> uint32_t link_speed;
>> + int ret;
>>
>> if (port_id_is_invalid(res->id, ENABLED_WARN))
>> return;
>> @@ -1511,8 +1510,15 @@ cmd_config_speed_specific_parsed(void *parsed_result,
>> return;
>> }
>>
>> - if (parse_and_check_speed_duplex(res->value1, res->value2,
>> - &link_speed) < 0)
>> + ret = eth_dev_info_get_print_err(res->id, &dev_info);
>> + if (ret != 0)
>> + return;
>> + if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_SETTING_LANES) == 0)
>> + fprintf(stderr, "The setting lane may not take effect because "
>> + "the port (%d) does not support it\n", res->id);
>> +
>> + if (parse_and_check_speed_duplex(res->value1, res->lanes_value,
>> + res->value2, &link_speed) < 0)
>> return;
>>
>> ports[res->id].dev_conf.link_speeds = link_speed;
>> @@ -1535,6 +1541,12 @@ static cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
>> static cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
>> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
>> "10#100#1000#2500#5000#10000#25000#40000#50000#100000#200000#400000#auto");
>> +static cmdline_parse_token_string_t cmd_config_speed_specific_lanes_item =
>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, lanes_item,
>> + "lanes");
>> +static cmdline_parse_token_num_t cmd_config_speed_specific_lanes_value =
>> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, lanes_value,
>> + RTE_UINT8);
>> static cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
>> TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
>> "duplex");
>> @@ -1546,14 +1558,16 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
>> .f = cmd_config_speed_specific_parsed,
>> .data = NULL,
>> .help_str = "port config <port_id> speed "
>> - "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto duplex "
>> - "half|full|auto",
>> + "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto"
>> + " lanes 1|2|4|8 duplex half|full|auto",
>> .tokens = {
>> (void *)&cmd_config_speed_specific_port,
>> (void *)&cmd_config_speed_specific_keyword,
>> (void *)&cmd_config_speed_specific_id,
>> (void *)&cmd_config_speed_specific_item1,
>> (void *)&cmd_config_speed_specific_value1,
>> + (void *)&cmd_config_speed_specific_lanes_item,
>> + (void *)&cmd_config_speed_specific_lanes_value,
>> (void *)&cmd_config_speed_specific_item2,
>> (void *)&cmd_config_speed_specific_value2,
>> NULL,
>> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
>> index 968d2164ab..c104327878 100644
>> --- a/app/test-pmd/config.c
>> +++ b/app/test-pmd/config.c
>> @@ -587,39 +587,51 @@ device_infos_display_speeds(uint32_t speed_capa)
>> if (speed_capa == RTE_ETH_LINK_SPEED_AUTONEG)
>> printf(" Autonegotiate (all speeds)");
>> if (speed_capa & RTE_ETH_LINK_SPEED_FIXED)
>> - printf(" Disable autonegotiate (fixed speed) ");
>> + printf(" Disable autonegotiate (fixed speed) /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
>> - printf(" 10 Mbps half-duplex ");
>> + printf(" 10Mbps_1lane_half-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_10M)
>> - printf(" 10 Mbps full-duplex ");
>> + printf(" 10Mbps_1lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
>> - printf(" 100 Mbps half-duplex ");
>> + printf(" 100Mbps_lane_half-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_100M)
>> - printf(" 100 Mbps full-duplex ");
>> + printf(" 100Mbps_1lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_1G)
>> - printf(" 1 Gbps ");
>> + printf(" 1Gbps_1lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
>> - printf(" 2.5 Gbps ");
>> + printf(" 2.5Gbps_1lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_5G)
>> - printf(" 5 Gbps ");
>> + printf(" 5Gbps_1lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_10G)
>> - printf(" 10 Gbps ");
>> - if (speed_capa & RTE_ETH_LINK_SPEED_20G)
>> - printf(" 20 Gbps ");
>> + printf(" 10Gbps_1lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_10G_4LANES)
>> + printf(" 10Gbps_4lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_20G_2LANES)
>> + printf(" 20Gbps_2lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_25G)
>> - printf(" 25 Gbps ");
>> - if (speed_capa & RTE_ETH_LINK_SPEED_40G)
>> - printf(" 40 Gbps ");
>> + printf(" 25Gbps_1lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_40G_4LANES)
>> + printf(" 40Gbps_4lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_50G)
>> - printf(" 50 Gbps ");
>> - if (speed_capa & RTE_ETH_LINK_SPEED_56G)
>> - printf(" 56 Gbps ");
>> + printf(" 50Gbps_1lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_50G_2LANES)
>> + printf(" 50Gbps_2lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_56G_4LANES)
>> + printf(" 56Gbps_4lane_full-duplex /");
>> if (speed_capa & RTE_ETH_LINK_SPEED_100G)
>> - printf(" 100 Gbps ");
>> - if (speed_capa & RTE_ETH_LINK_SPEED_200G)
>> - printf(" 200 Gbps ");
>> - if (speed_capa & RTE_ETH_LINK_SPEED_400G)
>> - printf(" 400 Gbps ");
>> + printf(" 100Gbps_1lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_100G_2LANES)
>> + printf(" 100Gbps_2lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_100G_4LANES)
>> + printf(" 100Gbps_4lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_200G_4LANES)
>> + printf(" 200Gbps_4lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_200G_2LANES)
>> + printf(" 200Gbps_2lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_400G_4LANES)
>> + printf(" 400Gbps_4lane_full-duplex /");
>> + if (speed_capa & RTE_ETH_LINK_SPEED_400G_8LANES)
>> + printf(" 400Gbps_8lane_full-duplex /");
>> }
>>
>> void
>> @@ -828,6 +840,10 @@ 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 (link.link_lanes == 0)
>> + printf("Link lanes: unknown\n");
>> + else
>> + printf("Link lanes: %u\n", link.link_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) ?
>> diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
>> index c17334ac25..46aceeee93 100644
>> --- a/doc/guides/rel_notes/release_24_03.rst
>> +++ b/doc/guides/rel_notes/release_24_03.rst
>> @@ -79,6 +79,7 @@ New Features
>> * **Support setting lanes for ethdev.**
>> * Support setting lanes by extended ``RTE_ETH_LINK_SPEED_*``.
>> * Added function to convert bitmap flag to the struct of link speed info.
>> + ``rte_eth_speed_capa_to_info()``
>>
>> * **Added hash calculation of an encapsulated packet as done by the HW.**
>>
>> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> index 2fbf9220d8..087f7fe853 100644
>> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> @@ -190,6 +190,7 @@ For example:
>> memory allocation on the socket: 0
>> Link status: up
>> Link speed: 40000 Mbps
>> + Link lanes: 4
>> Link duplex: full-duplex
>> Promiscuous mode: enabled
>> Allmulticast mode: disabled
>> @@ -2065,7 +2066,7 @@ port config - speed
>> Set the speed and duplex mode for all ports or a specific port::
>>
>> testpmd> port config (port_id|all) speed (10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto) \
>> - duplex (half|full|auto)
>> + lanes 1|2|4|8 duplex (half|full|auto)
>>
>> port config - queues/descriptors
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> --
>> 2.33.0
>>
>
On 3/22/2024 7:09 AM, Dengdui Huang wrote:
> At the physical layer, multiple lanes are often used to work together
> to achieve higher speeds. So a speeds can be achieved with different
> number of lanes. For example, the following solutions can be used to
> implement 100G:
> 1. Combines four 25G lanes
> 2. Combines two 50G lanes
> 3. A single 100G lane
>
> It is assumed that two ports are interconnected and the two ports support
> the above three solutions. But, we just configured the speed to 100G and
> one port uses four 25G lanes by default and the other port uses two 50G lanes
> by default, the port cannot be up. In this case, we need to configure the
> ports to use the same solutions (for example, uses two 50G lanes) so that
> the ports can be up.
>
> This patch set add support setting lanes for ethdev. application can use
> this feature to configure lanes to help select the same solutions.
>
Hi Dengdui, Damodharam,
As details of the implementation under discussion, I have a high level
question.
Why/when an application need to configure the lanes explicitly?
In above description, it mentions if one port is configured as 4x25G and
other 2x50G, port can't be up. How do you end up being in this situation?
Lets assume first port is configured as 100G, and FW configured it as
4x25G, and again user configured second port as 100G, why FW can't
detect this and configure ports with correct lane configuration?
In this case, if we push the responsibility to the user, when user is
configuring the second port how she will know what is the lane
configuration for first port, and what is the proper lane configuration
for the second port?
Instead of pushing this configuration to user, why it can't be handled
internally?
As long as user requested speed configured by device, the lane
configuration has no impact to the user, right?
Is there a case/reason user need to explicitly set, lets say PAM4
against NRZ?
Thanks,
ferruh
Hi, Ferruh
Sorry for replying your email very late.
The answers to your questions are as follows. Please correct me if I am wrong.
On 2024/4/4 21:58, Ferruh Yigit wrote:
>
> Hi Dengdui, Damodharam,
>
> As details of the implementation under discussion, I have a high level
> question.
>
> Why/when an application need to configure the lanes explicitly?
>
> In above description, it mentions if one port is configured as 4x25G and
> other 2x50G, port can't be up. How do you end up being in this situation?
>
According to the Ethernet standard document[1], speed and lanes need to be configured to the PHY together.
Currently, the application just set one speed like 100G to the driver.
And this doesn't matter with lane number.
Currently, the lane number of one NIC for a specified speed depand on their default behavior.
As a result, this situation will be happened.
> Lets assume first port is configured as 100G, and FW configured it as
> 4x25G, and again user configured second port as 100G, why FW can't
> detect this and configure ports with correct lane configuration?
When the auto-negotiation is disabled, FW of the local port never know the configuration of
the peer port.
After all, not all NICs support auto-negotiation feature.
>
> In this case, if we push the responsibility to the user, when user is
> configuring the second port how she will know what is the lane
> configuration for first port, and what is the proper lane configuration
> for the second port?
So we need to support the lane query function for above reason.
>
> Instead of pushing this configuration to user, why it can't be handled
> internally?
>
> As long as user requested speed configured by device, the lane
> configuration has no impact to the user, right?> Is there a case/reason user need to explicitly set, lets say PAM4
> against NRZ?
>
Sorry, I can not understand what you mean.
[1]
https://lore.kernel.org/netdev/20201010154119.3537085-1-idosch@idosch.org/T/
On 5/16/2024 1:48 PM, huangdengdui wrote:
> Hi, Ferruh
> Sorry for replying your email very late.
> The answers to your questions are as follows. Please correct me if I am wrong.
>
> On 2024/4/4 21:58, Ferruh Yigit wrote:
>>
>> Hi Dengdui, Damodharam,
>>
>> As details of the implementation under discussion, I have a high level
>> question.
>>
>> Why/when an application need to configure the lanes explicitly?
>>
>> In above description, it mentions if one port is configured as 4x25G and
>> other 2x50G, port can't be up. How do you end up being in this situation?
>>
>
> According to the Ethernet standard document[1], speed and lanes need to be configured to the PHY together.
> Currently, the application just set one speed like 100G to the driver.
> And this doesn't matter with lane number.
> Currently, the lane number of one NIC for a specified speed depand on their default behavior.
> As a result, this situation will be happened.
>
I guess we come to agreement that with three new APIs for lane (get,
set, get_capabilities), link speed and lane APIs can be separated, this
cause more clear APIs.
>> Lets assume first port is configured as 100G, and FW configured it as
>> 4x25G, and again user configured second port as 100G, why FW can't
>> detect this and configure ports with correct lane configuration?
>
> When the auto-negotiation is disabled, FW of the local port never know the configuration of
> the peer port.
>
> After all, not all NICs support auto-negotiation feature.
>
Ack
>>
>> In this case, if we push the responsibility to the user, when user is
>> configuring the second port how she will know what is the lane
>> configuration for first port, and what is the proper lane configuration
>> for the second port?
>
> So we need to support the lane query function for above reason.
>
Ack
>>
>> Instead of pushing this configuration to user, why it can't be handled
>> internally?
>>
>> As long as user requested speed configured by device, the lane
>> configuration has no impact to the user, right?> Is there a case/reason user need to explicitly set, lets say PAM4
>> against NRZ?
>>
> Sorry, I can not understand what you mean.
>
Indeed you already answered this one, explicit lane configuration is
required two align configuration of both peers when auto-negotiation is off.
> [1]
> https://lore.kernel.org/netdev/20201010154119.3537085-1-idosch@idosch.org/T/
@@ -1356,15 +1356,20 @@ struct cmd_config_speed_all {
cmdline_fixed_string_t keyword;
cmdline_fixed_string_t all;
cmdline_fixed_string_t item1;
+ cmdline_fixed_string_t lanes_item;
cmdline_fixed_string_t item2;
cmdline_fixed_string_t value1;
+ uint8_t lanes_value;
cmdline_fixed_string_t value2;
};
static int
-parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
+parse_and_check_speed_duplex(char *speedstr, uint8_t lanes, char *duplexstr,
+ uint32_t *speed)
{
+ uint32_t speed_num;
+ char *endptr;
int duplex;
if (!strcmp(duplexstr, "half")) {
@@ -1378,47 +1383,22 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
return -1;
}
- if (!strcmp(speedstr, "10")) {
- *speed = (duplex == RTE_ETH_LINK_HALF_DUPLEX) ?
- RTE_ETH_LINK_SPEED_10M_HD : RTE_ETH_LINK_SPEED_10M;
- } else if (!strcmp(speedstr, "100")) {
- *speed = (duplex == RTE_ETH_LINK_HALF_DUPLEX) ?
- RTE_ETH_LINK_SPEED_100M_HD : RTE_ETH_LINK_SPEED_100M;
- } else {
- if (duplex != RTE_ETH_LINK_FULL_DUPLEX) {
- fprintf(stderr, "Invalid speed/duplex parameters\n");
- return -1;
- }
- if (!strcmp(speedstr, "1000")) {
- *speed = RTE_ETH_LINK_SPEED_1G;
- } else if (!strcmp(speedstr, "2500")) {
- *speed = RTE_ETH_LINK_SPEED_2_5G;
- } else if (!strcmp(speedstr, "5000")) {
- *speed = RTE_ETH_LINK_SPEED_5G;
- } else if (!strcmp(speedstr, "10000")) {
- *speed = RTE_ETH_LINK_SPEED_10G;
- } else if (!strcmp(speedstr, "25000")) {
- *speed = RTE_ETH_LINK_SPEED_25G;
- } else if (!strcmp(speedstr, "40000")) {
- *speed = RTE_ETH_LINK_SPEED_40G;
- } else if (!strcmp(speedstr, "50000")) {
- *speed = RTE_ETH_LINK_SPEED_50G;
- } else if (!strcmp(speedstr, "100000")) {
- *speed = RTE_ETH_LINK_SPEED_100G;
- } else if (!strcmp(speedstr, "200000")) {
- *speed = RTE_ETH_LINK_SPEED_200G;
- } else if (!strcmp(speedstr, "400000")) {
- *speed = RTE_ETH_LINK_SPEED_400G;
- } else if (!strcmp(speedstr, "auto")) {
- *speed = RTE_ETH_LINK_SPEED_AUTONEG;
- } else {
- fprintf(stderr, "Unknown speed parameter\n");
- return -1;
- }
+ if (!strcmp(speedstr, "auto")) {
+ *speed = RTE_ETH_LINK_SPEED_AUTONEG;
+ return 0;
}
- if (*speed != RTE_ETH_LINK_SPEED_AUTONEG)
- *speed |= RTE_ETH_LINK_SPEED_FIXED;
+ speed_num = strtol(speedstr, &endptr, 10);
+ if (*endptr != '\0') {
+ fprintf(stderr, "Unknown speed parameter\n");
+ return -1;
+ }
+
+ *speed = rte_eth_speed_bitflag(speed_num, lanes, duplex);
+ if (*speed == 0) {
+ fprintf(stderr, "param error\n");
+ return -1;
+ }
return 0;
}
@@ -1429,19 +1409,27 @@ cmd_config_speed_all_parsed(void *parsed_result,
__rte_unused void *data)
{
struct cmd_config_speed_all *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
uint32_t link_speed;
portid_t pid;
+ int ret;
if (!all_ports_stopped()) {
fprintf(stderr, "Please stop all ports first\n");
return;
}
- if (parse_and_check_speed_duplex(res->value1, res->value2,
- &link_speed) < 0)
+ if (parse_and_check_speed_duplex(res->value1, res->lanes_value,
+ res->value2, &link_speed) < 0)
return;
RTE_ETH_FOREACH_DEV(pid) {
+ ret = eth_dev_info_get_print_err(pid, &dev_info);
+ if (ret != 0)
+ return;
+ if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_SETTING_LANES) == 0)
+ fprintf(stderr, "The setting lane may not take effect because "
+ "the port (%u) does not support it\n", pid);
ports[pid].dev_conf.link_speeds = link_speed;
}
@@ -1460,6 +1448,11 @@ static cmdline_parse_token_string_t cmd_config_speed_all_item1 =
static cmdline_parse_token_string_t cmd_config_speed_all_value1 =
TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
"10#100#1000#2500#5000#10000#25000#40000#50000#100000#200000#400000#auto");
+static cmdline_parse_token_string_t cmd_config_speed_all_lanes_item =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, lanes_item, "lanes");
+static cmdline_parse_token_num_t cmd_config_speed_all_lanes_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_speed_all, lanes_value,
+ RTE_UINT8);
static cmdline_parse_token_string_t cmd_config_speed_all_item2 =
TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
static cmdline_parse_token_string_t cmd_config_speed_all_value2 =
@@ -1470,14 +1463,16 @@ static cmdline_parse_inst_t cmd_config_speed_all = {
.f = cmd_config_speed_all_parsed,
.data = NULL,
.help_str = "port config all speed "
- "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto duplex "
- "half|full|auto",
+ "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto"
+ " lanes 1|2|4|8 duplex half|full|auto",
.tokens = {
(void *)&cmd_config_speed_all_port,
(void *)&cmd_config_speed_all_keyword,
(void *)&cmd_config_speed_all_all,
(void *)&cmd_config_speed_all_item1,
(void *)&cmd_config_speed_all_value1,
+ (void *)&cmd_config_speed_all_lanes_item,
+ (void *)&cmd_config_speed_all_lanes_value,
(void *)&cmd_config_speed_all_item2,
(void *)&cmd_config_speed_all_value2,
NULL,
@@ -1490,8 +1485,10 @@ struct cmd_config_speed_specific {
cmdline_fixed_string_t keyword;
portid_t id;
cmdline_fixed_string_t item1;
+ cmdline_fixed_string_t lanes_item;
cmdline_fixed_string_t item2;
cmdline_fixed_string_t value1;
+ uint8_t lanes_value;
cmdline_fixed_string_t value2;
};
@@ -1501,7 +1498,9 @@ cmd_config_speed_specific_parsed(void *parsed_result,
__rte_unused void *data)
{
struct cmd_config_speed_specific *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
uint32_t link_speed;
+ int ret;
if (port_id_is_invalid(res->id, ENABLED_WARN))
return;
@@ -1511,8 +1510,15 @@ cmd_config_speed_specific_parsed(void *parsed_result,
return;
}
- if (parse_and_check_speed_duplex(res->value1, res->value2,
- &link_speed) < 0)
+ ret = eth_dev_info_get_print_err(res->id, &dev_info);
+ if (ret != 0)
+ return;
+ if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_SETTING_LANES) == 0)
+ fprintf(stderr, "The setting lane may not take effect because "
+ "the port (%d) does not support it\n", res->id);
+
+ if (parse_and_check_speed_duplex(res->value1, res->lanes_value,
+ res->value2, &link_speed) < 0)
return;
ports[res->id].dev_conf.link_speeds = link_speed;
@@ -1535,6 +1541,12 @@ static cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
static cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
"10#100#1000#2500#5000#10000#25000#40000#50000#100000#200000#400000#auto");
+static cmdline_parse_token_string_t cmd_config_speed_specific_lanes_item =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, lanes_item,
+ "lanes");
+static cmdline_parse_token_num_t cmd_config_speed_specific_lanes_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, lanes_value,
+ RTE_UINT8);
static cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
"duplex");
@@ -1546,14 +1558,16 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
.f = cmd_config_speed_specific_parsed,
.data = NULL,
.help_str = "port config <port_id> speed "
- "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto duplex "
- "half|full|auto",
+ "10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto"
+ " lanes 1|2|4|8 duplex half|full|auto",
.tokens = {
(void *)&cmd_config_speed_specific_port,
(void *)&cmd_config_speed_specific_keyword,
(void *)&cmd_config_speed_specific_id,
(void *)&cmd_config_speed_specific_item1,
(void *)&cmd_config_speed_specific_value1,
+ (void *)&cmd_config_speed_specific_lanes_item,
+ (void *)&cmd_config_speed_specific_lanes_value,
(void *)&cmd_config_speed_specific_item2,
(void *)&cmd_config_speed_specific_value2,
NULL,
@@ -587,39 +587,51 @@ device_infos_display_speeds(uint32_t speed_capa)
if (speed_capa == RTE_ETH_LINK_SPEED_AUTONEG)
printf(" Autonegotiate (all speeds)");
if (speed_capa & RTE_ETH_LINK_SPEED_FIXED)
- printf(" Disable autonegotiate (fixed speed) ");
+ printf(" Disable autonegotiate (fixed speed) /");
if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
- printf(" 10 Mbps half-duplex ");
+ printf(" 10Mbps_1lane_half-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_10M)
- printf(" 10 Mbps full-duplex ");
+ printf(" 10Mbps_1lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
- printf(" 100 Mbps half-duplex ");
+ printf(" 100Mbps_lane_half-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_100M)
- printf(" 100 Mbps full-duplex ");
+ printf(" 100Mbps_1lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_1G)
- printf(" 1 Gbps ");
+ printf(" 1Gbps_1lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
- printf(" 2.5 Gbps ");
+ printf(" 2.5Gbps_1lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_5G)
- printf(" 5 Gbps ");
+ printf(" 5Gbps_1lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_10G)
- printf(" 10 Gbps ");
- if (speed_capa & RTE_ETH_LINK_SPEED_20G)
- printf(" 20 Gbps ");
+ printf(" 10Gbps_1lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_10G_4LANES)
+ printf(" 10Gbps_4lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_20G_2LANES)
+ printf(" 20Gbps_2lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_25G)
- printf(" 25 Gbps ");
- if (speed_capa & RTE_ETH_LINK_SPEED_40G)
- printf(" 40 Gbps ");
+ printf(" 25Gbps_1lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_40G_4LANES)
+ printf(" 40Gbps_4lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_50G)
- printf(" 50 Gbps ");
- if (speed_capa & RTE_ETH_LINK_SPEED_56G)
- printf(" 56 Gbps ");
+ printf(" 50Gbps_1lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_50G_2LANES)
+ printf(" 50Gbps_2lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_56G_4LANES)
+ printf(" 56Gbps_4lane_full-duplex /");
if (speed_capa & RTE_ETH_LINK_SPEED_100G)
- printf(" 100 Gbps ");
- if (speed_capa & RTE_ETH_LINK_SPEED_200G)
- printf(" 200 Gbps ");
- if (speed_capa & RTE_ETH_LINK_SPEED_400G)
- printf(" 400 Gbps ");
+ printf(" 100Gbps_1lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_100G_2LANES)
+ printf(" 100Gbps_2lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_100G_4LANES)
+ printf(" 100Gbps_4lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_200G_4LANES)
+ printf(" 200Gbps_4lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_200G_2LANES)
+ printf(" 200Gbps_2lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_400G_4LANES)
+ printf(" 400Gbps_4lane_full-duplex /");
+ if (speed_capa & RTE_ETH_LINK_SPEED_400G_8LANES)
+ printf(" 400Gbps_8lane_full-duplex /");
}
void
@@ -828,6 +840,10 @@ 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 (link.link_lanes == 0)
+ printf("Link lanes: unknown\n");
+ else
+ printf("Link lanes: %u\n", link.link_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) ?
@@ -79,6 +79,7 @@ New Features
* **Support setting lanes for ethdev.**
* Support setting lanes by extended ``RTE_ETH_LINK_SPEED_*``.
* Added function to convert bitmap flag to the struct of link speed info.
+ ``rte_eth_speed_capa_to_info()``
* **Added hash calculation of an encapsulated packet as done by the HW.**
@@ -190,6 +190,7 @@ For example:
memory allocation on the socket: 0
Link status: up
Link speed: 40000 Mbps
+ Link lanes: 4
Link duplex: full-duplex
Promiscuous mode: enabled
Allmulticast mode: disabled
@@ -2065,7 +2066,7 @@ port config - speed
Set the speed and duplex mode for all ports or a specific port::
testpmd> port config (port_id|all) speed (10|100|1000|2500|5000|10000|25000|40000|50000|100000|200000|400000|auto) \
- duplex (half|full|auto)
+ lanes 1|2|4|8 duplex (half|full|auto)
port config - queues/descriptors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~