DPDK patches and discussions
 help / color / mirror / Atom feed
From: Ciara Loftus <ciara.loftus@intel.com>
To: dev@dpdk.org
Cc: Ciara Loftus <ciara.loftus@intel.com>
Subject: [RFC PATCH 3/3] app/testpmd: support link state on close ethdev API
Date: Fri, 29 Aug 2025 14:02:24 +0000	[thread overview]
Message-ID: <20250829140224.1748255-4-ciara.loftus@intel.com> (raw)
In-Reply-To: <20250829140224.1748255-1-ciara.loftus@intel.com>

Allow the user to configure link state on close behaviour via the
link_state_on_close argument. Three options are allowed:
1. down: bring (or keep) the link down
2. up: bring (or keep) the link up
3. initial: restore the link to the state it was in when the device was
started.

Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
 app/test-pmd/cmdline.c                      | 56 +++++++++++++++++++++
 app/test-pmd/config.c                       | 17 +++++++
 app/test-pmd/parameters.c                   | 26 ++++++++++
 app/test-pmd/testpmd.c                      | 16 ++++++
 app/test-pmd/testpmd.h                      |  3 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  7 +++
 6 files changed, 125 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 7b4e27eddf..79afcca60c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -679,6 +679,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"    Set a controllable LED associated with a certain"
 			" port on or off.\n\n"
 
+			"set port (port_id) link_state_on_close (down|up|initial)\n"
+			"    Set link state on close to down, up or initial for a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -13857,6 +13860,58 @@ static cmdline_parse_inst_t cmd_set_dev_led = {
 	},
 };
 
+/* *** SET LINK STATE ON CLOSE FOR A CERTAIN PORT *** */
+struct cmd_link_state_on_close_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t link_state_on_close;
+	cmdline_fixed_string_t state;
+};
+
+static void
+cmd_set_link_state_on_close_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_link_state_on_close_result *res = parsed_result;
+
+	if (strcmp(res->state, "down") == 0)
+		set_link_state_on_close(res->port_id, RTE_ETH_LINK_STATE_ON_CLOSE_DOWN);
+	else if (strcmp(res->state, "up") == 0)
+		set_link_state_on_close(res->port_id, RTE_ETH_LINK_STATE_ON_CLOSE_UP);
+	else if (strcmp(res->state, "initial") == 0)
+		set_link_state_on_close(res->port_id, RTE_ETH_LINK_STATE_ON_CLOSE_INITIAL);
+	else
+		printf("Invalid state: %s\n", res->state);
+}
+
+static cmdline_parse_token_string_t cmd_link_state_on_close_set =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_state_on_close_result, set, "set");
+static cmdline_parse_token_string_t cmd_link_state_on_close_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_state_on_close_result, port, "port");
+static cmdline_parse_token_num_t cmd_link_state_on_close_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_link_state_on_close_result, port_id, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_link_state_on_close =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_state_on_close_result, link_state_on_close,
+		"link_state_on_close");
+static cmdline_parse_token_string_t cmd_link_state_on_close_state =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_state_on_close_result, state, "down#up#initial");
+
+static cmdline_parse_inst_t cmd_set_link_state_on_close = {
+	.f = cmd_set_link_state_on_close_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> link_state_on_close <down/up/initial>",
+	.tokens = {
+		(void *)&cmd_link_state_on_close_set,
+		(void *)&cmd_link_state_on_close_port,
+		(void *)&cmd_link_state_on_close_port_id,
+		(void *)&cmd_link_state_on_close,
+		(void *)&cmd_link_state_on_close_state,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -14105,6 +14160,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	&cmd_set_port_cman_config,
 	&cmd_config_tx_affinity_map,
 	&cmd_set_dev_led,
+	&cmd_set_link_state_on_close,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 0fda8e99f8..c5c5e23b4b 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -5429,6 +5429,23 @@ set_dev_led(portid_t port_id, bool active)
 			port_id, rte_strerror(-ret));
 }
 
+void
+set_link_state_on_close(portid_t port_id, enum rte_eth_link_state_on_close state)
+{
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		fprintf(stderr, "Error: Invalid port number %u\n", port_id);
+		return;
+	}
+
+	ret = rte_eth_dev_set_link_state_on_close(port_id, state);
+
+	if (ret < 0)
+		fprintf(stderr, "Error: Unable to set link state on close for port %u: %s\n",
+			port_id, rte_strerror(-ret));
+}
+
 int
 set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc)
 {
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 1132972913..83c077f651 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -253,6 +253,8 @@ enum {
 	TESTPMD_OPT_NUM_PROCS_NUM,
 #define TESTPMD_OPT_PROC_ID "proc-id"
 	TESTPMD_OPT_PROC_ID_NUM,
+#define TESTPMD_OPT_LINK_STATE_ON_CLOSE "link_state_on_close"
+	TESTPMD_OPT_LINK_STATE_ON_CLOSE_NUM,
 
 	TESTPMD_OPT_LONG_MAX_NUM
 };
@@ -378,6 +380,7 @@ static const struct option long_options[] = {
 	NO_ARG(TESTPMD_OPT_RECORD_BURST_STATS),
 	REQUIRED_ARG(TESTPMD_OPT_NUM_PROCS),
 	REQUIRED_ARG(TESTPMD_OPT_PROC_ID),
+	REQUIRED_ARG(TESTPMD_OPT_LINK_STATE_ON_CLOSE),
 	{ 0, 0, NULL, 0 }
 };
 #undef NO_ARG
@@ -930,6 +933,23 @@ parse_link_speed(int n)
 	return speed;
 }
 
+static int
+parse_link_state_on_close(const char *optarg)
+{
+	if (!strcmp(optarg, "down")) {
+		close_state = RTE_ETH_LINK_STATE_ON_CLOSE_DOWN;
+	} else if (!strcmp(optarg, "up")) {
+		close_state = RTE_ETH_LINK_STATE_ON_CLOSE_UP;
+	} else if (!strcmp(optarg, "initial")) {
+		close_state = RTE_ETH_LINK_STATE_ON_CLOSE_INITIAL;
+	} else {
+		fprintf(stderr, "Invalid state: %s\n", optarg);
+		return -1;
+	}
+
+	return 0;
+}
+
 void
 launch_args_parse(int argc, char** argv)
 {
@@ -1733,6 +1753,12 @@ launch_args_parse(int argc, char** argv)
 		case TESTPMD_OPT_PROC_ID_NUM:
 			proc_id = atoi(optarg);
 			break;
+		case TESTPMD_OPT_LINK_STATE_ON_CLOSE_NUM:
+			if (parse_link_state_on_close(optarg)) {
+				rte_exit(EXIT_FAILURE,
+					"invalid link_state_on_close argument\n");
+			}
+			break;
 		default:
 			usage(argv[0]);
 			fprintf(stderr, "Invalid option: %s\n", argv[optind - 1]);
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bb88555328..4ffa1113cd 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -557,6 +557,11 @@ uint32_t eth_link_speed;
  */
 int proc_id;
 
+/*
+ * Link state on close.
+ */
+enum rte_eth_link_state_on_close close_state;
+
 /*
  * Number of processes in multi-process, used to
  * configure the queues to be polled.
@@ -3103,6 +3108,17 @@ start_port(portid_t pid)
 		p_pi = pi;
 		cnt_pi++;
 
+		/* Configure link state on close */
+		if (close_state) {
+			diag = rte_eth_dev_set_link_state_on_close(pi, close_state);
+			if (diag < 0)
+				fprintf(stderr,
+					"Port %d: Failed to configure link state on close\n",
+					pi);
+			else
+				printf("Link state on close configured for port %i\n", pi);
+		}
+
 		/* start port */
 		diag = eth_dev_start_mp(pi);
 		if (diag < 0) {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index e629edaa02..9e39bfea5b 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -821,6 +821,8 @@ extern struct rte_flow_action_conntrack conntrack_context;
 extern int proc_id;
 extern unsigned int num_procs;
 
+extern enum rte_eth_link_state_on_close close_state;
+
 static inline bool
 is_proc_primary(void)
 {
@@ -959,6 +961,7 @@ void update_fwd_ports(portid_t new_pid);
 
 void set_fwd_eth_peer(portid_t port_id, char *peer_addr);
 void set_dev_led(portid_t port_id, bool active);
+void set_link_state_on_close(portid_t port_id, enum rte_eth_link_state_on_close state);
 
 void port_mtu_set(portid_t port_id, uint16_t mtu);
 int port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 6ad83ae50d..96a7dd5470 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1863,6 +1863,13 @@ Set a controllable LED associated with a certain port on or off::
 
    testpmd> set port (port_id) led (on|off)
 
+set port link_state_on_close
+~~~~~~~~~~~~
+
+Set the link state on close for a certain port::
+
+   testpmd> set port (port_id) link_state_on_close (down|up|initial)
+
 Port Functions
 --------------
 
-- 
2.34.1


      parent reply	other threads:[~2025-08-29 14:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-29 14:02 [RFC PATCH 0/3] Make Link Status on Close Configurable Ciara Loftus
2025-08-29 14:02 ` [RFC PATCH 1/3] ethdev: add set link state on close API Ciara Loftus
2025-08-29 15:19   ` Ivan Malov
2025-08-29 14:02 ` [RFC PATCH 2/3] net/ice: implement the link state on close device op Ciara Loftus
2025-08-29 14:02 ` Ciara Loftus [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250829140224.1748255-4-ciara.loftus@intel.com \
    --to=ciara.loftus@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).