DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] app/test-pmd: add explicit parameter for fixed link speeds
@ 2026-11-03 15:50 Bruce Richardson
  2026-11-04 12:29 ` Stephen Hemminger
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Bruce Richardson @ 2026-11-03 15:50 UTC (permalink / raw)
  To: dev; +Cc: stephen, Bruce Richardson, Aman Singh

When a particular speed was specified for a port in testpmd, the flags
passed to the underlying API call always included the
RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
bitmap when setting speeds, and is used to disable autonegotiation.
It's possible to have a link report only a single speed while
still have negotiation enabled, so testpmd needs to be extended to
support setting a speed both with and without the flag.

This patch does so by adding an optional "fixed" keyword after the speed
specified by the user. The presence or absense of the keyword adjusts
the presence or absense of the FIXED speed bit in the ethdev
configuration structure "rte_eth_conf.link_speeds" bitmap.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test-pmd/cmdline.c                      | 69 ++++++++++++++++++---
 doc/guides/rel_notes/release_26_11.rst      |  8 +++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 10 ++-
 3 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 51078a2a73..ee86f75c09 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -726,8 +726,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id|all)"
 			" speed (10|100|1000|2500|5000|10000|25000|40000|50000|"
 			"100000|200000|400000|800000|auto)"
-			" duplex (half|full|auto)\n"
-			"    Set speed and duplex for all ports or port_id\n\n"
+			" [fixed] duplex (half|full|auto)\n"
+			"    Set speed and duplex; fixed disables link autonegotiation\n\n"
 
 			"port config (port_id|all) loopback (mode)\n"
 			"    Set loopback mode for all ports or port_id\n\n"
@@ -1395,10 +1395,11 @@ struct cmd_config_speed_all {
 	cmdline_fixed_string_t item2;
 	cmdline_fixed_string_t value1;
 	cmdline_fixed_string_t value2;
+	cmdline_fixed_string_t fixed;
 };
 
 static int
-parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
+parse_and_check_speed_duplex(char *speedstr, char *duplexstr, bool fixed, uint32_t *speed)
 {
 
 	int duplex;
@@ -1455,8 +1456,13 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 		}
 	}
 
-	if (*speed != RTE_ETH_LINK_SPEED_AUTONEG)
+	if (fixed) {
+		if (*speed == RTE_ETH_LINK_SPEED_AUTONEG) {
+			fprintf(stderr, "A fixed link requires a specific speed\n");
+			return -1;
+		}
 		*speed |= RTE_ETH_LINK_SPEED_FIXED;
+	}
 
 	return 0;
 }
@@ -1464,7 +1470,7 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 static void
 cmd_config_speed_all_parsed(void *parsed_result,
 			__rte_unused struct cmdline *cl,
-			__rte_unused void *data)
+			void *data)
 {
 	struct cmd_config_speed_all *res = parsed_result;
 	uint32_t link_speed;
@@ -1476,7 +1482,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	if (parse_and_check_speed_duplex(res->value1, res->value2,
-			&link_speed) < 0)
+			data != NULL, &link_speed) < 0)
 		return;
 
 	RTE_ETH_FOREACH_DEV(pid) {
@@ -1504,6 +1510,8 @@ static cmdline_parse_token_string_t cmd_config_speed_all_item2 =
 static cmdline_parse_token_string_t cmd_config_speed_all_value2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2,
 						"half#full#auto");
+static cmdline_parse_token_string_t cmd_config_speed_all_fixed_token =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, fixed, "fixed");
 
 static cmdline_parse_inst_t cmd_config_speed_all = {
 	.f = cmd_config_speed_all_parsed,
@@ -1524,6 +1532,26 @@ static cmdline_parse_inst_t cmd_config_speed_all = {
 	},
 };
 
+static cmdline_parse_inst_t cmd_config_speed_all_fixed = {
+	.f = cmd_config_speed_all_parsed,
+	.data = &cmd_config_speed_all_fixed,
+	.help_str = "port config all speed "
+		"10|100|1000|2500|5000|10000|25000|40000|50000|"
+		"100000|200000|400000|800000 "
+		"fixed 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_fixed_token,
+		(void *)&cmd_config_speed_all_item2,
+		(void *)&cmd_config_speed_all_value2,
+		NULL,
+	},
+};
+
 /* *** configure speed for specific port *** */
 struct cmd_config_speed_specific {
 	cmdline_fixed_string_t port;
@@ -1533,12 +1561,13 @@ struct cmd_config_speed_specific {
 	cmdline_fixed_string_t item2;
 	cmdline_fixed_string_t value1;
 	cmdline_fixed_string_t value2;
+	cmdline_fixed_string_t fixed;
 };
 
 static void
 cmd_config_speed_specific_parsed(void *parsed_result,
 				__rte_unused struct cmdline *cl,
-				__rte_unused void *data)
+				void *data)
 {
 	struct cmd_config_speed_specific *res = parsed_result;
 	uint32_t link_speed;
@@ -1552,7 +1581,7 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 	}
 
 	if (parse_and_check_speed_duplex(res->value1, res->value2,
-			&link_speed) < 0)
+			data != NULL, &link_speed) < 0)
 		return;
 
 	ports[res->id].dev_conf.link_speeds = link_speed;
@@ -1582,6 +1611,8 @@ static cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
 static cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2,
 							"half#full#auto");
+static cmdline_parse_token_string_t cmd_config_speed_specific_fixed_token =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, fixed, "fixed");
 
 static cmdline_parse_inst_t cmd_config_speed_specific = {
 	.f = cmd_config_speed_specific_parsed,
@@ -1602,6 +1633,26 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
 	},
 };
 
+static cmdline_parse_inst_t cmd_config_speed_specific_fixed = {
+	.f = cmd_config_speed_specific_parsed,
+	.data = &cmd_config_speed_specific_fixed,
+	.help_str = "port config <port_id> speed "
+		"10|100|1000|2500|5000|10000|25000|40000|50000|"
+		"100000|200000|400000|800000 "
+		"fixed 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_fixed_token,
+		(void *)&cmd_config_speed_specific_item2,
+		(void *)&cmd_config_speed_specific_value2,
+		NULL,
+	},
+};
+
 static int
 parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
 {
@@ -14357,7 +14408,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	&cmd_operate_detach_device,
 	&cmd_set_port_setup_on,
 	&cmd_config_speed_all,
+	&cmd_config_speed_all_fixed,
 	&cmd_config_speed_specific,
+	&cmd_config_speed_specific_fixed,
 	&cmd_config_speed_lanes_all,
 	&cmd_config_speed_lanes_specific,
 	&cmd_show_speed_lanes,
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 8ca8379cc6..e7ed2ca13f 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -341,6 +341,14 @@ New Features
   for compatibility with the ``lib/bpf`` execution context.
 
 
+* **Added explicit fixed-speed selection in testpmd.**
+
+  Added an optional ``fixed`` keyword to the port speed configuration command.
+  Numeric speeds now leave link autonegotiation enabled unless ``fixed`` is specified.
+  Add ``fixed`` between the speed value and ``duplex`` to disable link autonegotiation,
+  preserving the previous behavior.
+
+
 Removed Items
 -------------
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a967bbef76..0ab52a8af0 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2167,7 +2167,15 @@ 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|800000|auto) \
-            duplex (half|full|auto)
+            [fixed] duplex (half|full|auto)
+
+Without ``fixed``, the selected speed is advertised with link autonegotiation enabled.
+With ``fixed``, link autonegotiation is disabled and the selected speed is forced.
+The ``auto`` speed advertises all supported speeds and cannot be combined with ``fixed``.
+The ``auto`` duplex value selects full duplex; it does not control link autonegotiation.
+Support for these settings depends on the driver and hardware.
+
+
 
 port config - queues/descriptors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
2.55.0


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

* Re: [PATCH] app/test-pmd: add explicit parameter for fixed link speeds
  2026-11-03 15:50 [PATCH] app/test-pmd: add explicit parameter for fixed link speeds Bruce Richardson
@ 2026-11-04 12:29 ` Stephen Hemminger
  2026-11-04 13:39   ` Bruce Richardson
  2026-11-09 15:59 ` [PATCH v2] app/testpmd: add explicit link autonegotiation control Bruce Richardson
  2026-11-10 12:16 ` [PATCH v3] " Bruce Richardson
  2 siblings, 1 reply; 7+ messages in thread
From: Stephen Hemminger @ 2026-11-04 12:29 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, Aman Singh

On Tue,  3 Nov 2026 15:50:33 +0000
Bruce Richardson <bruce.richardson@intel.com> wrote:

> When a particular speed was specified for a port in testpmd, the flags
> passed to the underlying API call always included the
> RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
> bitmap when setting speeds, and is used to disable autonegotiation.
> It's possible to have a link report only a single speed while
> still have negotiation enabled, so testpmd needs to be extended to
> support setting a speed both with and without the flag.
> 
> This patch does so by adding an optional "fixed" keyword after the speed
> specified by the user. The presence or absense of the keyword adjusts
> the presence or absense of the FIXED speed bit in the ethdev
> configuration structure "rte_eth_conf.link_speeds" bitmap.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---

In general it looked ok to me. But I would like testpmd and ethtool have same syntax
to follow the principle of "least surprise" for users.

The AI review with its issues and that encouragement was:

Review: [PATCH] app/test-pmd: add explicit parameter for fixed link
speeds (patchwork 172601)

Applies to main (26.11-rc2), builds with -Dwerror=true.

Warning (should fix)
--------------------

1. Syntax should follow ethtool rather than invent "fixed".

   ethtool has autoneg as a separate on/off setting:

     ethtool -s eth0 speed 10000 duplex full autoneg off

   With autoneg on, a given speed/duplex limits what gets advertised
   (the kernel's ethnl_auto_linkmodes()). That is the same as this
   patch's default, so the semantics are right; only the keyword and
   its position need to change:

     port config (port_id|all) speed (...|auto) duplex (half|full|auto)
         [autoneg (on|off)]

   autoneg off   -> set RTE_ETH_LINK_SPEED_FIXED
   autoneg on    -> clear it
   absent        -> leave autoneg alone. ethtool keeps the current
                    setting, so keep the FIXED bit already in
                    ports[pid].dev_conf.link_speeds. The default
                    dev_conf is autoneg, so a fresh port behaves as
                    posted.
   speed auto + autoneg off -> error, as now.

   Putting the optional tokens last leaves the existing
   "speed N duplex D" prefix alone. Users who know ethtool can guess
   it. Untested sketch for the all-ports case:

     struct cmd_config_speed_all {
     	...
     	cmdline_fixed_string_t item3;	/* "autoneg" */
     	cmdline_fixed_string_t value3;	/* "on#off" */
     };

     static cmdline_parse_token_string_t cmd_config_speed_all_item3 =
     	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item3,
     				 "autoneg");
     static cmdline_parse_token_string_t cmd_config_speed_all_value3 =
     	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value3,
     				 "on#off");

   The second cmdline_parse_inst_t still needs the two extra tokens.
   In the handler, res->item3[0] == '\0' means autoneg was not given.
   The cmdline library zeroes the result buffer, so the
   ".data = &cmd_config_speed_all_fixed" self-reference used as a flag
   can go. Same for the per-port instance.

2. Default behaviour of an existing command changes silently.

   Before this patch "port config 0 speed 10000 duplex full" set
   RTE_ETH_LINK_SPEED_FIXED. After it, the same command leaves autoneg
   enabled and advertises only 10G. Existing scripts and test plans
   (DTS, vendor validation) keep parsing but now do something
   different. Whether the user sees a difference depends on the PMD.

   The new default is correct (it matches ethtool), but the release
   note puts it under New Features. Give the behaviour change its own
   sentence, e.g.:

     Speed settings no longer disable autonegotiation by default;
     add ``autoneg off`` to force the speed.

3. --eth-link-speed is now inconsistent with the runtime command.

   parse_link_speed() in parameters.c still starts from
   RTE_ETH_LINK_SPEED_FIXED, and run_app.rst calls it "a forced link
   speed". So the startup option forces the speed and the runtime
   command no longer does. Either add a matching option (e.g.
   --eth-link-autoneg=on|off), or at minimum document it in the speed
   command section:

     The ``--eth-link-speed`` command line option always disables
     autonegotiation.

Info (consider)
---------------

4. testpmd_funcs.rst: the patch leaves three blank lines before
   "port config - queues/descriptors"; one is enough. "Support for
   these settings depends on the driver and hardware." adds nothing
   and can go.

5. Commit message: "absense" (twice) -> "absence"; "still have
   negotiation enabled" -> "still have autonegotiation enabled".

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

* Re: [PATCH] app/test-pmd: add explicit parameter for fixed link speeds
  2026-11-04 12:29 ` Stephen Hemminger
@ 2026-11-04 13:39   ` Bruce Richardson
  0 siblings, 0 replies; 7+ messages in thread
From: Bruce Richardson @ 2026-11-04 13:39 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Aman Singh

On Wed, Nov 04, 2026 at 01:29:49PM +0100, Stephen Hemminger wrote:
> On Tue,  3 Nov 2026 15:50:33 +0000
> Bruce Richardson <bruce.richardson@intel.com> wrote:
> 
> > When a particular speed was specified for a port in testpmd, the flags
> > passed to the underlying API call always included the
> > RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
> > bitmap when setting speeds, and is used to disable autonegotiation.
> > It's possible to have a link report only a single speed while
> > still have negotiation enabled, so testpmd needs to be extended to
> > support setting a speed both with and without the flag.
> > 
> > This patch does so by adding an optional "fixed" keyword after the speed
> > specified by the user. The presence or absense of the keyword adjusts
> > the presence or absense of the FIXED speed bit in the ethdev
> > configuration structure "rte_eth_conf.link_speeds" bitmap.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > ---
> 
> In general it looked ok to me. But I would like testpmd and ethtool have same syntax
> to follow the principle of "least surprise" for users.
> 
> The AI review with its issues and that encouragement was:
> 
> Review: [PATCH] app/test-pmd: add explicit parameter for fixed link
> speeds (patchwork 172601)
> 
> Applies to main (26.11-rc2), builds with -Dwerror=true.
> 
> Warning (should fix)
> --------------------
> 
> 1. Syntax should follow ethtool rather than invent "fixed".
> 
>    ethtool has autoneg as a separate on/off setting:
> 
>      ethtool -s eth0 speed 10000 duplex full autoneg off
> 
>    With autoneg on, a given speed/duplex limits what gets advertised
>    (the kernel's ethnl_auto_linkmodes()). That is the same as this
>    patch's default, so the semantics are right; only the keyword and
>    its position need to change:
> 
>      port config (port_id|all) speed (...|auto) duplex (half|full|auto)
>          [autoneg (on|off)]
> 
>    autoneg off   -> set RTE_ETH_LINK_SPEED_FIXED
>    autoneg on    -> clear it
>    absent        -> leave autoneg alone. ethtool keeps the current
>                     setting, so keep the FIXED bit already in
>                     ports[pid].dev_conf.link_speeds. The default
>                     dev_conf is autoneg, so a fresh port behaves as
>                     posted.
>    speed auto + autoneg off -> error, as now.
> 
>    Putting the optional tokens last leaves the existing
>    "speed N duplex D" prefix alone. Users who know ethtool can guess
>    it. Untested sketch for the all-ports case:
> 
>      struct cmd_config_speed_all {
>      	...
>      	cmdline_fixed_string_t item3;	/* "autoneg" */
>      	cmdline_fixed_string_t value3;	/* "on#off" */
>      };
> 
>      static cmdline_parse_token_string_t cmd_config_speed_all_item3 =
>      	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item3,
>      				 "autoneg");
>      static cmdline_parse_token_string_t cmd_config_speed_all_value3 =
>      	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value3,
>      				 "on#off");
> 
>    The second cmdline_parse_inst_t still needs the two extra tokens.
>    In the handler, res->item3[0] == '\0' means autoneg was not given.
>    The cmdline library zeroes the result buffer, so the
>    ".data = &cmd_config_speed_all_fixed" self-reference used as a flag
>    can go. Same for the per-port instance.
> 

Ack, will rework to use the autoneg syntax.

> 2. Default behaviour of an existing command changes silently.
> 
>    Before this patch "port config 0 speed 10000 duplex full" set
>    RTE_ETH_LINK_SPEED_FIXED. After it, the same command leaves autoneg
>    enabled and advertises only 10G. Existing scripts and test plans
>    (DTS, vendor validation) keep parsing but now do something
>    different. Whether the user sees a difference depends on the PMD.
> 
>    The new default is correct (it matches ethtool), but the release
>    note puts it under New Features. Give the behaviour change its own
>    sentence, e.g.:
> 
>      Speed settings no longer disable autonegotiation by default;
>      add ``autoneg off`` to force the speed.
> 

This becomes moot if we rework the syntax. However, when making the
original change, I had AI do an analysis - only 5 drivers in tree actually
take account of the FIXED flag in turning on/off autoneg. Hopefully, adding
testpmd support will allow that list to increase, because nearly all
drivers just ignore it.

Interestingly, AI also flagged that there is a further set of 5 drivers
which would reject the existing testpmd command as it currently stands
since they reject any speed selection with the FIXED flag set.

> 3. --eth-link-speed is now inconsistent with the runtime command.
> 
>    parse_link_speed() in parameters.c still starts from
>    RTE_ETH_LINK_SPEED_FIXED, and run_app.rst calls it "a forced link
>    speed". So the startup option forces the speed and the runtime
>    command no longer does. Either add a matching option (e.g.
>    --eth-link-autoneg=on|off), or at minimum document it in the speed
>    command section:
> 
>      The ``--eth-link-speed`` command line option always disables
>      autonegotiation.
> 

If we rework this also becomes largely moot, though the option of a
non-fixed link speed flag is a possibility for the future.

> Info (consider)
> ---------------
> 
> 4. testpmd_funcs.rst: the patch leaves three blank lines before
>    "port config - queues/descriptors"; one is enough. "Support for
>    these settings depends on the driver and hardware." adds nothing
>    and can go.
> 
> 5. Commit message: "absense" (twice) -> "absence"; "still have
>    negotiation enabled" -> "still have autonegotiation enabled".

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

* [PATCH v2] app/testpmd: add explicit link autonegotiation control
  2026-11-03 15:50 [PATCH] app/test-pmd: add explicit parameter for fixed link speeds Bruce Richardson
  2026-11-04 12:29 ` Stephen Hemminger
@ 2026-11-09 15:59 ` Bruce Richardson
  2026-11-09 17:45   ` Stephen Hemminger
  2026-11-10 12:16 ` [PATCH v3] " Bruce Richardson
  2 siblings, 1 reply; 7+ messages in thread
From: Bruce Richardson @ 2026-11-09 15:59 UTC (permalink / raw)
  To: dev; +Cc: stephen, Bruce Richardson

When a particular speed was specified for a port in testpmd, the flags
passed to the underlying API call always included the
RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
bitmap when setting speeds, and is used to disable autonegotiation.
It's possible to have a link report only a single speed while
still have negotiation enabled, so testpmd needs to be extended to
support setting a speed both with and without the flag.

This patch does so by adding optional "autoneg on|off" setting after
speed and duplex settings specified by the user. This new option adjusts
the presence or absence of the FIXED speed bit in the ethdev
configuration structure "rte_eth_conf.link_speeds" bitmap. For backward
compatibility, the default value is "autoneg off" for fixed speeds if
not specified, meaning that the RTE_ETH_LINK_SPEED_FIXED flag is set on
the speed value by default.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
V2:
* changed syntax to more closely match that of ethtool, adding
  autoneg on|off at the end of the command.
* increased compatibility by ensuring that when no autoneg value is
  specified, a numeric speed sets the fixed flag (autoneg off), while an
  "auto" speed keeps autoneg on.
---
 app/test-pmd/cmdline.c                      | 90 +++++++++++++++++++--
 doc/guides/rel_notes/release_26_11.rst      |  6 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +-
 3 files changed, 95 insertions(+), 9 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 51078a2a73..676ed18aca 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -726,8 +726,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id|all)"
 			" speed (10|100|1000|2500|5000|10000|25000|40000|50000|"
 			"100000|200000|400000|800000|auto)"
-			" duplex (half|full|auto)\n"
-			"    Set speed and duplex for all ports or port_id\n\n"
+			" duplex (half|full|auto) [autoneg (on|off)]\n"
+			"    Set speed and duplex; optionally enable or disable link autonegotiation\n\n"
 
 			"port config (port_id|all) loopback (mode)\n"
 			"    Set loopback mode for all ports or port_id\n\n"
@@ -1395,10 +1395,21 @@ struct cmd_config_speed_all {
 	cmdline_fixed_string_t item2;
 	cmdline_fixed_string_t value1;
 	cmdline_fixed_string_t value2;
+	cmdline_fixed_string_t autoneg;
+	cmdline_fixed_string_t autoneg_value;
 };
 
+static uint32_t
+link_speed_fixed_bit(const char *speed, const char *autoneg)
+{
+	if (autoneg == NULL)
+		return strcmp(speed, "auto") == 0 ? 0 : RTE_ETH_LINK_SPEED_FIXED;
+
+	return strcmp(autoneg, "off") == 0 ? RTE_ETH_LINK_SPEED_FIXED : 0;
+}
+
 static int
-parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
+parse_and_check_speed_duplex(char *speedstr, char *duplexstr, bool fixed, uint32_t *speed)
 {
 
 	int duplex;
@@ -1455,8 +1466,13 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 		}
 	}
 
-	if (*speed != RTE_ETH_LINK_SPEED_AUTONEG)
+	if (fixed) {
+		if (*speed == RTE_ETH_LINK_SPEED_AUTONEG) {
+			fprintf(stderr, "A fixed link requires a specific speed\n");
+			return -1;
+		}
 		*speed |= RTE_ETH_LINK_SPEED_FIXED;
+	}
 
 	return 0;
 }
@@ -1464,9 +1480,11 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 static void
 cmd_config_speed_all_parsed(void *parsed_result,
 			__rte_unused struct cmdline *cl,
-			__rte_unused void *data)
+			void *data)
 {
 	struct cmd_config_speed_all *res = parsed_result;
+	/* data is used to identify command variant with/without explicit autoneg setting */
+	const char *autoneg = data != NULL ? res->autoneg_value : NULL;
 	uint32_t link_speed;
 	portid_t pid;
 
@@ -1476,7 +1494,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	if (parse_and_check_speed_duplex(res->value1, res->value2,
-			&link_speed) < 0)
+			link_speed_fixed_bit(res->value1, autoneg) != 0, &link_speed) < 0)
 		return;
 
 	RTE_ETH_FOREACH_DEV(pid) {
@@ -1504,6 +1522,10 @@ static cmdline_parse_token_string_t cmd_config_speed_all_item2 =
 static cmdline_parse_token_string_t cmd_config_speed_all_value2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2,
 						"half#full#auto");
+static cmdline_parse_token_string_t cmd_config_speed_all_autoneg_token =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, autoneg, "autoneg");
+static cmdline_parse_token_string_t cmd_config_speed_all_autoneg_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, autoneg_value, "on#off");
 
 static cmdline_parse_inst_t cmd_config_speed_all = {
 	.f = cmd_config_speed_all_parsed,
@@ -1524,6 +1546,27 @@ static cmdline_parse_inst_t cmd_config_speed_all = {
 	},
 };
 
+static cmdline_parse_inst_t cmd_config_speed_all_autoneg = {
+	.f = cmd_config_speed_all_parsed,
+	.data = &cmd_config_speed_all_autoneg,
+	.help_str = "port config all speed "
+		"10|100|1000|2500|5000|10000|25000|40000|50000|"
+		"100000|200000|400000|800000|auto "
+		"duplex half|full|auto autoneg on|off",
+	.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_item2,
+		(void *)&cmd_config_speed_all_value2,
+		(void *)&cmd_config_speed_all_autoneg_token,
+		(void *)&cmd_config_speed_all_autoneg_value,
+		NULL,
+	},
+};
+
 /* *** configure speed for specific port *** */
 struct cmd_config_speed_specific {
 	cmdline_fixed_string_t port;
@@ -1533,14 +1576,18 @@ struct cmd_config_speed_specific {
 	cmdline_fixed_string_t item2;
 	cmdline_fixed_string_t value1;
 	cmdline_fixed_string_t value2;
+	cmdline_fixed_string_t autoneg;
+	cmdline_fixed_string_t autoneg_value;
 };
 
 static void
 cmd_config_speed_specific_parsed(void *parsed_result,
 				__rte_unused struct cmdline *cl,
-				__rte_unused void *data)
+				void *data)
 {
 	struct cmd_config_speed_specific *res = parsed_result;
+	/* data is used to identify command variant with/without explicit autoneg setting */
+	const char *autoneg = data != NULL ? res->autoneg_value : NULL;
 	uint32_t link_speed;
 
 	if (port_id_is_invalid(res->id, ENABLED_WARN))
@@ -1552,7 +1599,7 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 	}
 
 	if (parse_and_check_speed_duplex(res->value1, res->value2,
-			&link_speed) < 0)
+			link_speed_fixed_bit(res->value1, autoneg) != 0, &link_speed) < 0)
 		return;
 
 	ports[res->id].dev_conf.link_speeds = link_speed;
@@ -1582,6 +1629,10 @@ static cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
 static cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2,
 							"half#full#auto");
+static cmdline_parse_token_string_t cmd_config_speed_specific_autoneg_token =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, autoneg, "autoneg");
+static cmdline_parse_token_string_t cmd_config_speed_specific_autoneg_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, autoneg_value, "on#off");
 
 static cmdline_parse_inst_t cmd_config_speed_specific = {
 	.f = cmd_config_speed_specific_parsed,
@@ -1602,6 +1653,27 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
 	},
 };
 
+static cmdline_parse_inst_t cmd_config_speed_specific_autoneg = {
+	.f = cmd_config_speed_specific_parsed,
+	.data = &cmd_config_speed_specific_autoneg,
+	.help_str = "port config <port_id> speed "
+		"10|100|1000|2500|5000|10000|25000|40000|50000|"
+		"100000|200000|400000|800000|auto "
+		"duplex half|full|auto autoneg on|off",
+	.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_item2,
+		(void *)&cmd_config_speed_specific_value2,
+		(void *)&cmd_config_speed_specific_autoneg_token,
+		(void *)&cmd_config_speed_specific_autoneg_value,
+		NULL,
+	},
+};
+
 static int
 parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
 {
@@ -14357,7 +14429,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	&cmd_operate_detach_device,
 	&cmd_set_port_setup_on,
 	&cmd_config_speed_all,
+	&cmd_config_speed_all_autoneg,
 	&cmd_config_speed_specific,
+	&cmd_config_speed_specific_autoneg,
 	&cmd_config_speed_lanes_all,
 	&cmd_config_speed_lanes_specific,
 	&cmd_show_speed_lanes,
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 8ca8379cc6..29fccf09e3 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -340,6 +340,12 @@ New Features
   Added ``dpdk-validate-bpf`` tool to pre-validate eBPF programs
   for compatibility with the ``lib/bpf`` execution context.
 
+* **Added explicit link autonegotiation control in testpmd.**
+
+  Added an optional ``autoneg on|off`` setting after ``duplex`` in the port speed configuration command.
+  For compatibility with older behavior, if unspecified,
+  auto-negotiation is disabled by default for numeric speeds, and enabled for "auto" speed selection.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a967bbef76..6bac4d2763 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2167,7 +2167,13 @@ 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|800000|auto) \
-            duplex (half|full|auto)
+            duplex (half|full|auto) [autoneg (on|off)]
+
+With ``autoneg on``, the selected speed is advertised with link autonegotiation enabled.
+With ``autoneg off``, link autonegotiation is disabled and the selected speed is forced.
+If ``autoneg`` parameter is omitted for a numeric speed, link autonegotiation is disabled.
+The ``auto`` speed advertises all supported speeds and enables link autonegotiation if ``autoneg`` is omitted.
+NOTE: Combining ``auto`` speed with ``autoneg off`` is an error.
 
 port config - queues/descriptors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
2.55.0


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

* Re: [PATCH v2] app/testpmd: add explicit link autonegotiation control
  2026-11-09 15:59 ` [PATCH v2] app/testpmd: add explicit link autonegotiation control Bruce Richardson
@ 2026-11-09 17:45   ` Stephen Hemminger
  0 siblings, 0 replies; 7+ messages in thread
From: Stephen Hemminger @ 2026-11-09 17:45 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Mon,  9 Nov 2026 15:59:35 +0000
Bruce Richardson <bruce.richardson@intel.com> wrote:

> When a particular speed was specified for a port in testpmd, the flags
> passed to the underlying API call always included the
> RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
> bitmap when setting speeds, and is used to disable autonegotiation.
> It's possible to have a link report only a single speed while
> still have negotiation enabled, so testpmd needs to be extended to
> support setting a speed both with and without the flag.
> 
> This patch does so by adding optional "autoneg on|off" setting after
> speed and duplex settings specified by the user. This new option adjusts
> the presence or absence of the FIXED speed bit in the ethdev
> configuration structure "rte_eth_conf.link_speeds" bitmap. For backward
> compatibility, the default value is "autoneg off" for fixed speeds if
> not specified, meaning that the RTE_ETH_LINK_SPEED_FIXED flag is set on
> the speed value by default.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
> V2:
> * changed syntax to more closely match that of ethtool, adding
>   autoneg on|off at the end of the command.
> * increased compatibility by ensuring that when no autoneg value is
>   specified, a numeric speed sets the fixed flag (autoneg off), while an
>   "auto" speed keeps autoneg on.
> ---

Looked ok to me, but AI decided that it was pickier than me.

Review: [PATCH v2] app/testpmd: add explicit link autonegotiation control

Applied on 26.11-rc2, testpmd builds with -Dwerror=true. Parser
behaviour checked against lib/cmdline: the 7-token and 9-token
instances share a prefix, but match_inst() rejects the short
instance when trailing tokens remain, so there is no ambiguity.
Semantics match rte_ethdev.h (FIXED is bit 0, AUTONEG is 0).

Warning
-------

link_speed_fixed_bit() returns a uint32_t bit, but both callers
immediately reduce it to bool:

	link_speed_fixed_bit(res->value1, autoneg) != 0, &link_speed) < 0)

Make it a predicate and drop the "!= 0" at both call sites:

	static bool
	link_speed_is_fixed(const char *speed, const char *autoneg)
	{
		if (autoneg == NULL)
			return strcmp(speed, "auto") != 0;

		return strcmp(autoneg, "off") == 0;
	}

	if (parse_and_check_speed_duplex(res->value1, res->value2,
			link_speed_is_fixed(res->value1, autoneg), &link_speed) < 0)

Info
----

testpmd_funcs.rst: "NOTE: Combining ``auto`` speed with ``autoneg
off`` is an error." is plain text. The file uses the ``.. note::``
directive everywhere else (17 instances); use it here too.

Review-Result: WARNING

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

* [PATCH v3] app/testpmd: add explicit link autonegotiation control
  2026-11-03 15:50 [PATCH] app/test-pmd: add explicit parameter for fixed link speeds Bruce Richardson
  2026-11-04 12:29 ` Stephen Hemminger
  2026-11-09 15:59 ` [PATCH v2] app/testpmd: add explicit link autonegotiation control Bruce Richardson
@ 2026-11-10 12:16 ` Bruce Richardson
  2026-11-10 16:59   ` Stephen Hemminger
  2 siblings, 1 reply; 7+ messages in thread
From: Bruce Richardson @ 2026-11-10 12:16 UTC (permalink / raw)
  To: dev; +Cc: stephen, Bruce Richardson

When a particular speed was specified for a port in testpmd, the flags
passed to the underlying API call always included the
RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
bitmap when setting speeds, and is used to disable autonegotiation.
It's possible to have a link report only a single speed while
still have negotiation enabled, so testpmd needs to be extended to
support setting a speed both with and without the flag.

This patch does so by adding optional "autoneg on|off" setting after
speed and duplex settings specified by the user. This new option adjusts
the presence or absence of the FIXED speed bit in the ethdev
configuration structure "rte_eth_conf.link_speeds" bitmap. For backward
compatibility, the default value is "autoneg off" for fixed speeds if
not specified, meaning that the RTE_ETH_LINK_SPEED_FIXED flag is set on
the speed value by default.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
V3:
* change type of new function to bool from uint32_t since value is only
  used as a flag
* Use proper ".. note::" syntax for newly added note in the testpmd docs

V2:
* changed syntax to more closely match that of ethtool, adding
  autoneg on|off at the end of the command.
* increased compatibility by ensuring that when no autoneg value is
  specified, a numeric speed sets the fixed flag (autoneg off), while an
  "auto" speed keeps autoneg on.
---
 app/test-pmd/cmdline.c                      | 91 +++++++++++++++++++--
 doc/guides/rel_notes/release_26_11.rst      |  6 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 11 ++-
 3 files changed, 99 insertions(+), 9 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 51078a2a73..cdee12a507 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -726,8 +726,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id|all)"
 			" speed (10|100|1000|2500|5000|10000|25000|40000|50000|"
 			"100000|200000|400000|800000|auto)"
-			" duplex (half|full|auto)\n"
-			"    Set speed and duplex for all ports or port_id\n\n"
+			" duplex (half|full|auto) [autoneg (on|off)]\n"
+			"    Set speed and duplex; optionally enable or disable link autonegotiation\n\n"
 
 			"port config (port_id|all) loopback (mode)\n"
 			"    Set loopback mode for all ports or port_id\n\n"
@@ -1395,10 +1395,22 @@ struct cmd_config_speed_all {
 	cmdline_fixed_string_t item2;
 	cmdline_fixed_string_t value1;
 	cmdline_fixed_string_t value2;
+	cmdline_fixed_string_t autoneg;
+	cmdline_fixed_string_t autoneg_value;
 };
 
+static bool
+link_speed_is_fixed(const char *speed, const char *autoneg)
+{
+	if (autoneg == NULL)
+		/* if no flag specified, set fixed speed if speed is not "auto" */
+		return strcmp(speed, "auto") != 0;
+
+	return strcmp(autoneg, "off") == 0;
+}
+
 static int
-parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
+parse_and_check_speed_duplex(char *speedstr, char *duplexstr, bool fixed, uint32_t *speed)
 {
 
 	int duplex;
@@ -1455,8 +1467,13 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 		}
 	}
 
-	if (*speed != RTE_ETH_LINK_SPEED_AUTONEG)
+	if (fixed) {
+		if (*speed == RTE_ETH_LINK_SPEED_AUTONEG) {
+			fprintf(stderr, "A fixed link requires a specific speed\n");
+			return -1;
+		}
 		*speed |= RTE_ETH_LINK_SPEED_FIXED;
+	}
 
 	return 0;
 }
@@ -1464,9 +1481,11 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 static void
 cmd_config_speed_all_parsed(void *parsed_result,
 			__rte_unused struct cmdline *cl,
-			__rte_unused void *data)
+			void *data)
 {
 	struct cmd_config_speed_all *res = parsed_result;
+	/* data is used to identify command variant with/without explicit autoneg setting */
+	const char *autoneg = data != NULL ? res->autoneg_value : NULL;
 	uint32_t link_speed;
 	portid_t pid;
 
@@ -1476,7 +1495,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	}
 
 	if (parse_and_check_speed_duplex(res->value1, res->value2,
-			&link_speed) < 0)
+			link_speed_is_fixed(res->value1, autoneg), &link_speed) < 0)
 		return;
 
 	RTE_ETH_FOREACH_DEV(pid) {
@@ -1504,6 +1523,10 @@ static cmdline_parse_token_string_t cmd_config_speed_all_item2 =
 static cmdline_parse_token_string_t cmd_config_speed_all_value2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2,
 						"half#full#auto");
+static cmdline_parse_token_string_t cmd_config_speed_all_autoneg_token =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, autoneg, "autoneg");
+static cmdline_parse_token_string_t cmd_config_speed_all_autoneg_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, autoneg_value, "on#off");
 
 static cmdline_parse_inst_t cmd_config_speed_all = {
 	.f = cmd_config_speed_all_parsed,
@@ -1524,6 +1547,27 @@ static cmdline_parse_inst_t cmd_config_speed_all = {
 	},
 };
 
+static cmdline_parse_inst_t cmd_config_speed_all_autoneg = {
+	.f = cmd_config_speed_all_parsed,
+	.data = &cmd_config_speed_all_autoneg,
+	.help_str = "port config all speed "
+		"10|100|1000|2500|5000|10000|25000|40000|50000|"
+		"100000|200000|400000|800000|auto "
+		"duplex half|full|auto autoneg on|off",
+	.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_item2,
+		(void *)&cmd_config_speed_all_value2,
+		(void *)&cmd_config_speed_all_autoneg_token,
+		(void *)&cmd_config_speed_all_autoneg_value,
+		NULL,
+	},
+};
+
 /* *** configure speed for specific port *** */
 struct cmd_config_speed_specific {
 	cmdline_fixed_string_t port;
@@ -1533,14 +1577,18 @@ struct cmd_config_speed_specific {
 	cmdline_fixed_string_t item2;
 	cmdline_fixed_string_t value1;
 	cmdline_fixed_string_t value2;
+	cmdline_fixed_string_t autoneg;
+	cmdline_fixed_string_t autoneg_value;
 };
 
 static void
 cmd_config_speed_specific_parsed(void *parsed_result,
 				__rte_unused struct cmdline *cl,
-				__rte_unused void *data)
+				void *data)
 {
 	struct cmd_config_speed_specific *res = parsed_result;
+	/* data is used to identify command variant with/without explicit autoneg setting */
+	const char *autoneg = data != NULL ? res->autoneg_value : NULL;
 	uint32_t link_speed;
 
 	if (port_id_is_invalid(res->id, ENABLED_WARN))
@@ -1552,7 +1600,7 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 	}
 
 	if (parse_and_check_speed_duplex(res->value1, res->value2,
-			&link_speed) < 0)
+			link_speed_is_fixed(res->value1, autoneg), &link_speed) < 0)
 		return;
 
 	ports[res->id].dev_conf.link_speeds = link_speed;
@@ -1582,6 +1630,10 @@ static cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
 static cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2,
 							"half#full#auto");
+static cmdline_parse_token_string_t cmd_config_speed_specific_autoneg_token =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, autoneg, "autoneg");
+static cmdline_parse_token_string_t cmd_config_speed_specific_autoneg_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, autoneg_value, "on#off");
 
 static cmdline_parse_inst_t cmd_config_speed_specific = {
 	.f = cmd_config_speed_specific_parsed,
@@ -1602,6 +1654,27 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
 	},
 };
 
+static cmdline_parse_inst_t cmd_config_speed_specific_autoneg = {
+	.f = cmd_config_speed_specific_parsed,
+	.data = &cmd_config_speed_specific_autoneg,
+	.help_str = "port config <port_id> speed "
+		"10|100|1000|2500|5000|10000|25000|40000|50000|"
+		"100000|200000|400000|800000|auto "
+		"duplex half|full|auto autoneg on|off",
+	.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_item2,
+		(void *)&cmd_config_speed_specific_value2,
+		(void *)&cmd_config_speed_specific_autoneg_token,
+		(void *)&cmd_config_speed_specific_autoneg_value,
+		NULL,
+	},
+};
+
 static int
 parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
 {
@@ -14357,7 +14430,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	&cmd_operate_detach_device,
 	&cmd_set_port_setup_on,
 	&cmd_config_speed_all,
+	&cmd_config_speed_all_autoneg,
 	&cmd_config_speed_specific,
+	&cmd_config_speed_specific_autoneg,
 	&cmd_config_speed_lanes_all,
 	&cmd_config_speed_lanes_specific,
 	&cmd_show_speed_lanes,
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 8ca8379cc6..29fccf09e3 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -340,6 +340,12 @@ New Features
   Added ``dpdk-validate-bpf`` tool to pre-validate eBPF programs
   for compatibility with the ``lib/bpf`` execution context.
 
+* **Added explicit link autonegotiation control in testpmd.**
+
+  Added an optional ``autoneg on|off`` setting after ``duplex`` in the port speed configuration command.
+  For compatibility with older behavior, if unspecified,
+  auto-negotiation is disabled by default for numeric speeds, and enabled for "auto" speed selection.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a967bbef76..866f8057c1 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2167,7 +2167,16 @@ 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|800000|auto) \
-            duplex (half|full|auto)
+            duplex (half|full|auto) [autoneg (on|off)]
+
+With ``autoneg on``, the selected speed is advertised with link autonegotiation enabled.
+With ``autoneg off``, link autonegotiation is disabled and the selected speed is forced.
+If ``autoneg`` parameter is omitted for a numeric speed, link autonegotiation is disabled.
+The ``auto`` speed advertises all supported speeds and enables link autonegotiation if ``autoneg`` is omitted.
+
+.. note ::
+
+   Combining ``auto`` speed with ``autoneg off`` is an error.
 
 port config - queues/descriptors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
2.55.0


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

* Re: [PATCH v3] app/testpmd: add explicit link autonegotiation control
  2026-11-10 12:16 ` [PATCH v3] " Bruce Richardson
@ 2026-11-10 16:59   ` Stephen Hemminger
  0 siblings, 0 replies; 7+ messages in thread
From: Stephen Hemminger @ 2026-11-10 16:59 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Tue, 10 Nov 2026 12:16:57 +0000
Bruce Richardson <bruce.richardson@intel.com> wrote:

> When a particular speed was specified for a port in testpmd, the flags
> passed to the underlying API call always included the
> RTE_ETH_LINK_SPEED_FIXED flag. This flag is not a mandatory part of the
> bitmap when setting speeds, and is used to disable autonegotiation.
> It's possible to have a link report only a single speed while
> still have negotiation enabled, so testpmd needs to be extended to
> support setting a speed both with and without the flag.
> 
> This patch does so by adding optional "autoneg on|off" setting after
> speed and duplex settings specified by the user. This new option adjusts
> the presence or absence of the FIXED speed bit in the ethdev
> configuration structure "rte_eth_conf.link_speeds" bitmap. For backward
> compatibility, the default value is "autoneg off" for fixed speeds if
> not specified, meaning that the RTE_ETH_LINK_SPEED_FIXED flag is set on
> the speed value by default.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---

Applied to next-net and resolved merge conflict and minor docbook whitespace

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

end of thread, other threads:[~2026-11-10 16:59 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 15:50 [PATCH] app/test-pmd: add explicit parameter for fixed link speeds Bruce Richardson
2026-11-04 12:29 ` Stephen Hemminger
2026-11-04 13:39   ` Bruce Richardson
2026-11-09 15:59 ` [PATCH v2] app/testpmd: add explicit link autonegotiation control Bruce Richardson
2026-11-09 17:45   ` Stephen Hemminger
2026-11-10 12:16 ` [PATCH v3] " Bruce Richardson
2026-11-10 16:59   ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox