From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 061B4A0093; Mon, 15 Jun 2020 11:02:29 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 197535681; Mon, 15 Jun 2020 11:02:14 +0200 (CEST) Received: from mailout1.w1.samsung.com (mailout1.w1.samsung.com [210.118.77.11]) by dpdk.org (Postfix) with ESMTP id 8E8944C90 for ; Mon, 15 Jun 2020 11:02:12 +0200 (CEST) Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20200615090212euoutp0128ca70ed475298d9d97ea0648e89941f~YrCJ7bCCg2219822198euoutp017 for ; Mon, 15 Jun 2020 09:02:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20200615090212euoutp0128ca70ed475298d9d97ea0648e89941f~YrCJ7bCCg2219822198euoutp017 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1592211732; bh=OljwWih5OTHZTwp2/hu3sxZtTvfXEk8Y4NL40w+Uj38=; h=From:To:Subject:Date:In-Reply-To:Reply-To:References:From; b=foE+CSWTIE/q22Tf5zXD12lQVdXXHsFgZd9+ADAKHVNk77u8iZd/T8eGPSVF861ix mLuHwcK4mBcGEh3iRFAEe4Xls1kwpgI9gDCc7xGQA3jrbzFdFweHhnGs80/gL1p1nH ImE6QxfweJWeX0J+tnXaAizgiRhgVipE+MN40NA0= Received: from eusmges3new.samsung.com (unknown [203.254.199.245]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20200615090212eucas1p2b430e3ec29c8eb36868333cc6ee0b5d8~YrCJvq22o2891328913eucas1p2y; Mon, 15 Jun 2020 09:02:12 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges3new.samsung.com (EUCPMTA) with SMTP id 71.E0.60698.41937EE5; Mon, 15 Jun 2020 10:02:12 +0100 (BST) Received: from eusmtrp1.samsung.com (unknown [182.198.249.138]) by eucas1p2.samsung.com (KnoxPortal) with ESMTPA id 20200615090211eucas1p2f9951f582b14d602cbf4d51e228b12a0~YrCJRon4A3240932409eucas1p2C; Mon, 15 Jun 2020 09:02:11 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eusmtrp1.samsung.com (KnoxPortal) with ESMTP id 20200615090211eusmtrp1b992c276468094686a4211d8c4d0fee0~YrCJQ0bQ51017810178eusmtrp1S; Mon, 15 Jun 2020 09:02:11 +0000 (GMT) X-AuditID: cbfec7f5-a29ff7000001ed1a-77-5ee739142bd8 Received: from eusmtip1.samsung.com ( [203.254.199.221]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id CB.1A.08375.31937EE5; Mon, 15 Jun 2020 10:02:11 +0100 (BST) Received: from idyukov.rnd.samsung.ru (unknown [106.109.129.29]) by eusmtip1.samsung.com (KnoxPortal) with ESMTPA id 20200615090210eusmtip10b5e0865cd120b5f2442d506727e9bfa~YrCIe-sRV0240602406eusmtip1Z; Mon, 15 Jun 2020 09:02:10 +0000 (GMT) From: Ivan Dyukov To: dev@dpdk.org, i.dyukov@samsung.com, v.kuramshin@samsung.com, thomas@monjalon.net, david.marchand@redhat.com, ferruh.yigit@intel.com, arybchenko@solarflare.com, wei.zhao1@intel.com, jia.guo@intel.com, beilei.xing@intel.com, qiming.yang@intel.com, wenzhuo.lu@intel.com Date: Mon, 15 Jun 2020 12:01:50 +0300 Message-Id: <20200615090158.18912-3-i.dyukov@samsung.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200615090158.18912-1-i.dyukov@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA0WSfyyUcRzH932eu+ceN2ePY/MZLdttLZnQKA+rxGrdX/FHTauFk2cYd6d7 UPRHMuwmk3STH6105ce4CbkjQ7o/0A6hdCzMr/xcMT8KYTnPWf+9Pu8f38/22ZfExaV8ZzJO kcSoFLIECSHkGTq3+k46+s+Fe2+Pk/SEZoygH61kYnRTVQ5B/1ptwujRNpOALhnMENBzO4s4 rXnfjOjViW4ebRp5J6B1GwM4re/ZRRdspdtl5Xzp69YFTNo5UiiQLrcPEdK8xmokrZnZJEKJ G8Kz0UxCXAqj8jofKYxt3jRhidtZ6F6vPigdZcTlIBsSKF/QfN0lcpCQFFNVCL53Z/K4YR3B 8MoC4oY1BJ/7V/HDyrfnszhnVCIo0u9ZUxsIRis0mCVFUG5gUr/ALIYjpcHgYXbxQd2BugRf fpcfhHjUMZgdSicsLKL8YdKst65whZq6jgO2oQJg4GORwMJi6iiYX64fPAqUVgDzpfXWwkVQ 98zzOXaAxa5GAcdHwPQ0l8fxffjTYBZwZTWCcW2WNRQIjUt9+0ySOHUC3rZ4cXIQVBp0mEUG yg6Gf9pbZHwfCwzPcE4WgTpbzKUl0PFp0CoD7P615WQpzOuarMdqQ/B4fAPLR64l/3eVIVSN nJhkVh7DsD4K5q4nK5OzyYoYz9tKeQPa/zKmva6NZtS+E2VEFIkktqL8sNlwMV+WwqbKjQhI XOIoCu41hYtF0bLUNEaljFAlJzCsEbmQPImTyEe7cEtMxciSmHiGSWRUhy5G2jinI2ODtrUw 8nTo6JCbsrK8M/5MssE1b6DAz7BGvjru6m2fF+E3HRJW/2avbTrN84p2ItPDp6L2Q4178ANz vGOa81jAVnRUztS5ie2rxQZd2l5A/M4dh+brCnmY980lXeCUkvdjue2yb8iaR/Zki7q2buXJ TKtLYX9GWG4PG24g7a5JeGys7JQ7rmJl/wBs+fJiLgMAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrDLMWRmVeSWpSXmKPExsVy+t/xu7rCls/jDM4eVrV4MOUum0X3hxYm i+0rutgs3n3azmRxZ+9pdotZl5rYLZ7/ecVsMWXnDkaLTw9OsFicvrmZ3WLN14vMFlvP/GV0 4PH4tWApq8fiPS+ZPI7dnMbu8X7fVTaPvi2rGD1WP/nBFsAWpWdTlF9akqqQkV9cYqsUbWhh pGdoaaFnZGKpZ2hsHmtlZKqkb2eTkpqTWZZapG+XoJex48dppoJfrYwVZ7c6NjA2ZXYxcnJI CJhIXJvzjLmLkYtDSGApo8Sjie+BHA6ghITE6yfMEDXCEn+udbFB1HxmlHj34z87SIJNQEPi dMc8JpCEiMASJom9q84xgiSEBVwlLn9bygRiswioSjy72sAGYvMKWEo8vL4Vaqq8xOoNB8Bs TgEriYsHZ4ANFRLIlHg1/w4rhC0ncX3+F6YJjHwLGBlWMYqklhbnpucWG+oVJ+YWl+al6yXn 525iBIb8tmM/N+9gvLQx+BCjAAejEg+vReizOCHWxLLiytxDjBIczEoivE5nT8cJ8aYkVlal FuXHF5XmpBYfYjQFOnAis5Rocj4wHvNK4g1NDc0tLA3Njc2NzSyUxHk7BA7GCAmkJ5akZqem FqQWwfQxcXBKNTAGeTyZulBEcf+ksPUFh60/6lxzDvZIubnteLPmUfE1AnWr5A1jUr3M7/jt cue2WCzuEPbwxDPP1f5v9ExSPlz7k7Q/2qJW4Yif/iuPljVP3nhmzAtN8Tq52JBFu3rV59Ta vnXr5/IdvRa8M/XN4WtK3yaYJ7ybc69465bk/Utn/06IUtHau/a9EktxRqKhFnNRcSIARpRB OI8CAAA= X-CMS-MailID: 20200615090211eucas1p2f9951f582b14d602cbf4d51e228b12a0 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20200615090211eucas1p2f9951f582b14d602cbf4d51e228b12a0 X-EPHeader: CA CMS-TYPE: 201P X-CMS-RootMailID: 20200615090211eucas1p2f9951f582b14d602cbf4d51e228b12a0 References: <20200427095737.11082-1-i.dyukov@samsung.com> <20200615090158.18912-1-i.dyukov@samsung.com> Subject: [dpdk-dev] [PATCH v3 2/7] ethdev: add a link status text representation X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: i.dyukov@samsung.com List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This commit add function which treat link status structure and format it to text representation. Signed-off-by: Ivan Dyukov --- MAINTAINERS | 1 + app/test/Makefile | 3 + app/test/meson.build | 2 + app/test/test_ethdev_link.c | 253 +++++++++++++++++++++++++++++++++ lib/librte_ethdev/rte_ethdev.c | 163 +++++++++++++++++++++ lib/librte_ethdev/rte_ethdev.h | 52 +++++++ 6 files changed, 474 insertions(+) create mode 100644 app/test/test_ethdev_link.c diff --git a/MAINTAINERS b/MAINTAINERS index 6a14622a0..94c5cd58e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -378,6 +378,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 diff --git a/app/test/Makefile b/app/test/Makefile index 5b119aa61..14552073d 100644 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -249,6 +249,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 1715ddbcb..c5b742c15 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -38,6 +38,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', @@ -196,6 +197,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..9d04dfb81 --- /dev/null +++ b/app/test/test_ethdev_link.c @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + */ + +#include +#include + +#include +#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[128]; + ret = rte_eth_link_format(text, 128, NULL, &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at 2.5 Gbit/s 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_format(text, 128, NULL, &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at 10 Mbit/s HDX Fixed", + text, strlen(text), "Invalid default link status " + "string with HDX"); + + link_status.link_speed = ETH_SPEED_NUM_UNKNOWN, + ret = rte_eth_link_format(text, 128, NULL, &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format default string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("Link up at Unknown speed HDX Fixed", + text, strlen(text), "Invalid default link status " + "string with HDX"); + 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[128]; + ret = rte_eth_link_format(text, 128, NULL, &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_string_overflow(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[128]; + int i = 0; + for (i = 0; i < 128; i++) + text[i] = 'Y'; + + + ret = rte_eth_link_format(NULL, 2, "status %S, %G Gbits/s", + &link_status); + RTE_TEST_ASSERT(ret < 0, "Format string should fail, but it's ok\n"); + + ret = rte_eth_link_format(text, 2, "status %S, %G Gbits/s", + &link_status); + RTE_TEST_ASSERT(ret < 0, "Format string should fail, but it's ok\n"); + RTE_TEST_ASSERT(text[2] == 'Y', "String1 overflow\n"); + + ret = rte_eth_link_format(text, 8, NULL, + &link_status); + RTE_TEST_ASSERT(ret < 0, "Default format string should fail," + " but it's ok\n"); + RTE_TEST_ASSERT(text[8] == 'Y', "String1 overflow\n"); + + ret = rte_eth_link_format(text, 10, NULL, + &link_status); + RTE_TEST_ASSERT(ret < 0, "Default format string should fail," + " but it's ok\n"); + RTE_TEST_ASSERT(text[10] == 'Y', "String1 overflow\n"); + + ret = rte_eth_link_format(text, 2, "%S", + &link_status); + RTE_TEST_ASSERT(ret < 0, "Status string should fail, but it's ok\n"); + + return TEST_SUCCESS; +} + +static int32_t +test_link_status_format(void) +{ + int ret = 0; + struct rte_eth_link link_status = { + .link_speed = ETH_SPEED_NUM_40G, + .link_status = ETH_LINK_UP, + .link_autoneg = ETH_LINK_AUTONEG, + .link_duplex = ETH_LINK_FULL_DUPLEX + }; + char text[128]; + int i = 0; + for (i = 0; i < 128; i++) + text[i] = 'Y'; + ret = rte_eth_link_format(text, 128, "status = %S, duplex = %D\n", + &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("status = Up, duplex = FDX\n", + text, strlen(text), "Invalid status string1."); + + ret = rte_eth_link_format(text, 128, + "%A", + &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("Autoneg", + text, strlen(text), "Invalid status string2."); + + ret = rte_eth_link_format(text, 128, + "%G", + &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("40.0", + text, strlen(text), "Invalid status string3."); + return TEST_SUCCESS; +} + +static int32_t +test_link_status_return_value(void) +{ + int ret = 0; + struct rte_eth_link link_status = { + .link_speed = ETH_SPEED_NUM_40G, + .link_status = ETH_LINK_UP, + .link_autoneg = ETH_LINK_AUTONEG, + .link_duplex = ETH_LINK_FULL_DUPLEX + }; + char text[128]; + int i = 0; + for (i = 0; i < 128; i++) + text[i] = 'Y'; + ret = rte_eth_link_format(text, 128, "status = %S, ", + &link_status); + ret += rte_eth_link_format(text + ret, 128 - ret, + "%A", + &link_status); + ret += rte_eth_link_format(text + ret, 128 - ret, + ", duplex = %D\n", + &link_status); + ret += rte_eth_link_format(text + ret, 128 - ret, + "%M Mbits/s\n", + &link_status); + RTE_TEST_ASSERT(ret > 0, "Failed to format string\n"); + TEST_ASSERT_BUFFERS_ARE_EQUAL("status = Up, Autoneg, duplex = FDX\n" + "40000 Mbits/s\n", + text, strlen(text), "Invalid status string"); + + return TEST_SUCCESS; +} + +static int32_t +test_link_status_invalid_fmt(void) +{ + int ret = 0; + struct rte_eth_link link_status = { + .link_speed = ETH_SPEED_NUM_40G, + .link_status = ETH_LINK_UP, + .link_autoneg = ETH_LINK_AUTONEG, + .link_duplex = ETH_LINK_FULL_DUPLEX + }; + char text[128]; + ret = rte_eth_link_format(text, 128, "status = %", + &link_status); + RTE_TEST_ASSERT(ret < 0, "Status string1 should fail, but it's ok\n"); + ret = rte_eth_link_format(text, 128, + ", duplex = %d\n", + &link_status); + RTE_TEST_ASSERT(ret < 0, "Status string2 should fail, but it's ok\n"); + ret = rte_eth_link_format(text, 128, + "% Mbits/s\n", + &link_status); + RTE_TEST_ASSERT(ret < 0, "Status string3 should fail, but it's ok\n"); + + return TEST_SUCCESS; +} + +static int32_t +test_link_status_format_edges(void) +{ + int ret = 0; + struct rte_eth_link link_status = { + .link_speed = ETH_SPEED_NUM_UNKNOWN, + .link_status = ETH_LINK_DOWN, + .link_autoneg = ETH_LINK_AUTONEG, + .link_duplex = ETH_LINK_HALF_DUPLEX + }; + char text[128]; + ret = rte_eth_link_format(text, 4, "%S", &link_status); + RTE_TEST_ASSERT(ret < 0, "It should fail. No space for " + "zero terminator\n"); + ret = rte_eth_link_format(text, 6, "123%D", &link_status); + RTE_TEST_ASSERT(ret < 0, "It should fail. No space for " + "zero terminator\n"); + ret = rte_eth_link_format(text, 7, "%A", &link_status); + RTE_TEST_ASSERT(ret < 0, "It should fail. No space for " + "zero terminator\n"); + ret = rte_eth_link_format(text, 8, "%A", &link_status); + RTE_TEST_ASSERT(ret > 0, "It should ok, but it fails\n"); + return TEST_SUCCESS; +} +static struct unit_test_suite link_status_testsuite = { + .suite_name = "link status formating", + .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_status_string_overflow), + TEST_CASE(test_link_status_format), + TEST_CASE(test_link_status_format_edges), + TEST_CASE(test_link_status_invalid_fmt), + TEST_CASE(test_link_status_return_value), + 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 8e10a6fc3..108be1902 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -2385,6 +2385,169 @@ rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *eth_link) return 0; } +int +rte_eth_link_printf(const char *const fmt, + struct rte_eth_link *link) +{ + char text[200]; + int ret; + ret = rte_eth_link_format(text, 200, fmt, link); + printf("%s", text); + return ret; +} + +int +rte_eth_link_format(char *str, int32_t len, const char *const fmt, + struct rte_eth_link *link) +{ + int offset = 0; + int32_t clen = len; + const char *fmt_cur = fmt; + double gbits = (double)link->link_speed / 1000.; + /* TBD: make it international? */ + static const char LINK_DOWN_STR[] = "Link down"; + static const char LINK_UP_STR[] = "Link up at "; + static const char UNKNOWN_SPEED_STR[] = "Unknown speed"; + static const char MBITS_STR[] = "Mbit/s"; + static const char GBITS_STR[] = "Gbit/s"; + static const char AUTONEG_STR[] = "Autoneg"; + static const char FIXED_STR[] = "Fixed"; + static const char FDX_STR[] = "FDX"; + static const char HDX_STR[] = "HDX"; + static const char UNKNOWN_STR[] = "Unknown"; + static const char UP_STR[] = "Up"; + static const char DOWN_STR[] = "Down"; + if (str == NULL || len == 0) + return -1; + /* default format string, if no fmt is specified */ + if (fmt == NULL) { + if (link->link_status == ETH_LINK_DOWN) + return snprintf(str, (size_t)clen, "%s", LINK_DOWN_STR); + + offset = snprintf(str, (size_t)clen, "%s", LINK_UP_STR); + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + if (link->link_speed == ETH_SPEED_NUM_UNKNOWN) { + offset = snprintf(str, clen, "%s", + UNKNOWN_SPEED_STR); + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + } else { + if (link->link_speed < ETH_SPEED_NUM_1G) { + offset = snprintf(str, clen, + "%u %s", + link->link_speed, + MBITS_STR); + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + + } else { + offset = snprintf(str, clen, + "%.1f %s", + gbits, + GBITS_STR); + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + } + } + offset = snprintf(str, clen, " %s", link->link_duplex ? + FDX_STR : HDX_STR); + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + offset = snprintf(str, clen, " %s", link->link_autoneg ? + AUTONEG_STR : FIXED_STR); + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + /* Formated status */ + } else { + char c = *fmt_cur; + while (c) { + if (clen <= 0) + return -1; + if (c == '%') { + c = *++fmt_cur; + switch (c) { + /* Speed in Mbits/s */ + case 'M': + if (link->link_speed == + ETH_SPEED_NUM_UNKNOWN) + offset = snprintf(str, + clen, "%s", + UNKNOWN_STR); + else + offset = snprintf(str, + clen, "%u", + link->link_speed); + break; + /* Speed in Gbits/s */ + case 'G': + if (link->link_speed == + ETH_SPEED_NUM_UNKNOWN) + offset = snprintf(str, + clen, "%s", + UNKNOWN_STR); + else { + offset = snprintf(str, + clen, "%.1f", + gbits); + } + break; + /* Link status */ + case 'S': + offset = snprintf(str, clen, + "%s", + link->link_status ? + UP_STR : DOWN_STR); + break; + /* Link autoneg */ + case 'A': + offset = snprintf(str, clen, + "%s", + link->link_autoneg ? + AUTONEG_STR : + FIXED_STR); + break; + /* Link duplex */ + case 'D': + offset = snprintf(str, clen, + "%s", + link->link_duplex ? + FDX_STR : HDX_STR); + break; + /* Error cases */ + default: + return -1; + + } + if (offset < 0 || (clen - offset) <= 0) + return -1; + clen -= offset; + str += offset; + } else { + *str++ = c; + clen--; + } + c = *++fmt_cur; + } + } + /* teminate string */ + clen = len - clen; + *str = 0; + return clen; +} + 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..83291e656 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -2295,6 +2295,58 @@ 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); + +/** + * print formated link status to stdout. This function threats all + * special values like ETH_SPEED_NUM_UNKNOWN, ETH_LINK_DOWN etc. and convert + * them to textual representation. + * + * @param fmt + * Format string which allow to format link status. If NULL is provided + * , default formating will be applied. + * Following specifiers are available: + * - '%M' link speed in Mbits/s + * - '%G' link speed in Gbits/s + * - '%S' link status. e.g. Up or Down + * - '%A' link autonegotiation state + * - '%D' link duplex state + * @param link + * Link status provided by rte_eth_link_get function + * @return + * - Number of bytes written to stdout. In case of error, -1 is returned. + * + */ +int rte_eth_link_printf(const char *const fmt, + struct rte_eth_link *link); + +/** + * Format link status to textual representation. This function threats all + * special values like ETH_SPEED_NUM_UNKNOWN, ETH_LINK_DOWN etc. and convert + * them to textual representation. + * + * @param str + * A pointer to a string to be filled with textual representation of + * device status. + * @param len + * Length of available memory at 'str' string. + * @param fmt + * Format string which allow to format link status. If NULL is provided + * , default formating will be applied. + * Following specifiers are available: + * - '%M' link speed in Mbits/s + * - '%G' link speed in Gbits/s + * - '%S' link status. e.g. Up or Down + * - '%A' link autonegotiation state + * - '%D' link duplex state + * @param link + * Link status provided by rte_eth_link_get function + * @return + * - Number of bytes written to str array. In case of error, -1 is returned. + * + */ +int rte_eth_link_format(char *str, int32_t len, const char *const fmt, + struct rte_eth_link *eth_link); + /** * Retrieve the general I/O statistics of an Ethernet device. * -- 2.17.1