ethdev: format link status text
authorIvan Dyukov <i.dyukov@samsung.com>
Tue, 15 Sep 2020 19:06:57 +0000 (22:06 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 21 Sep 2020 16:05:37 +0000 (18:05 +0200)
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>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
MAINTAINERS
app/test/meson.build
app/test/test_ethdev_link.c [new file with mode: 0644]
lib/librte_ethdev/rte_ethdev.c
lib/librte_ethdev/rte_ethdev.h
lib/librte_ethdev/rte_ethdev_version.map

index 6e6f4cc..652712c 100644 (file)
@@ -370,6 +370,7 @@ M: Ferruh Yigit <ferruh.yigit@intel.com>
 M: Andrew Rybchenko <arybchenko@solarflare.com>
 T: git://dpdk.org/next/dpdk-next-net
 F: lib/librte_ethdev/
+F: app/test/test_ethdev*
 F: devtools/test-null.sh
 F: doc/guides/prog_guide/switch_representation.rst
 
index 786a213..181e870 100644 (file)
@@ -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',
@@ -200,6 +201,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 (file)
index 0000000..ee11987
--- /dev/null
@@ -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);
index 066751f..dfe5c1b 100644 (file)
@@ -2384,6 +2384,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)
 {
index 394e353..c6560f2 100644 (file)
@@ -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
@@ -2436,6 +2437,44 @@ 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);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * 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);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * 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.
  *
index fc47f64..c95ef51 100644 (file)
@@ -225,6 +225,10 @@ EXPERIMENTAL {
        rte_tm_shared_wred_context_delete;
        rte_tm_wred_profile_add;
        rte_tm_wred_profile_delete;
+
+       # added in 20.11
+       rte_eth_link_speed_to_str;
+       rte_eth_link_to_str;
 };
 
 INTERNAL {