get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/73315/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 73315,
    "url": "https://patches.dpdk.org/api/patches/73315/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200706203743.29416-3-i.dyukov@samsung.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200706203743.29416-3-i.dyukov@samsung.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200706203743.29416-3-i.dyukov@samsung.com",
    "date": "2020-07-06T20:37:16",
    "name": "[v6,02/25] ethdev: add a link status text representation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "47f9cc8dbf686845d5305e29a27d6ae98ed671af",
    "submitter": {
        "id": 783,
        "url": "https://patches.dpdk.org/api/people/783/?format=api",
        "name": "Ivan Dyukov",
        "email": "i.dyukov@samsung.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200706203743.29416-3-i.dyukov@samsung.com/mbox/",
    "series": [
        {
            "id": 10825,
            "url": "https://patches.dpdk.org/api/series/10825/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=10825",
            "date": "2020-07-06T20:37:14",
            "name": "ethdev: allow unknown link speed",
            "version": 6,
            "mbox": "https://patches.dpdk.org/series/10825/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/73315/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/73315/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 85B5DA00C5;\n\tMon,  6 Jul 2020 22:38:15 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id EBACB1DD1D;\n\tMon,  6 Jul 2020 22:38:00 +0200 (CEST)",
            "from mailout2.w1.samsung.com (mailout2.w1.samsung.com\n [210.118.77.12]) by dpdk.org (Postfix) with ESMTP id 6CD861DD01\n for <dev@dpdk.org>; Mon,  6 Jul 2020 22:37:59 +0200 (CEST)",
            "from eucas1p2.samsung.com (unknown [182.198.249.207])\n by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id\n 20200706203758euoutp026455cce955f1005a4cc058111853b604~fREpDn8o21760817608euoutp02W;\n Mon,  6 Jul 2020 20:37:58 +0000 (GMT)",
            "from eusmges3new.samsung.com (unknown [203.254.199.245]) by\n eucas1p1.samsung.com (KnoxPortal) with ESMTP id\n 20200706203757eucas1p1e18af4b01670a92025ed1ed161de5ea2~fREoJyHMF2452524525eucas1p18;\n Mon,  6 Jul 2020 20:37:57 +0000 (GMT)",
            "from eucas1p2.samsung.com ( [182.198.249.207]) by\n eusmges3new.samsung.com (EUCPMTA) with SMTP id 2E.B6.06318.5AB830F5; Mon,  6\n Jul 2020 21:37:57 +0100 (BST)",
            "from eusmtrp1.samsung.com (unknown [182.198.249.138]) by\n eucas1p2.samsung.com (KnoxPortal) with ESMTPA id\n 20200706203757eucas1p2f59654f60db48ec7164aad3d29ad6dff~fREnxFSpt2126421264eucas1p2p;\n Mon,  6 Jul 2020 20:37:57 +0000 (GMT)",
            "from eusmgms1.samsung.com (unknown [182.198.249.179]) by\n eusmtrp1.samsung.com (KnoxPortal) with ESMTP id\n 20200706203757eusmtrp1bf933607d0fb02c1354191515ed08272~fREnwCuf32965829658eusmtrp1l;\n Mon,  6 Jul 2020 20:37:57 +0000 (GMT)",
            "from eusmtip1.samsung.com ( [203.254.199.221]) by\n eusmgms1.samsung.com (EUCPMTA) with SMTP id 7D.CF.06314.5AB830F5; Mon,  6\n Jul 2020 21:37:57 +0100 (BST)",
            "from idyukov.rnd.samsung.ru (unknown [106.109.129.29]) by\n eusmtip1.samsung.com (KnoxPortal) with ESMTPA id\n 20200706203755eusmtip1873f504ce548404fbb6eea689eb09010~fREl9Ed5S1560515605eusmtip18;\n Mon,  6 Jul 2020 20:37:55 +0000 (GMT)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com\n 20200706203758euoutp026455cce955f1005a4cc058111853b604~fREpDn8o21760817608euoutp02W",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com;\n s=mail20170921; t=1594067878;\n bh=vMec8EIsQzAulmX4sPhJTJM/231q/aaNJYVNXJvukBs=;\n h=From:To:Subject:Date:In-Reply-To:Reply-To:References:From;\n b=pivY/YD2dkYt9isW9P8GYgDD6XVJn/eueI8lfmkwy2YVTjVzZeZFVcd4UaSyBf4nT\n rTVgwblwzIFoTS/6CC/KVnwLy+NX80weE7KD2/xt8tmijCFlukF5ObIlzdqKlutCzb\n /zfma2aUpEwO1UQ93L6zBoeXANgHWZKwzRhXnmfM=",
        "X-AuditID": "cbfec7f5-371ff700000018ae-0e-5f038ba5a927",
        "From": "Ivan Dyukov <i.dyukov@samsung.com>",
        "To": "dev@dpdk.org, i.dyukov@samsung.com, v.kuramshin@samsung.com,\n thomas@monjalon.net, david.marchand@redhat.com, ferruh.yigit@intel.com,\n arybchenko@solarflare.com, wei.zhao1@intel.com, jia.guo@intel.com,\n beilei.xing@intel.com, qiming.yang@intel.com, wenzhuo.lu@intel.com,\n mb@smartsharesystems.com, stephen@networkplumber.org,\n nicolas.chautru@intel.com, bruce.richardson@intel.com,\n konstantin.ananyev@intel.com, cristian.dumitrescu@intel.com,\n radu.nicolau@intel.com, akhil.goyal@nxp.com, declan.doherty@intel.com,\n skori@marvell.com, pbhagavatula@marvell.com, jerinj@marvell.com,\n kirankumark@marvell.com, david.hunt@intel.com, anatoly.burakov@intel.com,\n xiaoyun.li@intel.com, jingjing.wu@intel.com, john.mcnamara@intel.com,\n jasvinder.singh@intel.com, byron.marohn@intel.com, yipeng1.wang@intel.com",
        "Date": "Mon,  6 Jul 2020 23:37:16 +0300",
        "Message-Id": "<20200706203743.29416-3-i.dyukov@samsung.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200706203743.29416-1-i.dyukov@samsung.com>",
        "X-Brightmail-Tracker": [
            "\n H4sIAAAAAAAAA0WSbUxTdxTG/d93Kl2u1cQTML50M0ODqNOYw2Z0TpPdxJn4YckSN8WqN0Ck\n YHrBgcQEnDRd2zEtxQ6cyCCKlClQUSoBg6ggVERhBpugdkQloENexA2tYy0Xs2+/85yX5/lw\n BFrn4KKE5NR02ZRqSNFzGuZy62TXijM2OmHV1J+rsPp2CcH+R+U0BpwPObSNHKXwgXsjNtb/\n yqLjcQ6F+Y5RCuvPWTl8ETjC4PBYPYV9TT4ei7uP8DjWMsDjT10nCQ4Eh2gsKh0n2FVyicXJ\n aw0cvgyWMZj/5j7Bn+tuEWyzjzLovOIlaLaKOFJZwWN530IcC9xi0Oe/yOPvE/dovHT7HcHj\n bdUEO81T7OdLpDelZ1ipvHGQkgp+u0dLrf4TvGRvL6Gk2mEvJb28ep+T8uvcROrot9FS1ZN/\n uO2aHZr1++SU5IOyaeWG3ZqkH50u9kCri2RWFx5jc0h3ppVECCCuhbGzV6gw68RzBCpdyVai\n CfErAjWBTlotxgkMF46T9xtlRV5ebVQQyLVYOLWYCBVP7Wx4ihNjwGcpocKNeWItB/XB3mmT\n ueKXYG9wMGFmxKWQO+mcPqsV48FV4GNVi0VQVdMc8haECPFTOHUzSs23EHpPv5q+CeJdAfKe\n Hp+JtAWGi2tolefCUFsdr/IC8BXYGZWz4W9PL68uWwg8KsubGdoIdc/v8GEzWlwG1Q0rVXkT\n XDgfnM4A4gfw4K85YZkOoeOya0bWgsWsU6f10NzePSMDvHsbqaIEvsHVavgmAm5b7DGyqPh/\n p1JC3GS+nKEYE2VlTar8fZxiMCoZqYlxe9OMHhL6VN+/bRNecjW4p4WIAtFHagMCnaBjDQeV\n LGMLAYHWz9N+0enbpdPuM2Qdkk1pCaaMFFlpIdECo5+vXVM2uFMnJhrS5f2yfEA2ve9SQkRU\n DunxR67VHs62GTN6thVFx+7qi58y1LbTnqb0bz57nTy+7qMbz/JGF7tHC2e99vc//zDO25P2\n wyff3nBGmga+/uro7OvN8UNO63dU6YbDVQkvLibtN271mswpStHpj/8YyZrjSfLMmqj45Xy0\n ee/SpnjKr2nMvNOxOXdx110PHROb3WHbpGeUJMPq5bRJMfwHkHAJZqUDAAA=",
            "\n H4sIAAAAAAAAAzWSa0hTYRjHe89tR2lxmlZvRmaDLhTNjqY+62JixE4fgiDrQ7c19KSWc7mz\n SdnNJMw2M10rs8uyRCoNzbQ0MdGBWi0TNbuaiRlRmbeUctjFJX37w+/3XOB5WFIxSvmx8Ykm\n 0ZioS1Ay3pTrd9O7ZYVWUru8vQtD6VMHgp6uAhK67e8YsA6eIOBV0VqoqbxMg+19KgFZtiEC\n Km9aGOjrTqOgf7iSgM6HLhlcbEuTwbDzkwxOt1xC8Gn8Cwl5+d8RtDju0TBWX83AwPh1CrLc\n HQjOVDxC0JQ5RIH9QRWCdAsHg7duyKCg0x+Gux9R4HpdLoPbo60k3Hv6C0FOUymC5vQ/dMR8\n wZ1fSAsFNZ8J4ey1VlJofH1eJmQ+dhBCWX8VIQzUdjBCVkUREp70WEmhuPcns8l7m2q10WA2\n iQFxBsm0RrmdhyAVrwZV0Aq1ig8O27kyKEQZGL46RkyITxaNgeG7VXGn7Ln0/sZcdKD0XDad\n itoOWJAXi7kV+HpelcyCvFkFV4iw44kbWRA7ATD+2ktOOj54/IWFmXS+I3zDnUl5AMMtxq4M\n B+EBvtxbBrefPP4P+HAanFlt+5cpbgE+PmZHnizn1Dj3rIue7DoPF9+pIz3DvLiV+EqDnycq\n uHj8ZkTmMRScP355dYTIRtPy0ZQi5CuaJX2sXuJVkk4vmRNjVdEG/V00cfL7jWPlVaitbLMT\n cSxSTpVnMKRWQeuSpYN6J8IsqfSVRza7dinkMbqDKaLRoDWaE0TJiUIm1ssh/WZEGyYeKNGk\n 5UP4MFDzYcFhwaGgnCXP4Op3KLhYnUncJ4r7ReP/OoL18ktF5y+7rCeSLxyu+zi9WBP+LTIn\n nR95PD1pfVTSOm0fO7tuzu/IVb9Co/ZE5Zk3Pj9kod0hgR+2rK/mfmxriFlkK6tn915S19gj\n skp6Rwe6A7D4Y+vCk0kpFefIF21HOkP7muc2zteod858WfJxYMN2a0TZ0c3jJQH6m9HPptYe\n W5rm1CgpKU7HLyGNku4vLeipCggDAAA="
        ],
        "X-CMS-MailID": "20200706203757eucas1p2f59654f60db48ec7164aad3d29ad6dff",
        "X-Msg-Generator": "CA",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "X-RootMTR": "20200706203757eucas1p2f59654f60db48ec7164aad3d29ad6dff",
        "X-EPHeader": "CA",
        "CMS-TYPE": "201P",
        "X-CMS-RootMailID": "20200706203757eucas1p2f59654f60db48ec7164aad3d29ad6dff",
        "References": "<20200427095737.11082-1-i.dyukov@samsung.com>\n <20200706203743.29416-1-i.dyukov@samsung.com>\n <CGME20200706203757eucas1p2f59654f60db48ec7164aad3d29ad6dff@eucas1p2.samsung.com>",
        "Subject": "[dpdk-dev] [PATCH v6 02/25] ethdev: add a link status text\n\trepresentation",
        "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 <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This commit add function which treat link status structure\nand format it to text representation.\n\nSigned-off-by: Ivan Dyukov <i.dyukov@samsung.com>\n---\n MAINTAINERS                              |   1 +\n app/test/Makefile                        |   3 +\n app/test/meson.build                     |   2 +\n app/test/test_ethdev_link.c              | 278 +++++++++++++++++++++++\n lib/librte_ethdev/rte_ethdev.c           | 169 ++++++++++++++\n lib/librte_ethdev/rte_ethdev.h           |  54 +++++\n lib/librte_ethdev/rte_ethdev_version.map |   4 +\n 7 files changed, 511 insertions(+)\n create mode 100644 app/test/test_ethdev_link.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 5e706cd7e..f4fb31ea2 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -393,6 +393,7 @@ T: git://dpdk.org/next/dpdk-next-net\n F: lib/librte_ethdev/\n F: devtools/test-null.sh\n F: doc/guides/prog_guide/switch_representation.rst\n+F: app/test/test_ethdev*\n \n Flow API\n M: Ori Kam <orika@mellanox.com>\ndiff --git a/app/test/Makefile b/app/test/Makefile\nindex e5440774b..9f43b8c3c 100644\n--- a/app/test/Makefile\n+++ b/app/test/Makefile\n@@ -251,6 +251,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) += test_security.c\n \n SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c test_ipsec_perf.c\n SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c\n+\n+SRCS-$(CONFIG_RTE_LIBRTE_ETHER) += test_ethdev_link.c\n+\n ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)\n LDLIBS += -lrte_ipsec\n endif\ndiff --git a/app/test/meson.build b/app/test/meson.build\nindex 56591db4e..6df31a4dc 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -39,6 +39,7 @@ test_sources = files('commands.c',\n \t'test_efd.c',\n \t'test_efd_perf.c',\n \t'test_errno.c',\n+\t'test_ethdev_link.c',\n \t'test_event_crypto_adapter.c',\n \t'test_event_eth_rx_adapter.c',\n \t'test_event_ring.c',\n@@ -199,6 +200,7 @@ fast_tests = [\n         ['eal_flags_misc_autotest', false],\n         ['eal_fs_autotest', true],\n         ['errno_autotest', true],\n+        ['ethdev_link_status' true],\n         ['event_ring_autotest', true],\n         ['fib_autotest', true],\n         ['fib6_autotest', true],\ndiff --git a/app/test/test_ethdev_link.c b/app/test/test_ethdev_link.c\nnew file mode 100644\nindex 000000000..6709323ef\n--- /dev/null\n+++ b/app/test/test_ethdev_link.c\n@@ -0,0 +1,278 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved\n+ */\n+\n+#include <rte_log.h>\n+#include <rte_ethdev.h>\n+\n+#include <rte_test.h>\n+#include \"test.h\"\n+\n+\n+static int32_t\n+test_link_status_up_default(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_2_5G,\n+\t\t.link_status = ETH_LINK_UP,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX\n+\t};\n+\tchar text[128];\n+\tret = rte_eth_link_strf(text, 128, NULL, &link_status);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format default string\\n\");\n+\tprintf(\"Default link up #1: %s\\n\", text);\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"Link up at 2.5 Gbit/s FDX Autoneg\\n\",\n+\t\ttext, strlen(text), \"Invalid default link status string\");\n+\n+\tlink_status.link_duplex = ETH_LINK_HALF_DUPLEX;\n+\tlink_status.link_autoneg = ETH_LINK_FIXED;\n+\tlink_status.link_speed = ETH_SPEED_NUM_10M,\n+\tret = rte_eth_link_strf(text, 128, NULL, &link_status);\n+\tprintf(\"Default link up #2: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format default string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"Link up at 10 Mbit/s HDX Fixed\\n\",\n+\t\ttext, strlen(text), \"Invalid default link status \"\n+\t\t\"string with HDX\");\n+\n+\tlink_status.link_speed = ETH_SPEED_NUM_UNKNOWN,\n+\tret = rte_eth_link_strf(text, 128, NULL, &link_status);\n+\tprintf(\"Default link up #3: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format default string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"Link up at Unknown speed HDX Fixed\\n\",\n+\t\ttext, strlen(text), \"Invalid default link status \"\n+\t\t\"string with HDX\");\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int32_t\n+test_link_status_down_default(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_2_5G,\n+\t\t.link_status = ETH_LINK_DOWN,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX\n+\t};\n+\tchar text[128];\n+\tret = rte_eth_link_strf(text, 128, NULL, &link_status);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format default string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"Link down\\n\",\n+\t\ttext, strlen(text), \"Invalid default link status string\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int32_t\n+test_link_status_string_overflow(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_2_5G,\n+\t\t.link_status = ETH_LINK_UP,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX\n+\t};\n+\tchar text[128];\n+\tint i = 0;\n+\tfor (i = 0; i < 128; i++)\n+\t\ttext[i] = 'Y';\n+\ttext[127] = '\\0';\n+\n+\tret = rte_eth_link_strf(NULL, 2, \"status %S, %G Gbits/s\",\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Format string should fail, but it's ok\\n\");\n+\n+\tret = rte_eth_link_strf(text, 2, \"status %S, %G Gbits/s\",\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Format string should fail, but it's ok\\n\");\n+\tRTE_TEST_ASSERT(text[2] == 'Y', \"String1 overflow\\n\");\n+\n+\tret = rte_eth_link_strf(text, 8, NULL,\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Default format string should fail,\"\n+\t\t\t\" but it's ok\\n\");\n+\tRTE_TEST_ASSERT(text[8] == 'Y', \"String1 overflow\\n\");\n+\n+\tret = rte_eth_link_strf(text, 10, NULL,\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Default format string should fail,\"\n+\t\t\t\" but it's ok\\n\");\n+\tRTE_TEST_ASSERT(text[10] == 'Y', \"String1 overflow\\n\");\n+\n+\ttext[1] = 'Y';\n+\tret = rte_eth_link_strf(text, 1, \"%S\",\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Status string should fail, but it's ok\\n\");\n+\tRTE_TEST_ASSERT(text[1] == 'Y', \"String1 overflow\\n\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int32_t\n+test_link_status_format(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_40G,\n+\t\t.link_status = ETH_LINK_UP,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX\n+\t};\n+\tchar text[128];\n+\tint i = 0;\n+\tfor (i = 0; i < 128; i++)\n+\t\ttext[i] = 'Y';\n+\ttext[127] = '\\0';\n+\tprintf(\"status format #1: %s\\n\", text);\n+\tret = rte_eth_link_strf(text, 128, \"status = %S, duplex = %D\\n\",\n+\t\t&link_status);\n+\tprintf(\"status format #2: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"status = Up, duplex = FDX\\n\",\n+\t\ttext, strlen(text), \"Invalid status string1.\");\n+\n+\tret = rte_eth_link_strf(text, 128, \"%A\", &link_status);\n+\tprintf(\"status format #3: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"Autoneg\",\n+\t\ttext, strlen(text), \"Invalid status string2.\");\n+\n+\tret = rte_eth_link_strf(text, 128,\n+\t\t\"%G\",\n+\t\t&link_status);\n+\tprintf(\"status format #4: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"40.0\",\n+\t\ttext, strlen(text), \"Invalid status string3.\");\n+\n+\tret = rte_eth_link_strf(text, 128,\n+\t\t\"%M\",\n+\t\t&link_status);\n+\tprintf(\"status format #5: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"40000\",\n+\t\ttext, strlen(text), \"Invalid status string4.\");\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int32_t\n+test_link_status_return_value(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_40G,\n+\t\t.link_status = ETH_LINK_UP,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX\n+\t};\n+\tchar text[128];\n+\tint i = 0;\n+\tfor (i = 0; i < 128; i++)\n+\t\ttext[i] = 'Y';\n+\ttext[127] = '\\0';\n+\tret = rte_eth_link_strf(text, 128, \"status = %S, \",\n+\t\t&link_status);\n+\tprintf(\"return value #1:ret=%u, text=%s\\n\", ret, text);\n+\tret += rte_eth_link_strf(text + ret, 128 - ret,\n+\t\t\"%A\",\n+\t\t&link_status);\n+\tprintf(\"return value #2:ret=%u, text=%s\\n\", ret, text);\n+\tret += rte_eth_link_strf(text + ret, 128 - ret,\n+\t\t\", duplex = %D\\n\",\n+\t\t&link_status);\n+\tprintf(\"return value #3:ret=%u, text=%s\\n\", ret, text);\n+\tret += rte_eth_link_strf(text + ret, 128 - ret,\n+\t\t\"%M Mbits/s\\n\",\n+\t\t&link_status);\n+\tprintf(\"return value #4:ret=%u, text=%s\\n\", ret, text);\n+\tRTE_TEST_ASSERT(ret > 0, \"Failed to format string\\n\");\n+\tTEST_ASSERT_BUFFERS_ARE_EQUAL(\"status = Up, Autoneg, duplex = FDX\\n\"\n+\t\t\"40000 Mbits/s\\n\",\n+\t\ttext, strlen(text), \"Invalid status string\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int32_t\n+test_link_status_invalid_fmt(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_40G,\n+\t\t.link_status = ETH_LINK_UP,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX\n+\t};\n+\tchar text[128];\n+\tret = rte_eth_link_strf(text, 128, \"status = %\",\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Status string1 should fail, but it's ok\\n\");\n+\tret = rte_eth_link_strf(text, 128,\n+\t\t\", duplex = %d\\n\",\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Status string2 should fail, but it's ok\\n\");\n+\tret = rte_eth_link_strf(text, 128,\n+\t\t\"% Mbits/s\\n\",\n+\t\t&link_status);\n+\tRTE_TEST_ASSERT(ret < 0, \"Status string3 should fail, but it's ok\\n\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int32_t\n+test_link_status_format_edges(void)\n+{\n+\tint ret = 0;\n+\tstruct rte_eth_link link_status = {\n+\t\t.link_speed = ETH_SPEED_NUM_UNKNOWN,\n+\t\t.link_status = ETH_LINK_DOWN,\n+\t\t.link_autoneg = ETH_LINK_AUTONEG,\n+\t\t.link_duplex = ETH_LINK_HALF_DUPLEX\n+\t};\n+\tchar text[128];\n+\tret = rte_eth_link_strf(text, 4, \"%S\", &link_status);\n+\tprintf(\"format edges #1: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret < 0, \"It should fail. No space for \"\n+\t\t\t\t \"zero terminator\\n\");\n+\tret = rte_eth_link_strf(text, 6, \"123%D\", &link_status);\n+\tprintf(\"format edges #2: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret < 0, \"It should fail. No space for \"\n+\t\t\t\t \"zero terminator\\n\");\n+\tret = rte_eth_link_strf(text, 7, \"%A\", &link_status);\n+\tprintf(\"format edges #3: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret < 0, \"It should fail. No space for \"\n+\t\t\t\t \"zero terminator\\n\");\n+\tret = rte_eth_link_strf(text, 8, \"%A\", &link_status);\n+\tprintf(\"format edges #4: %s\\n\", text);\n+\tRTE_TEST_ASSERT(ret > 0, \"It should ok, but it fails\\n\");\n+\treturn TEST_SUCCESS;\n+}\n+static struct unit_test_suite link_status_testsuite = {\n+\t.suite_name = \"link status formatting\",\n+\t.setup = NULL,\n+\t.teardown = NULL,\n+\t.unit_test_cases = {\n+\t\tTEST_CASE(test_link_status_up_default),\n+\t\tTEST_CASE(test_link_status_down_default),\n+\t\tTEST_CASE(test_link_status_string_overflow),\n+\t\tTEST_CASE(test_link_status_format),\n+\t\tTEST_CASE(test_link_status_format_edges),\n+\t\tTEST_CASE(test_link_status_invalid_fmt),\n+\t\tTEST_CASE(test_link_status_return_value),\n+\t\tTEST_CASES_END() /**< NULL terminate unit test array */\n+\t}\n+};\n+\n+static int\n+test_link_status(void)\n+{\n+\trte_log_set_global_level(RTE_LOG_DEBUG);\n+\trte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);\n+\n+\treturn unit_test_suite_runner(&link_status_testsuite);\n+}\n+\n+REGISTER_TEST_COMMAND(ethdev_link_status, test_link_status);\ndiff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c\nindex d06b7f9b1..2234af175 100644\n--- a/lib/librte_ethdev/rte_ethdev.c\n+++ b/lib/librte_ethdev/rte_ethdev.c\n@@ -2383,6 +2383,175 @@ rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *eth_link)\n \treturn 0;\n }\n \n+static int\n+rte_eth_link_strf_parser(char *str, size_t len, const char *const fmt,\n+\t\t\t   struct rte_eth_link *link)\n+{\n+\tsize_t offset = 0;\n+\tconst char *fmt_cur = fmt;\n+\tchar *str_cur = str;\n+\tdouble gbits = (double)link->link_speed / 1000.;\n+\tstatic const char AUTONEG_STR[]       = \"Autoneg\";\n+\tstatic const char FIXED_STR[]         = \"Fixed\";\n+\tstatic const char FDX_STR[]           = \"FDX\";\n+\tstatic const char HDX_STR[]           = \"HDX\";\n+\tstatic const char UNKNOWN_STR[]       = \"Unknown\";\n+\tstatic const char UP_STR[]            = \"Up\";\n+\tstatic const char DOWN_STR[]          = \"Down\";\n+\n+\tchar gbits_str[20];\n+\tchar mbits_str[20];\n+\t/* preformat complex formatting to easily concatinate it further */\n+\tsnprintf(mbits_str, 20, \"%u\", link->link_speed);\n+\tsnprintf(gbits_str, 20, \"%.1f\", gbits);\n+\t/* init str before formatting */\n+\tstr[0] = 0;\n+\twhile (*fmt_cur) {\n+\t\t/* check str bounds */\n+\t\tif (offset > (len - 1)) {\n+\t\t\tstr[len - 1] = '\\0';\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (*fmt_cur == '%') {\n+\t\t\t/* set null terminator to current position,\n+\t\t\t * it's required for strlcat\n+\t\t\t */\n+\t\t\t*str_cur = '\\0';\n+\t\t\tswitch (*++fmt_cur) {\n+\t\t\t/* Speed in Mbits/s */\n+\t\t\tcase 'M':\n+\t\t\t\tif (link->link_speed ==\n+\t\t\t\t    ETH_SPEED_NUM_UNKNOWN)\n+\t\t\t\t\toffset = strlcat(str, UNKNOWN_STR,\n+\t\t\t\t\t\t\t len);\n+\t\t\t\telse\n+\t\t\t\t\toffset = strlcat(str, mbits_str, len);\n+\t\t\t\tbreak;\n+\t\t\t/* Speed in Gbits/s */\n+\t\t\tcase 'G':\n+\t\t\t\tif (link->link_speed ==\n+\t\t\t\t    ETH_SPEED_NUM_UNKNOWN)\n+\t\t\t\t\toffset = strlcat(str, UNKNOWN_STR,\n+\t\t\t\t\t\t\t len);\n+\t\t\t\telse\n+\t\t\t\t\toffset = strlcat(str, gbits_str, len);\n+\t\t\t\tbreak;\n+\t\t\t/* Link status */\n+\t\t\tcase 'S':\n+\t\t\t\toffset = strlcat(str, link->link_status ?\n+\t\t\t\t\tUP_STR : DOWN_STR, len);\n+\t\t\t\tbreak;\n+\t\t\t/* Link autoneg */\n+\t\t\tcase 'A':\n+\t\t\t\toffset = strlcat(str, link->link_autoneg ?\n+\t\t\t\t\tAUTONEG_STR : FIXED_STR, len);\n+\t\t\t\tbreak;\n+\t\t\t/* Link duplex */\n+\t\t\tcase 'D':\n+\t\t\t\toffset = strlcat(str, link->link_duplex ?\n+\t\t\t\t\tFDX_STR : HDX_STR, len);\n+\t\t\t\tbreak;\n+\t\t\t/* Error cases */\n+\t\t\tdefault:\n+\t\t\t\treturn -1;\n+\n+\t\t\t}\n+\t\t\tif (offset > (len - 1))\n+\t\t\t\treturn -1;\n+\n+\t\t\tstr_cur = str + offset;\n+\t\t} else {\n+\t\t\t*str_cur++ = *fmt_cur;\n+\t\t\toffset++;\n+\t\t}\n+\t\tfmt_cur++;\n+\t}\n+\t*str_cur = '\\0';\n+\treturn offset;\n+}\n+\n+int\n+rte_eth_link_printf(const char *const fmt,\n+\t\t    struct rte_eth_link *link)\n+{\n+\tchar text[200];\n+\tint ret;\n+\tret = rte_eth_link_strf(text, 200, fmt, link);\n+\tif (ret > 0)\n+\t\tprintf(\"%s\", text);\n+\treturn ret;\n+}\n+\n+int\n+rte_eth_link_strf(char *str, size_t len, const char *const fmt,\n+\t\t    struct rte_eth_link *link)\n+{\n+\tsize_t offset = 0;\n+\tdouble gbits = (double)link->link_speed / 1000.;\n+\tchar gbits_str[20];\n+\tchar mbits_str[20];\n+\t/* TBD: make it international? */\n+\tstatic const char LINK_DOWN_STR[]     = \"Link down\\n\";\n+\tstatic const char LINK_UP_STR[]       = \"Link up at \";\n+\tstatic const char UNKNOWN_SPEED_STR[] = \"Unknown speed \";\n+\tstatic const char MBITS_STR[]\t      = \"Mbit/s\";\n+\tstatic const char GBITS_STR[]\t      = \"Gbit/s\";\n+\tstatic const char FDX_STR[]           = \"FDX \";\n+\tstatic const char HDX_STR[]           = \"HDX \";\n+\t/* autoneg is latest param in default string, so add '\\n' */\n+\tstatic const char AUTONEG_STR[]       = \"Autoneg\\n\";\n+\tstatic const char FIXED_STR[]         = \"Fixed\\n\";\n+\tif (str == NULL || len == 0)\n+\t\treturn -1;\n+\t/* default format string, if no fmt is specified */\n+\tif (fmt == NULL) {\n+\t\tif (link->link_status == ETH_LINK_DOWN) {\n+\t\t\tif (sizeof(LINK_DOWN_STR) > len)\n+\t\t\t\treturn -1;\n+\t\t\treturn strlcpy(str, LINK_DOWN_STR, len);\n+\t\t}\n+\n+\t\t/* preformat complex strings to easily concatinate it further */\n+\t\tsnprintf(mbits_str, 20, \"%u %s \", link->link_speed, MBITS_STR);\n+\t\tsnprintf(gbits_str, 20, \"%.1f %s \", gbits, GBITS_STR);\n+\n+\t\toffset = strlcpy(str, LINK_UP_STR, len);\n+\t\t/* reserve one byte to null terminator */\n+\t\tif (offset > (len - 1))\n+\t\t\treturn -1;\n+\t\t/* link speed */\n+\t\tif (link->link_speed == ETH_SPEED_NUM_UNKNOWN) {\n+\t\t\toffset = strlcat(str, UNKNOWN_SPEED_STR, len);\n+\t\t\tif (offset > (len - 1))\n+\t\t\t\treturn -1;\n+\t\t} else {\n+\t\t\tif (link->link_speed < ETH_SPEED_NUM_1G) {\n+\t\t\t\toffset = strlcat(str, mbits_str, len);\n+\t\t\t\tif (offset > (len - 1))\n+\t\t\t\t\treturn -1;\n+\t\t\t} else {\n+\t\t\t\toffset = strlcat(str, gbits_str, len);\n+\t\t\t\tif (offset > (len - 1))\n+\t\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t\t/* link duplex */\n+\t\toffset = strlcat(str, link->link_duplex ?\n+\t\t\t       FDX_STR : HDX_STR, len);\n+\t\tif (offset > (len - 1))\n+\t\t\treturn -1;\n+\t\t/* link autonegotiation */\n+\t\toffset = strlcat(str, link->link_autoneg ?\n+\t\t\t       AUTONEG_STR : FIXED_STR, len);\n+\t\tif (offset > (len - 1))\n+\t\t\treturn -1;\n+\t/* Formatted status */\n+\t} else\n+\t\toffset = rte_eth_link_strf_parser(str, len, fmt, link);\n+\n+\treturn offset;\n+}\n+\n int\n rte_eth_stats_get(uint16_t port_id, struct rte_eth_stats *stats)\n {\ndiff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h\nindex 2090af501..974fee591 100644\n--- a/lib/librte_ethdev/rte_ethdev.h\n+++ b/lib/librte_ethdev/rte_ethdev.h\n@@ -2295,6 +2295,60 @@ int rte_eth_link_get(uint16_t port_id, struct rte_eth_link *link);\n  */\n int rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *link);\n \n+\n+/**\n+ * print formatted link status to stdout. This function threats all\n+ * special values like ETH_SPEED_NUM_UNKNOWN, ETH_LINK_DOWN etc. and convert\n+ * them to textual representation.\n+ *\n+ * @param fmt\n+ *   Format string which allow to format link status. If NULL is provided\n+ *   , default formatting will be applied.\n+ *   Following specifiers are available:\n+ *    - '%M' link speed in Mbits/s\n+ *    - '%G' link speed in Gbits/s\n+ *    - '%S' link status. e.g. Up or Down\n+ *    - '%A' link autonegotiation state\n+ *    - '%D' link duplex state\n+ * @param link\n+ *   Link status provided by rte_eth_link_get function\n+ * @return\n+ *   - Number of bytes written to stdout. In case of error, -1 is returned.\n+ *\n+ */\n+__rte_experimental\n+int rte_eth_link_printf(const char *const fmt,\n+\t\t\tstruct rte_eth_link *link);\n+\n+/**\n+ * Format link status to textual representation. This function threats all\n+ * special values like ETH_SPEED_NUM_UNKNOWN, ETH_LINK_DOWN etc. and convert\n+ * them to textual representation.\n+ *\n+ * @param str\n+ *   A pointer to a string to be filled with textual representation of\n+ *   device status.\n+ * @param len\n+ *   Length of available memory at 'str' string.\n+ * @param fmt\n+ *   Format string which allow to format link status. If NULL is provided\n+ *   , default formatting will be applied.\n+ *   Following specifiers are available:\n+ *    - '%M' link speed in Mbits/s\n+ *    - '%G' link speed in Gbits/s\n+ *    - '%S' link status. e.g. Up or Down\n+ *    - '%A' link autonegotiation state\n+ *    - '%D' link duplex state\n+ * @param link\n+ *   Link status provided by rte_eth_link_get function\n+ * @return\n+ *   - Number of bytes written to str array. In case of error, -1 is returned.\n+ *\n+ */\n+__rte_experimental\n+int rte_eth_link_strf(char *str, size_t len, const char *const fmt,\n+\t\t\tstruct rte_eth_link *eth_link);\n+\n /**\n  * Retrieve the general I/O statistics of an Ethernet device.\n  *\ndiff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map\nindex 715505604..6c80597d1 100644\n--- a/lib/librte_ethdev/rte_ethdev_version.map\n+++ b/lib/librte_ethdev/rte_ethdev_version.map\n@@ -241,4 +241,8 @@ EXPERIMENTAL {\n \t__rte_ethdev_trace_rx_burst;\n \t__rte_ethdev_trace_tx_burst;\n \trte_flow_get_aged_flows;\n+\n+\t# added in 20.08\n+\trte_eth_link_strf;\n+\trte_eth_link_printf;\n };\n",
    "prefixes": [
        "v6",
        "02/25"
    ]
}