get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 109302,
    "url": "http://patches.dpdk.org/api/patches/109302/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220406151903.2916254-4-juraj.linkes@pantheon.tech/",
    "project": {
        "id": 1,
        "url": "http://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": "<20220406151903.2916254-4-juraj.linkes@pantheon.tech>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220406151903.2916254-4-juraj.linkes@pantheon.tech",
    "date": "2022-04-06T15:18:43",
    "name": "[RFC,v1,03/23] dts: merge DTS framework/pmd_output.py to DPDK",
    "commit_ref": null,
    "pull_url": null,
    "state": "rfc",
    "archived": true,
    "hash": "15162e1fcedc05fdc65f6ef5420c27ffe1114805",
    "submitter": {
        "id": 1626,
        "url": "http://patches.dpdk.org/api/people/1626/?format=api",
        "name": "Juraj Linkeš",
        "email": "juraj.linkes@pantheon.tech"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220406151903.2916254-4-juraj.linkes@pantheon.tech/mbox/",
    "series": [
        {
            "id": 22381,
            "url": "http://patches.dpdk.org/api/series/22381/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=22381",
            "date": "2022-04-06T15:18:40",
            "name": "merge DTS test resource files to DPDK",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/22381/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/109302/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/109302/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id E1C75A0509;\n\tWed,  6 Apr 2022 17:19:27 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 61A9B428A4;\n\tWed,  6 Apr 2022 17:19:11 +0200 (CEST)",
            "from lb.pantheon.sk (lb.pantheon.sk [46.229.239.20])\n by mails.dpdk.org (Postfix) with ESMTP id 06DAD42878\n for <dev@dpdk.org>; Wed,  6 Apr 2022 17:19:10 +0200 (CEST)",
            "from localhost (localhost [127.0.0.1])\n by lb.pantheon.sk (Postfix) with ESMTP id 0856C184FF0;\n Wed,  6 Apr 2022 17:19:08 +0200 (CEST)",
            "from lb.pantheon.sk ([127.0.0.1])\n by localhost (lb.pantheon.sk [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id LPtmJfUomrov; Wed,  6 Apr 2022 17:19:07 +0200 (CEST)",
            "from entguard.lab.pantheon.local (unknown [46.229.239.141])\n by lb.pantheon.sk (Postfix) with ESMTP id 2E240184FF1;\n Wed,  6 Apr 2022 17:19:05 +0200 (CEST)"
        ],
        "X-Virus-Scanned": "amavisd-new at siecit.sk",
        "From": "=?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>",
        "To": "thomas@monjalon.net, david.marchand@redhat.com,\n Honnappa.Nagarahalli@arm.com, ohilyard@iol.unh.edu, lijuan.tu@intel.com",
        "Cc": "dev@dpdk.org, =?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>",
        "Subject": "[RFC PATCH v1 03/23] dts: merge DTS framework/pmd_output.py to DPDK",
        "Date": "Wed,  6 Apr 2022 15:18:43 +0000",
        "Message-Id": "<20220406151903.2916254-4-juraj.linkes@pantheon.tech>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220406151903.2916254-1-juraj.linkes@pantheon.tech>",
        "References": "<20220406151903.2916254-1-juraj.linkes@pantheon.tech>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "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"
    },
    "content": "---\n dts/framework/pmd_output.py | 341 ++++++++++++++++++++++++++++++++++++\n 1 file changed, 341 insertions(+)\n create mode 100644 dts/framework/pmd_output.py",
    "diff": "diff --git a/dts/framework/pmd_output.py b/dts/framework/pmd_output.py\nnew file mode 100644\nindex 0000000000..f27c2513af\n--- /dev/null\n+++ b/dts/framework/pmd_output.py\n@@ -0,0 +1,341 @@\n+# BSD LICENSE\n+#\n+# Copyright(c) 2020 Intel Corporation. All rights reserved\n+# All rights reserved.\n+#\n+# Redistribution and use in source and binary forms, with or without\n+# modification, are permitted provided that the following conditions\n+# are met:\n+#\n+#   * Redistributions of source code must retain the above copyright\n+#     notice, this list of conditions and the following disclaimer.\n+#   * Redistributions in binary form must reproduce the above copyright\n+#     notice, this list of conditions and the following disclaimer in\n+#     the documentation and/or other materials provided with the\n+#     distribution.\n+#   * Neither the name of Intel Corporation nor the names of its\n+#     contributors may be used to endorse or promote products derived\n+#     from this software without specific prior written permission.\n+#\n+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+import os\n+import re\n+from time import sleep\n+\n+from .settings import PROTOCOL_PACKET_SIZE, TIMEOUT, get_nic_driver\n+from .utils import create_mask\n+\n+\n+class PmdOutput:\n+\n+    \"\"\"\n+    Module for get all statics value by port in testpmd\n+    \"\"\"\n+\n+    def __init__(self, dut, session=None):\n+        self.dut = dut\n+        if session is None:\n+            session = dut\n+        self.session = session\n+        self.dut.testpmd = self\n+        self.rx_pkts_prefix = \"RX-packets:\"\n+        self.rx_missed_prefix = \"RX-missed:\"\n+        self.rx_bytes_prefix = \"RX-bytes:\"\n+        self.rx_badcrc_prefix = \"RX-badcrc:\"\n+        self.rx_badlen_prefix = \"RX-badlen:\"\n+        self.rx_error_prefix = \"RX-errors:\"\n+        self.rx_nombuf_prefix = \"RX-nombuf:\"\n+        self.tx_pkts_prefix = \"TX-packets:\"\n+        self.tx_error_prefix = \"TX-errors:\"\n+        self.tx_bytes_prefix = \"TX-bytes:\"\n+        self.bad_ipcsum_prefix = \"Bad-ipcsum:\"\n+        self.bad_l4csum_prefix = \"Bad-l4csum:\"\n+        self.set_default_corelist()\n+\n+    def get_pmd_value(self, prefix, out):\n+        pattern = re.compile(prefix + \"(\\s+)([0-9]+)\")\n+        m = pattern.search(out)\n+        if m is None:\n+            return None\n+        else:\n+            return int(m.group(2))\n+\n+    def set_default_corelist(self):\n+        \"\"\"\n+        set default cores for start testpmd\n+        \"\"\"\n+        core_number = len(self.dut.cores)\n+        if core_number < 2:\n+            raise ValueError(f\"Not enough cores on DUT {self.dut}\")\n+        else:\n+            self.default_cores = \"1S/2C/1T\"\n+\n+    def get_pmd_stats(self, portid):\n+        stats = {}\n+        out = self.session.send_expect(\"show port stats %d\" % portid, \"testpmd> \")\n+        stats[\"RX-packets\"] = self.get_pmd_value(self.rx_pkts_prefix, out)\n+        stats[\"RX-missed\"] = self.get_pmd_value(self.rx_missed_prefix, out)\n+        stats[\"RX-bytes\"] = self.get_pmd_value(self.rx_bytes_prefix, out)\n+\n+        stats[\"RX-badcrc\"] = self.get_pmd_value(self.rx_badcrc_prefix, out)\n+        stats[\"RX-badlen\"] = self.get_pmd_value(self.rx_badlen_prefix, out)\n+        stats[\"RX-errors\"] = self.get_pmd_value(self.rx_error_prefix, out)\n+        stats[\"RX-nombuf\"] = self.get_pmd_value(self.rx_nombuf_prefix, out)\n+        stats[\"TX-packets\"] = self.get_pmd_value(self.tx_pkts_prefix, out)\n+        stats[\"TX-errors\"] = self.get_pmd_value(self.tx_error_prefix, out)\n+        stats[\"TX-bytes\"] = self.get_pmd_value(self.tx_bytes_prefix, out)\n+\n+        # display when testpmd config forward engine to csum\n+        stats[\"Bad-ipcsum\"] = self.get_pmd_value(self.bad_ipcsum_prefix, out)\n+        stats[\"Bad-l4csum\"] = self.get_pmd_value(self.bad_l4csum_prefix, out)\n+        return stats\n+\n+    def get_pmd_cmd(self):\n+        return self.command\n+\n+    def start_testpmd(\n+        self,\n+        cores=\"default\",\n+        param=\"\",\n+        eal_param=\"\",\n+        socket=0,\n+        fixed_prefix=False,\n+        expected=\"testpmd> \",\n+        timeout=120,\n+        **config,\n+    ):\n+        \"\"\"\n+        start testpmd with input parameters.\n+        :param cores: eg:\n+                cores='default'\n+                cores='1S/4C/1T'\n+        :param param: dpdk application (testpmd) parameters\n+        :param eal_param: user defined DPDK eal parameters, eg:\n+                eal_param='-a af:00.0 -a af:00.1,proto_xtr=vlan',\n+                eal_param='-b af:00.0 --file-prefix=vf0',\n+                eal_param='--no-pci',\n+        :param socket: physical CPU socket index\n+        :param fixed_prefix: use fixed file-prefix or not, when it is true,\n+               the file-prefix will not be added a timestamp\n+        :param config: kwargs user defined eal parameters, eg:\n+                set PCI allow list: ports=[0,1], port_options={0: \"proto_xtr=vlan\"},\n+                set PCI block list: b_ports=['0000:1a:00.0'],\n+                disable PCI: no_pci=True,\n+                add virtual device: vdevs=['net_vhost0,iface=vhost-net,queues=1']\n+        :return: output of launching testpmd\n+        \"\"\"\n+        eal_param = \" \" + eal_param + \" \"\n+        eal_param = eal_param.replace(\" -w \", \" -a \")\n+        re_file_prefix = \"--file-prefix[\\s*=]\\S+\\s\"\n+        file_prefix_str = re.findall(re_file_prefix, eal_param)\n+        if file_prefix_str:\n+            tmp = re.split(\"(=|\\s+)\", file_prefix_str[-1].strip())\n+            file_prefix = tmp[-1].strip()\n+            config[\"prefix\"] = file_prefix\n+        eal_param = re.sub(re_file_prefix, \"\", eal_param)\n+        config[\"other_eal_param\"] = eal_param\n+\n+        config[\"cores\"] = cores\n+        if (\n+            \" -w \" not in eal_param\n+            and \" -a \" not in eal_param\n+            and \" -b \" not in eal_param\n+            and \"ports\" not in config\n+            and \"b_ports\" not in config\n+            and \" --no-pci \" not in eal_param\n+            and (\n+                \"no_pci\" not in config\n+                or (\"no_pci\" in config and config[\"no_pci\"] != True)\n+            )\n+        ):\n+            config[\"ports\"] = [\n+                self.dut.ports_info[i][\"pci\"] for i in range(len(self.dut.ports_info))\n+            ]\n+        all_eal_param = self.dut.create_eal_parameters(\n+            fixed_prefix=fixed_prefix, socket=socket, **config\n+        )\n+\n+        app_name = self.dut.apps_name[\"test-pmd\"]\n+        command = app_name + \" %s -- -i %s\" % (all_eal_param, param)\n+        command = command.replace(\"  \", \" \")\n+        if self.session != self.dut:\n+            self.session.send_expect(\"cd %s\" % self.dut.base_dir, \"# \")\n+        out = self.session.send_expect(command, expected, timeout)\n+        self.command = command\n+        # wait 10s to ensure links getting up before test start.\n+        sleep(10)\n+        return out\n+\n+    def execute_cmd(\n+        self, pmd_cmd, expected=\"testpmd> \", timeout=TIMEOUT, alt_session=False\n+    ):\n+        if \"dut\" in str(self.session):\n+            return self.session.send_expect(\n+                \"%s\" % pmd_cmd, expected, timeout=timeout, alt_session=alt_session\n+            )\n+        else:\n+            return self.session.send_expect(\"%s\" % pmd_cmd, expected, timeout=timeout)\n+\n+    def get_output(self, timeout=1):\n+        if \"dut\" in str(self.session):\n+            return self.session.get_session_output(timeout=timeout)\n+        else:\n+            return self.session.get_session_before(timeout=timeout)\n+\n+    def get_value_from_string(self, key_str, regx_str, string):\n+        \"\"\"\n+        Get some values from the given string by the regular expression.\n+        \"\"\"\n+        pattern = r\"(?<=%s)%s\" % (key_str, regx_str)\n+        s = re.compile(pattern)\n+        res = s.search(string)\n+        if type(res).__name__ == \"NoneType\":\n+            return \" \"\n+        else:\n+            return res.group(0)\n+\n+    def get_all_value_from_string(self, key_str, regx_str, string):\n+        \"\"\"\n+        Get some values from the given string by the regular expression.\n+        \"\"\"\n+        pattern = r\"(?<=%s)%s\" % (key_str, regx_str)\n+        s = re.compile(pattern)\n+        res = s.findall(string)\n+        if type(res).__name__ == \"NoneType\":\n+            return \" \"\n+        else:\n+            return res\n+\n+    def get_detail_from_port_info(self, key_str, regx_str, port):\n+        \"\"\"\n+        Get the detail info from the output of pmd cmd 'show port info <port num>'.\n+        \"\"\"\n+        out = self.session.send_expect(\"show port info %d\" % port, \"testpmd> \")\n+        find_value = self.get_value_from_string(key_str, regx_str, out)\n+        return find_value\n+\n+    def get_port_mac(self, port_id):\n+        \"\"\"\n+        Get the specified port MAC.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\n+            \"MAC address: \", \"([0-9A-F]{2}:){5}[0-9A-F]{2}\", port_id\n+        )\n+\n+    def get_firmware_version(self, port_id):\n+        \"\"\"\n+        Get the firmware version.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Firmware-version: \", \"\\S.*\", port_id)\n+\n+    def get_port_connect_socket(self, port_id):\n+        \"\"\"\n+        Get the socket id which the specified port is connecting with.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Connect to socket: \", \"\\d+\", port_id)\n+\n+    def get_port_memory_socket(self, port_id):\n+        \"\"\"\n+        Get the socket id which the specified port memory is allocated on.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\n+            \"memory allocation on the socket: \", \"\\d+\", port_id\n+        )\n+\n+    def get_port_link_status(self, port_id):\n+        \"\"\"\n+        Get the specified port link status now.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Link status: \", \"\\S+\", port_id)\n+\n+    def get_port_link_speed(self, port_id):\n+        \"\"\"\n+        Get the specified port link speed now.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Link speed: \", \"\\d+\", port_id)\n+\n+    def get_port_link_duplex(self, port_id):\n+        \"\"\"\n+        Get the specified port link mode, duplex or simplex.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Link duplex: \", \"\\S+\", port_id)\n+\n+    def get_port_promiscuous_mode(self, port_id):\n+        \"\"\"\n+        Get the promiscuous mode of port.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Promiscuous mode: \", \"\\S+\", port_id)\n+\n+    def get_port_allmulticast_mode(self, port_id):\n+        \"\"\"\n+        Get the allmulticast mode of port.\n+        \"\"\"\n+        return self.get_detail_from_port_info(\"Allmulticast mode: \", \"\\S+\", port_id)\n+\n+    def check_tx_bytes(self, tx_bytes, exp_bytes=0):\n+        \"\"\"\n+        fortville nic will send lldp packet when nic setup with testpmd.\n+        so should used (tx_bytes - exp_bytes) % PROTOCOL_PACKET_SIZE['lldp']\n+        for check tx_bytes count right\n+        \"\"\"\n+        # error_flag is true means tx_bytes different with expect bytes\n+        error_flag = 1\n+        for size in PROTOCOL_PACKET_SIZE[\"lldp\"]:\n+            error_flag = error_flag and (tx_bytes - exp_bytes) % size\n+\n+        return not error_flag\n+\n+    def get_port_vlan_offload(self, port_id):\n+        \"\"\"\n+        Function: get the port vlan setting info.\n+        return value:\n+            'strip':'on'\n+            'filter':'on'\n+            'qinq':'off'\n+        \"\"\"\n+        vlan_info = {}\n+        vlan_info[\"strip\"] = self.get_detail_from_port_info(\"strip \", \"\\S+\", port_id)\n+        vlan_info[\"filter\"] = self.get_detail_from_port_info(\"filter\", \"\\S+\", port_id)\n+        vlan_info[\"qinq\"] = self.get_detail_from_port_info(\n+            \"qinq\\(extend\\) \", \"\\S+\", port_id\n+        )\n+        return vlan_info\n+\n+    def quit(self):\n+        self.session.send_expect(\"quit\", \"# \")\n+\n+    def wait_link_status_up(self, port_id, timeout=10):\n+        \"\"\"\n+        check the link status is up\n+        if not, loop wait\n+        \"\"\"\n+        for i in range(timeout):\n+            out = self.session.send_expect(\n+                \"show port info %s\" % str(port_id), \"testpmd> \"\n+            )\n+            status = self.get_all_value_from_string(\"Link status: \", \"\\S+\", out)\n+            if \"down\" not in status:\n+                break\n+            sleep(1)\n+        return \"down\" not in status\n+\n+    def get_max_rule_number(self, obj, out):\n+        res = re.search(\n+            r\"fd_fltr_guar\\s+=\\s+(\\d+).*fd_fltr_best_effort\\s+=\\s+(\\d+)\\.\", out\n+        )\n+        obj.verify(res, \"'fd_fltr_guar' and 'fd_fltr_best_effort not found'\")\n+        fltr_guar, fltr_best = res.group(1), res.group(2)\n+        max_rule = int(fltr_guar) + int(fltr_best)\n+        obj.logger.info(f\"this Card max rule number is :{max_rule}\")\n+        return max_rule\n",
    "prefixes": [
        "RFC",
        "v1",
        "03/23"
    ]
}