[v11,02/24] ethdev: format a link status text
Checks
Commit Message
There is new link_speed value introduced. It's INT_MAX value which
means that speed is unknown. To simplify processing of the value
in application, new function is added which convert link_speed to
string. Also dpdk examples have many duplicated code which format
entire link status structure to text.
This commit adds two functions:
* rte_eth_link_speed_to_str - format link_speed to string
* rte_eth_link_to_str - convert link status structure to string
Signed-off-by: Ivan Dyukov <i.dyukov@samsung.com>
---
MAINTAINERS | 1 +
app/test/Makefile | 3 +
app/test/meson.build | 2 +
app/test/test_ethdev_link.c | 169 +++++++++++++++++++++++
lib/librte_ethdev/rte_ethdev.c | 37 +++++
lib/librte_ethdev/rte_ethdev.h | 32 +++++
lib/librte_ethdev/rte_ethdev_version.map | 4 +
7 files changed, 248 insertions(+)
create mode 100644 app/test/test_ethdev_link.c
Comments
> From: Ivan Dyukov [mailto:i.dyukov@samsung.com]
> Sent: Tuesday, September 15, 2020 9:07 PM
>
> There is new link_speed value introduced. It's INT_MAX value which
> means that speed is unknown. To simplify processing of the value
> in application, new function is added which convert link_speed to
> string. Also dpdk examples have many duplicated code which format
> entire link status structure to text.
>
> This commit adds two functions:
> * rte_eth_link_speed_to_str - format link_speed to string
> * rte_eth_link_to_str - convert link status structure to string
>
> Signed-off-by: Ivan Dyukov <i.dyukov@samsung.com>
> ---
> MAINTAINERS | 1 +
> app/test/Makefile | 3 +
> app/test/meson.build | 2 +
> app/test/test_ethdev_link.c | 169 +++++++++++++++++++++++
> lib/librte_ethdev/rte_ethdev.c | 37 +++++
> lib/librte_ethdev/rte_ethdev.h | 32 +++++
> lib/librte_ethdev/rte_ethdev_version.map | 4 +
> 7 files changed, 248 insertions(+)
> create mode 100644 app/test/test_ethdev_link.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5e706cd7e..f4fb31ea2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -393,6 +393,7 @@ T: git://dpdk.org/next/dpdk-next-net
> F: lib/librte_ethdev/
> F: devtools/test-null.sh
> F: doc/guides/prog_guide/switch_representation.rst
> +F: app/test/test_ethdev*
>
> Flow API
> M: Ori Kam <orika@mellanox.com>
> diff --git a/app/test/Makefile b/app/test/Makefile
> index e5440774b..9f43b8c3c 100644
> --- a/app/test/Makefile
> +++ b/app/test/Makefile
> @@ -251,6 +251,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) +=
> test_security.c
>
> SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c test_ipsec_perf.c
> SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c
> +
> +SRCS-$(CONFIG_RTE_LIBRTE_ETHER) += test_ethdev_link.c
> +
> ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)
> LDLIBS += -lrte_ipsec
> endif
> diff --git a/app/test/meson.build b/app/test/meson.build
> index 56591db4e..1e6acf701 100644
> --- a/app/test/meson.build
> +++ b/app/test/meson.build
> @@ -39,6 +39,7 @@ test_sources = files('commands.c',
> 'test_efd.c',
> 'test_efd_perf.c',
> 'test_errno.c',
> + 'test_ethdev_link.c',
> 'test_event_crypto_adapter.c',
> 'test_event_eth_rx_adapter.c',
> 'test_event_ring.c',
> @@ -199,6 +200,7 @@ fast_tests = [
> ['eal_flags_misc_autotest', false],
> ['eal_fs_autotest', true],
> ['errno_autotest', true],
> + ['ethdev_link_status', true],
> ['event_ring_autotest', true],
> ['fib_autotest', true],
> ['fib6_autotest', true],
> diff --git a/app/test/test_ethdev_link.c b/app/test/test_ethdev_link.c
> new file mode 100644
> index 000000000..ee11987ba
> --- /dev/null
> +++ b/app/test/test_ethdev_link.c
> @@ -0,0 +1,169 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
> + */
> +
> +#include <rte_log.h>
> +#include <rte_ethdev.h>
> +
> +#include <rte_test.h>
> +#include "test.h"
> +
> +
> +static int32_t
> +test_link_status_up_default(void)
> +{
> + int ret = 0;
> + struct rte_eth_link link_status = {
> + .link_speed = ETH_SPEED_NUM_2_5G,
> + .link_status = ETH_LINK_UP,
> + .link_autoneg = ETH_LINK_AUTONEG,
> + .link_duplex = ETH_LINK_FULL_DUPLEX
> + };
> + char text[RTE_ETH_LINK_MAX_STR_LEN];
> +
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
> + printf("Default link up #1: %s\n", text);
> + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at 2.5 Gbps FDX Autoneg",
> + text, strlen(text), "Invalid default link status string");
> +
> + link_status.link_duplex = ETH_LINK_HALF_DUPLEX;
> + link_status.link_autoneg = ETH_LINK_FIXED;
> + link_status.link_speed = ETH_SPEED_NUM_10M,
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + printf("Default link up #2: %s\n", text);
> + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
> + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at 10 Mbps HDX Fixed",
> + text, strlen(text), "Invalid default link status "
> + "string with HDX");
> +
> + link_status.link_speed = ETH_SPEED_NUM_UNKNOWN;
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + printf("Default link up #3: %s\n", text);
> + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
> + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at Unknown HDX Fixed",
> + text, strlen(text), "Invalid default link status "
> + "string with HDX");
> +
> + link_status.link_speed = ETH_SPEED_NUM_NONE;
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + printf("Default link up #3: %s\n", text);
> + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
> + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at None HDX Fixed",
> + text, strlen(text), "Invalid default link status "
> + "string with HDX");
> +
> + /* test max str len */
> + link_status.link_speed = ETH_SPEED_NUM_200G;
> + link_status.link_duplex = ETH_LINK_HALF_DUPLEX;
> + link_status.link_autoneg = ETH_LINK_AUTONEG;
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + printf("Default link up #4:len = %d, %s\n", ret, text);
> + RTE_TEST_ASSERT(ret < RTE_ETH_LINK_MAX_STR_LEN,
> + "String length exceeds max allowed value\n");
> + return TEST_SUCCESS;
> +}
> +
> +static int32_t
> +test_link_status_down_default(void)
> +{
> + int ret = 0;
> + struct rte_eth_link link_status = {
> + .link_speed = ETH_SPEED_NUM_2_5G,
> + .link_status = ETH_LINK_DOWN,
> + .link_autoneg = ETH_LINK_AUTONEG,
> + .link_duplex = ETH_LINK_FULL_DUPLEX
> + };
> + char text[RTE_ETH_LINK_MAX_STR_LEN];
> +
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
> + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link down",
> + text, strlen(text), "Invalid default link status string");
> +
> + return TEST_SUCCESS;
> +}
> +
> +static int32_t
> +test_link_status_invalid(void)
> +{
> + int ret = 0;
> + struct rte_eth_link link_status = {
> + .link_speed = 55555,
> + .link_status = ETH_LINK_UP,
> + .link_autoneg = ETH_LINK_AUTONEG,
> + .link_duplex = ETH_LINK_FULL_DUPLEX
> + };
> + char text[RTE_ETH_LINK_MAX_STR_LEN];
> +
> + ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
> + RTE_TEST_ASSERT(ret < RTE_ETH_LINK_MAX_STR_LEN,
> + "Failed to format invalid string\n");
> + printf("invalid link up #1: len=%d %s\n", ret, text);
> + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at Invalid FDX Autoneg",
> + text, strlen(text), "Incorrect invalid link status
> string");
> +
> + return TEST_SUCCESS;
> +}
> +
> +
> +static int32_t
> +test_link_speed_all_values(void)
> +{
> + const char *speed;
> + uint32_t i;
> + struct link_speed_t {
> + const char *value;
> + uint32_t link_speed;
> + } speed_str_map[] = {
> + { "None", ETH_SPEED_NUM_NONE },
> + { "10 Mbps", ETH_SPEED_NUM_10M },
> + { "100 Mbps", ETH_SPEED_NUM_100M },
> + { "1 Gbps", ETH_SPEED_NUM_1G },
> + { "2.5 Gbps", ETH_SPEED_NUM_2_5G },
> + { "5 Gbps", ETH_SPEED_NUM_5G },
> + { "10 Gbps", ETH_SPEED_NUM_10G },
> + { "20 Gbps", ETH_SPEED_NUM_20G },
> + { "25 Gbps", ETH_SPEED_NUM_25G },
> + { "40 Gbps", ETH_SPEED_NUM_40G },
> + { "50 Gbps", ETH_SPEED_NUM_50G },
> + { "56 Gbps", ETH_SPEED_NUM_56G },
> + { "100 Gbps", ETH_SPEED_NUM_100G },
> + { "200 Gbps", ETH_SPEED_NUM_200G },
> + { "Unknown", ETH_SPEED_NUM_UNKNOWN },
> + { "Invalid", 50505 }
> + };
> +
> + for (i = 0; i < sizeof(speed_str_map) / sizeof(struct
> link_speed_t);
> + i++) {
> + speed =
> rte_eth_link_speed_to_str(speed_str_map[i].link_speed);
> + TEST_ASSERT_BUFFERS_ARE_EQUAL(speed_str_map[i].value,
> + speed, strlen(speed_str_map[i].value),
> + "Invalid link speed string");
> + }
> + return TEST_SUCCESS;
> +}
> +
> +static struct unit_test_suite link_status_testsuite = {
> + .suite_name = "link status formatting",
> + .setup = NULL,
> + .teardown = NULL,
> + .unit_test_cases = {
> + TEST_CASE(test_link_status_up_default),
> + TEST_CASE(test_link_status_down_default),
> + TEST_CASE(test_link_speed_all_values),
> + TEST_CASE(test_link_status_invalid),
> + TEST_CASES_END() /**< NULL terminate unit test array */
> + }
> +};
> +
> +static int
> +test_link_status(void)
> +{
> + rte_log_set_global_level(RTE_LOG_DEBUG);
> + rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
> +
> + return unit_test_suite_runner(&link_status_testsuite);
> +}
> +
> +REGISTER_TEST_COMMAND(ethdev_link_status, test_link_status);
> diff --git a/lib/librte_ethdev/rte_ethdev.c
> b/lib/librte_ethdev/rte_ethdev.c
> index d06b7f9b1..438cece72 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -2383,6 +2383,43 @@ rte_eth_link_get_nowait(uint16_t port_id, struct
> rte_eth_link *eth_link)
> return 0;
> }
>
> +const char *
> +rte_eth_link_speed_to_str(uint32_t link_speed)
> +{
> + switch (link_speed) {
> + case ETH_SPEED_NUM_NONE: return "None";
> + case ETH_SPEED_NUM_10M: return "10 Mbps";
> + case ETH_SPEED_NUM_100M: return "100 Mbps";
> + case ETH_SPEED_NUM_1G: return "1 Gbps";
> + case ETH_SPEED_NUM_2_5G: return "2.5 Gbps";
> + case ETH_SPEED_NUM_5G: return "5 Gbps";
> + case ETH_SPEED_NUM_10G: return "10 Gbps";
> + case ETH_SPEED_NUM_20G: return "20 Gbps";
> + case ETH_SPEED_NUM_25G: return "25 Gbps";
> + case ETH_SPEED_NUM_40G: return "40 Gbps";
> + case ETH_SPEED_NUM_50G: return "50 Gbps";
> + case ETH_SPEED_NUM_56G: return "56 Gbps";
> + case ETH_SPEED_NUM_100G: return "100 Gbps";
> + case ETH_SPEED_NUM_200G: return "200 Gbps";
> + case ETH_SPEED_NUM_UNKNOWN: return "Unknown";
> + default: return "Invalid";
> + }
> +}
> +
> +int
> +rte_eth_link_to_str(char *str, size_t len, const struct rte_eth_link
> *eth_link)
> +{
> + if (eth_link->link_status == ETH_LINK_DOWN)
> + return snprintf(str, len, "Link down");
> + else
> + return snprintf(str, len, "Link up at %s %s %s",
> + rte_eth_link_speed_to_str(eth_link->link_speed),
> + (eth_link->link_duplex == ETH_LINK_FULL_DUPLEX) ?
> + "FDX" : "HDX",
> + (eth_link->link_autoneg == ETH_LINK_AUTONEG) ?
> + "Autoneg" : "Fixed");
> +}
> +
> int
> rte_eth_stats_get(uint16_t port_id, struct rte_eth_stats *stats)
> {
> diff --git a/lib/librte_ethdev/rte_ethdev.h
> b/lib/librte_ethdev/rte_ethdev.h
> index 2090af501..a86f8f916 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -323,6 +323,7 @@ struct rte_eth_link {
> #define ETH_LINK_UP 1 /**< Link is up (see link_status). */
> #define ETH_LINK_FIXED 0 /**< No autonegotiation (see
> link_autoneg). */
> #define ETH_LINK_AUTONEG 1 /**< Autonegotiated (see link_autoneg).
> */
> +#define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link
> string. */
>
> /**
> * A structure used to configure the ring threshold registers of an
> RX/TX
> @@ -2295,6 +2296,37 @@ int rte_eth_link_get(uint16_t port_id, struct
> rte_eth_link *link);
> */
> int rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link
> *link);
>
> +/**
> + * The function converts a link_speed to a string. It handles all
> special
> + * values like unknown or none speed.
> + * @param link_speed
> + * link_speed of rte_eth_link struct
> + * @return
> + * Link speed in textual format. It's pointer to immutable memory.
> + * No free is required.
> + */
> +__rte_experimental
> +const char *rte_eth_link_speed_to_str(uint32_t speed_link);
> +
> +/**
> + * The function converts a rte_eth_link struct representing a link
> status to
> + * a string.
> + * @param str
> + * A pointer to a string to be filled with textual representation of
> + * device status. At least ETH_LINK_MAX_STR_LEN bytes should be
> allocated to
> + * store default link status text.
> + * @param len
> + * Length of available memory at 'str' string.
> + * @param eth_link
> + * Link status returned by rte_eth_link_get function
> + * @return
> + * - Number of bytes written to str array.
> + *
> + */
> +__rte_experimental
> +int rte_eth_link_to_str(char *str, size_t len,
> + const struct rte_eth_link *eth_link);
> +
> /**
> * Retrieve the general I/O statistics of an Ethernet device.
> *
> diff --git a/lib/librte_ethdev/rte_ethdev_version.map
> b/lib/librte_ethdev/rte_ethdev_version.map
> index 715505604..69a763d4b 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -241,4 +241,8 @@ EXPERIMENTAL {
> __rte_ethdev_trace_rx_burst;
> __rte_ethdev_trace_tx_burst;
> rte_flow_get_aged_flows;
> +
> + # added in 20.11
> + rte_eth_link_to_str;
> + rte_eth_link_speed_to_str;
> };
> --
> 2.17.1
>
Great work, Ivan!
Acked-by: Morten Brørup <mb@smartsharesystems.com>
On 9/15/2020 9:44 PM, Morten Brørup wrote:
>> From: Ivan Dyukov [mailto:i.dyukov@samsung.com]
>> Sent: Tuesday, September 15, 2020 9:07 PM
>>
>> There is new link_speed value introduced. It's INT_MAX value which
>> means that speed is unknown. To simplify processing of the value
>> in application, new function is added which convert link_speed to
>> string. Also dpdk examples have many duplicated code which format
>> entire link status structure to text.
>>
>> This commit adds two functions:
>> * rte_eth_link_speed_to_str - format link_speed to string
>> * rte_eth_link_to_str - convert link status structure to string
>>
>> Signed-off-by: Ivan Dyukov <i.dyukov@samsung.com>
>
> Great work, Ivan!
>
+1
> Acked-by: Morten Brørup <mb@smartsharesystems.com>
>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
@@ -393,6 +393,7 @@ T: git://dpdk.org/next/dpdk-next-net
F: lib/librte_ethdev/
F: devtools/test-null.sh
F: doc/guides/prog_guide/switch_representation.rst
+F: app/test/test_ethdev*
Flow API
M: Ori Kam <orika@mellanox.com>
@@ -251,6 +251,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) += test_security.c
SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c test_ipsec_perf.c
SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_ETHER) += test_ethdev_link.c
+
ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)
LDLIBS += -lrte_ipsec
endif
@@ -39,6 +39,7 @@ test_sources = files('commands.c',
'test_efd.c',
'test_efd_perf.c',
'test_errno.c',
+ 'test_ethdev_link.c',
'test_event_crypto_adapter.c',
'test_event_eth_rx_adapter.c',
'test_event_ring.c',
@@ -199,6 +200,7 @@ fast_tests = [
['eal_flags_misc_autotest', false],
['eal_fs_autotest', true],
['errno_autotest', true],
+ ['ethdev_link_status', true],
['event_ring_autotest', true],
['fib_autotest', true],
['fib6_autotest', true],
new file mode 100644
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ */
+
+#include <rte_log.h>
+#include <rte_ethdev.h>
+
+#include <rte_test.h>
+#include "test.h"
+
+
+static int32_t
+test_link_status_up_default(void)
+{
+ int ret = 0;
+ struct rte_eth_link link_status = {
+ .link_speed = ETH_SPEED_NUM_2_5G,
+ .link_status = ETH_LINK_UP,
+ .link_autoneg = ETH_LINK_AUTONEG,
+ .link_duplex = ETH_LINK_FULL_DUPLEX
+ };
+ char text[RTE_ETH_LINK_MAX_STR_LEN];
+
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
+ printf("Default link up #1: %s\n", text);
+ TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at 2.5 Gbps FDX Autoneg",
+ text, strlen(text), "Invalid default link status string");
+
+ link_status.link_duplex = ETH_LINK_HALF_DUPLEX;
+ link_status.link_autoneg = ETH_LINK_FIXED;
+ link_status.link_speed = ETH_SPEED_NUM_10M,
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ printf("Default link up #2: %s\n", text);
+ RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
+ TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at 10 Mbps HDX Fixed",
+ text, strlen(text), "Invalid default link status "
+ "string with HDX");
+
+ link_status.link_speed = ETH_SPEED_NUM_UNKNOWN;
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ printf("Default link up #3: %s\n", text);
+ RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
+ TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at Unknown HDX Fixed",
+ text, strlen(text), "Invalid default link status "
+ "string with HDX");
+
+ link_status.link_speed = ETH_SPEED_NUM_NONE;
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ printf("Default link up #3: %s\n", text);
+ RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
+ TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at None HDX Fixed",
+ text, strlen(text), "Invalid default link status "
+ "string with HDX");
+
+ /* test max str len */
+ link_status.link_speed = ETH_SPEED_NUM_200G;
+ link_status.link_duplex = ETH_LINK_HALF_DUPLEX;
+ link_status.link_autoneg = ETH_LINK_AUTONEG;
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ printf("Default link up #4:len = %d, %s\n", ret, text);
+ RTE_TEST_ASSERT(ret < RTE_ETH_LINK_MAX_STR_LEN,
+ "String length exceeds max allowed value\n");
+ return TEST_SUCCESS;
+}
+
+static int32_t
+test_link_status_down_default(void)
+{
+ int ret = 0;
+ struct rte_eth_link link_status = {
+ .link_speed = ETH_SPEED_NUM_2_5G,
+ .link_status = ETH_LINK_DOWN,
+ .link_autoneg = ETH_LINK_AUTONEG,
+ .link_duplex = ETH_LINK_FULL_DUPLEX
+ };
+ char text[RTE_ETH_LINK_MAX_STR_LEN];
+
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n");
+ TEST_ASSERT_BUFFERS_ARE_EQUAL("Link down",
+ text, strlen(text), "Invalid default link status string");
+
+ return TEST_SUCCESS;
+}
+
+static int32_t
+test_link_status_invalid(void)
+{
+ int ret = 0;
+ struct rte_eth_link link_status = {
+ .link_speed = 55555,
+ .link_status = ETH_LINK_UP,
+ .link_autoneg = ETH_LINK_AUTONEG,
+ .link_duplex = ETH_LINK_FULL_DUPLEX
+ };
+ char text[RTE_ETH_LINK_MAX_STR_LEN];
+
+ ret = rte_eth_link_to_str(text, sizeof(text), &link_status);
+ RTE_TEST_ASSERT(ret < RTE_ETH_LINK_MAX_STR_LEN,
+ "Failed to format invalid string\n");
+ printf("invalid link up #1: len=%d %s\n", ret, text);
+ TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at Invalid FDX Autoneg",
+ text, strlen(text), "Incorrect invalid link status string");
+
+ return TEST_SUCCESS;
+}
+
+
+static int32_t
+test_link_speed_all_values(void)
+{
+ const char *speed;
+ uint32_t i;
+ struct link_speed_t {
+ const char *value;
+ uint32_t link_speed;
+ } speed_str_map[] = {
+ { "None", ETH_SPEED_NUM_NONE },
+ { "10 Mbps", ETH_SPEED_NUM_10M },
+ { "100 Mbps", ETH_SPEED_NUM_100M },
+ { "1 Gbps", ETH_SPEED_NUM_1G },
+ { "2.5 Gbps", ETH_SPEED_NUM_2_5G },
+ { "5 Gbps", ETH_SPEED_NUM_5G },
+ { "10 Gbps", ETH_SPEED_NUM_10G },
+ { "20 Gbps", ETH_SPEED_NUM_20G },
+ { "25 Gbps", ETH_SPEED_NUM_25G },
+ { "40 Gbps", ETH_SPEED_NUM_40G },
+ { "50 Gbps", ETH_SPEED_NUM_50G },
+ { "56 Gbps", ETH_SPEED_NUM_56G },
+ { "100 Gbps", ETH_SPEED_NUM_100G },
+ { "200 Gbps", ETH_SPEED_NUM_200G },
+ { "Unknown", ETH_SPEED_NUM_UNKNOWN },
+ { "Invalid", 50505 }
+ };
+
+ for (i = 0; i < sizeof(speed_str_map) / sizeof(struct link_speed_t);
+ i++) {
+ speed = rte_eth_link_speed_to_str(speed_str_map[i].link_speed);
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(speed_str_map[i].value,
+ speed, strlen(speed_str_map[i].value),
+ "Invalid link speed string");
+ }
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite link_status_testsuite = {
+ .suite_name = "link status formatting",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_link_status_up_default),
+ TEST_CASE(test_link_status_down_default),
+ TEST_CASE(test_link_speed_all_values),
+ TEST_CASE(test_link_status_invalid),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_link_status(void)
+{
+ rte_log_set_global_level(RTE_LOG_DEBUG);
+ rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
+
+ return unit_test_suite_runner(&link_status_testsuite);
+}
+
+REGISTER_TEST_COMMAND(ethdev_link_status, test_link_status);
@@ -2383,6 +2383,43 @@ rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *eth_link)
return 0;
}
+const char *
+rte_eth_link_speed_to_str(uint32_t link_speed)
+{
+ switch (link_speed) {
+ case ETH_SPEED_NUM_NONE: return "None";
+ case ETH_SPEED_NUM_10M: return "10 Mbps";
+ case ETH_SPEED_NUM_100M: return "100 Mbps";
+ case ETH_SPEED_NUM_1G: return "1 Gbps";
+ case ETH_SPEED_NUM_2_5G: return "2.5 Gbps";
+ case ETH_SPEED_NUM_5G: return "5 Gbps";
+ case ETH_SPEED_NUM_10G: return "10 Gbps";
+ case ETH_SPEED_NUM_20G: return "20 Gbps";
+ case ETH_SPEED_NUM_25G: return "25 Gbps";
+ case ETH_SPEED_NUM_40G: return "40 Gbps";
+ case ETH_SPEED_NUM_50G: return "50 Gbps";
+ case ETH_SPEED_NUM_56G: return "56 Gbps";
+ case ETH_SPEED_NUM_100G: return "100 Gbps";
+ case ETH_SPEED_NUM_200G: return "200 Gbps";
+ case ETH_SPEED_NUM_UNKNOWN: return "Unknown";
+ default: return "Invalid";
+ }
+}
+
+int
+rte_eth_link_to_str(char *str, size_t len, const struct rte_eth_link *eth_link)
+{
+ if (eth_link->link_status == ETH_LINK_DOWN)
+ return snprintf(str, len, "Link down");
+ else
+ return snprintf(str, len, "Link up at %s %s %s",
+ rte_eth_link_speed_to_str(eth_link->link_speed),
+ (eth_link->link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ "FDX" : "HDX",
+ (eth_link->link_autoneg == ETH_LINK_AUTONEG) ?
+ "Autoneg" : "Fixed");
+}
+
int
rte_eth_stats_get(uint16_t port_id, struct rte_eth_stats *stats)
{
@@ -323,6 +323,7 @@ struct rte_eth_link {
#define ETH_LINK_UP 1 /**< Link is up (see link_status). */
#define ETH_LINK_FIXED 0 /**< No autonegotiation (see link_autoneg). */
#define ETH_LINK_AUTONEG 1 /**< Autonegotiated (see link_autoneg). */
+#define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
/**
* A structure used to configure the ring threshold registers of an RX/TX
@@ -2295,6 +2296,37 @@ int rte_eth_link_get(uint16_t port_id, struct rte_eth_link *link);
*/
int rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *link);
+/**
+ * The function converts a link_speed to a string. It handles all special
+ * values like unknown or none speed.
+ * @param link_speed
+ * link_speed of rte_eth_link struct
+ * @return
+ * Link speed in textual format. It's pointer to immutable memory.
+ * No free is required.
+ */
+__rte_experimental
+const char *rte_eth_link_speed_to_str(uint32_t speed_link);
+
+/**
+ * The function converts a rte_eth_link struct representing a link status to
+ * a string.
+ * @param str
+ * A pointer to a string to be filled with textual representation of
+ * device status. At least ETH_LINK_MAX_STR_LEN bytes should be allocated to
+ * store default link status text.
+ * @param len
+ * Length of available memory at 'str' string.
+ * @param eth_link
+ * Link status returned by rte_eth_link_get function
+ * @return
+ * - Number of bytes written to str array.
+ *
+ */
+__rte_experimental
+int rte_eth_link_to_str(char *str, size_t len,
+ const struct rte_eth_link *eth_link);
+
/**
* Retrieve the general I/O statistics of an Ethernet device.
*
@@ -241,4 +241,8 @@ EXPERIMENTAL {
__rte_ethdev_trace_rx_burst;
__rte_ethdev_trace_tx_burst;
rte_flow_get_aged_flows;
+
+ # added in 20.11
+ rte_eth_link_to_str;
+ rte_eth_link_speed_to_str;
};