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
prev 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).