> From: Ivan Dyukov [mailto:i.dyu...@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.dyu...@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 <or...@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 <m...@smartsharesystems.com>