Show a patch.

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

{
    "id": 44465,
    "url": "http://patches.dpdk.org/api/patches/44465/?format=api",
    "web_url": "http://patches.dpdk.org/patch/44465/",
    "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"
    },
    "msgid": "<20180910054547.18494-4-david.marchand@6wind.com>",
    "date": "2018-09-10T05:45:47",
    "name": "[3/3] app/testpmd: add sanity checks on received/sent packets",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "f5771f599f4d2ba215e06a0b29642c56cf764aba",
    "submitter": {
        "id": 3,
        "url": "http://patches.dpdk.org/api/people/3/?format=api",
        "name": "David Marchand",
        "email": "david.marchand@6wind.com"
    },
    "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/patch/44465/mbox/",
    "series": [
        {
            "id": 1241,
            "url": "http://patches.dpdk.org/api/series/1241/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1241",
            "date": "2018-09-10T05:45:44",
            "name": "segment sanity checks",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/1241/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/44465/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/44465/checks/",
    "tags": {},
    "headers": {
        "X-Mailer": "git-send-email 2.17.1",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "From": "David Marchand <david.marchand@6wind.com>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=rXgcIL4PPWW2Qlra3wC6GonhaJ7cBMGi+7KbcbFBZJ4=;\n\tb=TUr1/a8ptl9QLH1/DVPKjC2faWTeaQf0eTqDaDr/WgCvKjPpQin7zTjniMSpGR4/uM\n\tUOeQ7Rsui73Cj40EABYe6vv2GM3LJ/WOMQpwVKxObQHnEaAN2qLmWXothaKcmtfQaAET\n\t7aEp5lEdNU6U7aYPv5MkMLDmW03YAn4VbcRvS4n2rhK/yjS34izgujo9ESAdug25WDWR\n\toVG+4k4CM4cpHdYRAfvfikAyWTraUCfuNy+MLkkKtubFLhZKxA8hAABbtiJzg/zk9B4E\n\t4fw3ZR2itO9YWuO0cx0vEwX82TPP9l5bLaxAc4HCr4K7WNPHf59Sm08I9jiDNBPwygx+\n\t0Tlg==",
        "X-Mailman-Version": "2.1.15",
        "Delivered-To": "patchwork@dpdk.org",
        "X-Gm-Message-State": "APzg51AJB+C6kpczGbW/uymnrh0Fo7/uVEKiRcEpPk2jEma9yANy+k/L\n\t3Wn7NFHlkp0fYX89A+BZbfdcj+mC2kg=",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Cc": "olivier.matz@6wind.com, wenzhuo.lu@intel.com, jingjing.wu@intel.com,\n\tbernard.iremonger@intel.com",
        "To": "dev@dpdk.org",
        "Errors-To": "dev-bounces@dpdk.org",
        "References": "<20180910054547.18494-1-david.marchand@6wind.com>",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=rXgcIL4PPWW2Qlra3wC6GonhaJ7cBMGi+7KbcbFBZJ4=;\n\tb=WtPmMULVLI8pkHROYUCYItrxX/rHxTNM3SC3W/IWD2BFNVwKwGIOE7hseVNg1eKf9y\n\tTQRHT0nitjgb6adhAJmpxdoKSJxOml79tCKoi1takc0z3TR/2X761yzByOErvHdiBVvc\n\t7kx5QR69Hzn8m/083zOmqcRCHNlekOs4wsXtlvm9k3CxObXAx3EZRUrMgkb/dYUezp6E\n\t8DSlznRqzjVS4+UY3BEXFm4AnjDIByHF1V/r+qrh/bTkhcXEUzh43hVDBtCE42j9V9t5\n\tii3ZR0qAEo0ZsqZbXdt4ANJZkjuKfYSs35PacFA/P4KMpsFE8ojGHN3f1G+00B3Yzc7k\n\tw0MA==",
        "Return-Path": "<dev-bounces@dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 1E4014CB5;\n\tMon, 10 Sep 2018 07:46:02 +0200 (CEST)",
            "from mail-wm0-f65.google.com (mail-wm0-f65.google.com\n\t[74.125.82.65]) by dpdk.org (Postfix) with ESMTP id 8444D4CB3\n\tfor <dev@dpdk.org>; Mon, 10 Sep 2018 07:46:00 +0200 (CEST)",
            "by mail-wm0-f65.google.com with SMTP id 207-v6so19887067wme.5\n\tfor <dev@dpdk.org>; Sun, 09 Sep 2018 22:46:00 -0700 (PDT)",
            "from 6wind.com ([109.190.253.16]) by smtp.gmail.com with ESMTPSA id\n\tt4-v6sm14667473wrb.45.2018.09.09.22.45.57\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tSun, 09 Sep 2018 22:45:59 -0700 (PDT)"
        ],
        "Date": "Mon, 10 Sep 2018 07:45:47 +0200",
        "X-Received": "by 2002:a1c:9290:: with SMTP id\n\tu138-v6mr12351534wmd.52.1536558359737; \n\tSun, 09 Sep 2018 22:45:59 -0700 (PDT)",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>",
        "Subject": "[dpdk-dev] [PATCH 3/3] app/testpmd: add sanity checks on\n\treceived/sent packets",
        "In-Reply-To": "<20180910054547.18494-1-david.marchand@6wind.com>",
        "Message-Id": "<20180910054547.18494-4-david.marchand@6wind.com>",
        "Precedence": "list",
        "X-BeenThere": "dev@dpdk.org",
        "X-Original-To": "patchwork@dpdk.org",
        "X-Google-Smtp-Source": "ANB0VdYifXA44nRsfTHR5zPZOo+fhv2yaQU1zhW3Gzu4gD6jRW9JgrxLmJP+1PP7t2iIZ8KbdoLrdw=="
    },
    "content": "Make use of the newly introduced rte_mbuf_check() to (optionally) check\nall packets received/sent through a port.\nThe idea behind this is to help to quickly identify badly formatted mbufs\ncoming from the pmd on the rx side, and from the application on the tx\nside.\nSetting the verbose level to some > 0 value will dump all packets in the\nassociated rx/tx callback to further help in the debugging.\n\nSigned-off-by: David Marchand <david.marchand@6wind.com>\n---\n app/test-pmd/cmdline.c    |  63 +++++++++++++++++++\n app/test-pmd/config.c     |  23 +++++++\n app/test-pmd/parameters.c |   7 +++\n app/test-pmd/testpmd.c    | 123 ++++++++++++++++++++++++++++++++++++++\n app/test-pmd/testpmd.h    |   9 +++\n 5 files changed, 225 insertions(+)",
    "diff": "diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex 589121d69..1de533999 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -912,6 +912,9 @@ static void cmd_help_long_parsed(void *parsed_result,\n \n \t\t\t\"port config (port_id) udp_tunnel_port add|rm vxlan|geneve (udp_port)\\n\\n\"\n \t\t\t\"    Add/remove UDP tunnel port for tunneling offload\\n\\n\"\n+\n+\t\t\t\"port config all sanity_check (none|rx|tx|rx+tx)\\n\\n\"\n+\t\t\t\"    Configure sanity checks\\n\\n\"\n \t\t);\n \t}\n \n@@ -17602,6 +17605,65 @@ cmdline_parse_inst_t cmd_config_per_queue_tx_offload = {\n \t}\n };\n \n+/* *** configure sanity check for all ports *** */\n+struct cmd_config_sanity_check_all {\n+\tcmdline_fixed_string_t port;\n+\tcmdline_fixed_string_t keyword;\n+\tcmdline_fixed_string_t all;\n+\tcmdline_fixed_string_t sanity_check;\n+\tcmdline_fixed_string_t mode;\n+};\n+\n+static void\n+cmd_config_sanity_check_all_parsed(void *parsed_result,\n+\t__rte_unused struct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_config_sanity_check_all *res = parsed_result;\n+\tportid_t pid;\n+\n+\tif (!all_ports_stopped()) {\n+\t\tprintf(\"Please stop all ports first\\n\");\n+\t\treturn;\n+\t}\n+\n+\tif (set_sanity_checks(res->mode) < 0)\n+\t\treturn;\n+\n+\tRTE_ETH_FOREACH_DEV(pid)\n+\t\tports[pid].sanity_checks = sanity_checks;\n+\n+\tcmd_reconfig_device_queue(RTE_PORT_ALL, 0, 1);\n+}\n+\n+cmdline_parse_token_string_t cmd_config_sanity_check_all_port =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, port, \"port\");\n+cmdline_parse_token_string_t cmd_config_sanity_check_all_keyword =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_config_sanity_check_all, keyword,\n+\t\t\"config\");\n+cmdline_parse_token_string_t cmd_config_sanity_check_all_all =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_config_sanity_check_all, all,\n+\t\t\"all\");\n+cmdline_parse_token_string_t cmd_config_sanity_check_all_sanity_check =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_config_sanity_check_all,\n+\t\tsanity_check, \"sanity_check\");\n+cmdline_parse_token_string_t cmd_config_sanity_check_all_mode =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_config_sanity_check_all, mode,\n+\t\t\"none#rx#tx#rx+tx\");\n+\n+cmdline_parse_inst_t cmd_config_sanity_check_all = {\n+\t.f = cmd_config_sanity_check_all_parsed,\n+\t.data = NULL,\n+\t.help_str = \"port config all sanity_check none|rx|tx|rx+tx\",\n+\t.tokens = {\n+\t\t(void *)&cmd_config_sanity_check_all_port,\n+\t\t(void *)&cmd_config_sanity_check_all_keyword,\n+\t\t(void *)&cmd_config_sanity_check_all_all,\n+\t\t(void *)&cmd_config_sanity_check_all_sanity_check,\n+\t\t(void *)&cmd_config_sanity_check_all_mode,\n+\t\tNULL,\n+\t},\n+};\n+\n /* ******************************************************************************** */\n \n /* list of instructions */\n@@ -17863,6 +17925,7 @@ cmdline_parse_ctx_t main_ctx[] = {\n \t(cmdline_parse_inst_t *)&cmd_tx_offload_get_configuration,\n \t(cmdline_parse_inst_t *)&cmd_config_per_port_tx_offload,\n \t(cmdline_parse_inst_t *)&cmd_config_per_queue_tx_offload,\n+\t(cmdline_parse_inst_t *)&cmd_config_sanity_check_all,\n #ifdef RTE_LIBRTE_BPF\n \t(cmdline_parse_inst_t *)&cmd_operate_bpf_ld_parse,\n \t(cmdline_parse_inst_t *)&cmd_operate_bpf_unld_parse,\ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex 14ccd6864..f34327d02 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -1849,6 +1849,9 @@ rxtx_config_display(void)\n \t\tprintf(\"  port %d: RX queue number: %d Tx queue number: %d\\n\",\n \t\t\t\t(unsigned int)pid, nb_rxq, nb_txq);\n \n+\t\tif (ports[pid].sanity_checks & SANITY_CHECK_RX)\n+\t\t\tprintf(\"    RX sanity checks enabled\\n\");\n+\n \t\tprintf(\"    Rx offloads=0x%\"PRIx64\" Tx offloads=0x%\"PRIx64\"\\n\",\n \t\t\t\tports[pid].dev_conf.rxmode.offloads,\n \t\t\t\tports[pid].dev_conf.txmode.offloads);\n@@ -1873,6 +1876,9 @@ rxtx_config_display(void)\n \t\t\t\trx_conf[qid].offloads);\n \t\t}\n \n+\t\tif (ports[pid].sanity_checks & SANITY_CHECK_TX)\n+\t\t\tprintf(\"    TX sanity checks enabled\\n\");\n+\n \t\t/* per tx queue config only for first queue to be less verbose */\n \t\tfor (qid = 0; qid < 1; qid++) {\n \t\t\trc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo);\n@@ -3827,3 +3833,20 @@ port_queue_region_info_display(portid_t port_id, void *buf)\n \n \tprintf(\"\\n\\n\");\n }\n+\n+int\n+set_sanity_checks(const char *arg)\n+{\n+\tif (!strcmp(arg, \"rx\")) {\n+\t\tsanity_checks = SANITY_CHECK_RX;\n+\t\treturn 0;\n+\t} else if (!strcmp(arg, \"tx\")) {\n+\t\tsanity_checks = SANITY_CHECK_TX;\n+\t\treturn 0;\n+\t} else if (!strcmp(arg, \"rx+tx\")) {\n+\t\tsanity_checks =\n+\t\t\tSANITY_CHECK_RX|SANITY_CHECK_TX;\n+\t\treturn 0;\n+\t} else\n+\t\treturn -1;\n+}\ndiff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c\nindex 962fad789..5a06dc592 100644\n--- a/app/test-pmd/parameters.c\n+++ b/app/test-pmd/parameters.c\n@@ -190,6 +190,7 @@ usage(char* progname)\n \tprintf(\"  --vxlan-gpe-port=N: UPD port of tunnel VXLAN-GPE\\n\");\n \tprintf(\"  --mlockall: lock all memory\\n\");\n \tprintf(\"  --no-mlockall: do not lock all memory\\n\");\n+\tprintf(\"  --sanity-checks <rx|tx|rx+tx>: enable rx/tx sanity checks on mbuf\\n\");\n }\n \n #ifdef RTE_LIBRTE_CMDLINE\n@@ -625,6 +626,7 @@ launch_args_parse(int argc, char** argv)\n \t\t{ \"vxlan-gpe-port\",\t\t1, 0, 0 },\n \t\t{ \"mlockall\",\t\t\t0, 0, 0 },\n \t\t{ \"no-mlockall\",\t\t0, 0, 0 },\n+\t\t{ \"sanity-checks\",\t\t1, 0, 0 },\n \t\t{ 0, 0, 0, 0 },\n \t};\n \n@@ -1147,6 +1149,11 @@ launch_args_parse(int argc, char** argv)\n \t\t\t\tdo_mlockall = 1;\n \t\t\tif (!strcmp(lgopts[opt_idx].name, \"no-mlockall\"))\n \t\t\t\tdo_mlockall = 0;\n+\t\t\tif (!strcmp(lgopts[opt_idx].name, \"sanity-checks\")) {\n+\t\t\t\tif (set_sanity_checks(optarg) < 0)\n+\t\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\t \"invalid sanity-checks argument\\n\");\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase 'h':\n \t\t\tusage(argv[0]);\ndiff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c\nindex ee48db2a3..a310431eb 100644\n--- a/app/test-pmd/testpmd.c\n+++ b/app/test-pmd/testpmd.c\n@@ -210,6 +210,9 @@ uint8_t dcb_test = 0;\n queueid_t nb_rxq = 1; /**< Number of RX queues per port. */\n queueid_t nb_txq = 1; /**< Number of TX queues per port. */\n \n+/* Sanity checks configuration */\n+uint8_t sanity_checks;\n+\n /*\n  * Configurable number of RX/TX ring descriptors.\n  * Defaults are supplied by drivers via ethdev.\n@@ -769,6 +772,9 @@ init_config(void)\n \t\t\tport->tx_conf[k].offloads =\n \t\t\t\tport->dev_conf.txmode.offloads;\n \n+\t\t/* Configure sanity checks with initial value from cmdline */\n+\t\tport->sanity_checks = sanity_checks;\n+\n \t\t/* set flag to initialize port/queue */\n \t\tport->need_reconfig = 1;\n \t\tport->need_reconfig_queues = 1;\n@@ -1632,6 +1638,59 @@ port_is_closed(portid_t port_id)\n \treturn 1;\n }\n \n+static uint16_t\n+mbuf_tx_check(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],\n+\t      uint16_t nb_pkts, __rte_unused void *user_param)\n+{\n+\tunsigned int count = 0;\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tconst char *reason;\n+\n+\t\tif (verbose_level > 0)\n+\t\t\trte_pktmbuf_dump(stdout, pkts[i], 0);\n+\n+\t\tif (!rte_mbuf_check(pkts[i], 1, &reason)) {\n+\t\t\tpkts[count++] = pkts[i];\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tTESTPMD_LOG(ERR, \"invalid tx mbuf on port %\"PRIu16\" queue %\"\n+\t\t\t    PRIu16\": %s\\n\", port_id, queue, reason);\n+\t\trte_pktmbuf_free(pkts[i]);\n+\t}\n+\n+\treturn count;\n+}\n+\n+static uint16_t\n+mbuf_rx_check(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],\n+\t      uint16_t nb_pkts, __rte_unused uint16_t max_pkts,\n+\t      __rte_unused void *user_param)\n+{\n+\tunsigned int count = 0;\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tconst char *reason;\n+\n+\t\tif (verbose_level > 0)\n+\t\t\trte_pktmbuf_dump(stdout, pkts[i], 0);\n+\n+\t\tif (!rte_mbuf_check(pkts[i], 1, &reason)) {\n+\t\t\tpkts[count++] = pkts[i];\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tTESTPMD_LOG(ERR, \"invalid rx mbuf on port %\"PRIu16\" queue %\"\n+\t\t\t    PRIu16\": %s\\n\", port_id, queue, reason);\n+\t\trte_pktmbuf_free(pkts[i]);\n+\t}\n+\n+\treturn count;\n+}\n+\n int\n start_port(portid_t pid)\n {\n@@ -1641,6 +1700,7 @@ start_port(portid_t pid)\n \tstruct rte_port *port;\n \tstruct ether_addr mac_addr;\n \tenum rte_eth_event_type event_type;\n+\tstruct rte_eth_dev_info dev_info;\n \n \tif (port_id_is_invalid(pid, ENABLED_WARN))\n \t\treturn 0;\n@@ -1671,6 +1731,32 @@ start_port(portid_t pid)\n \t\t\t\t}\n \t\t\t}\n \n+\t\t\t/* Free any remaining rx/tx callbacks before changing\n+\t\t\t * rxq/txq count.\n+\t\t\t */\n+\t\t\trte_eth_dev_info_get(pi, &dev_info);\n+\t\t\tfor (qi = 0; qi < dev_info.nb_tx_queues; qi++) {\n+\t\t\t\tif (!port->tx_checks_cb[qi])\n+\t\t\t\t\tcontinue;\n+\t\t\t\tif (rte_eth_remove_tx_callback(pi, qi,\n+\t\t\t\t\t\tport->tx_checks_cb[qi]) < 0) {\n+\t\t\t\t\t/* try to reconfigure port next time */\n+\t\t\t\t\tport->need_reconfig = 1;\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tport->tx_checks_cb[qi] = NULL;\n+\t\t\t}\n+\t\t\tfor (qi = 0; qi < dev_info.nb_rx_queues; qi++) {\n+\t\t\t\tif (!port->rx_checks_cb[qi])\n+\t\t\t\t\tcontinue;\n+\t\t\t\tif (rte_eth_remove_rx_callback(pi, qi,\n+\t\t\t\t\t\tport->rx_checks_cb[qi]) < 0) {\n+\t\t\t\t\t/* try to reconfigure port next time */\n+\t\t\t\t\tport->need_reconfig = 1;\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tport->rx_checks_cb[qi] = NULL;\n+\t\t\t}\n \t\t\tprintf(\"Configuring Port %d (socket %u)\\n\", pi,\n \t\t\t\t\tport->socket_id);\n \t\t\t/* configure port */\n@@ -1703,6 +1789,24 @@ start_port(portid_t pid)\n \t\t\t\t\t\tport->socket_id,\n \t\t\t\t\t\t&(port->tx_conf[qi]));\n \n+\t\t\t\tif (diag == 0 &&\n+\t\t\t\t    port->tx_checks_cb[qi]) {\n+\t\t\t\t\tif (!rte_eth_remove_tx_callback(pi, qi,\n+\t\t\t\t\t\t\tport->tx_checks_cb[qi]))\n+\t\t\t\t\t\tport->tx_checks_cb[qi] = NULL;\n+\t\t\t\t\telse\n+\t\t\t\t\t\tdiag = -1;\n+\t\t\t\t}\n+\n+\t\t\t\tif (diag == 0 &&\n+\t\t\t\t    port->sanity_checks & SANITY_CHECK_TX) {\n+\t\t\t\t\tport->tx_checks_cb[qi] =\n+\t\t\t\t\t\trte_eth_add_tx_callback(pi, qi,\n+\t\t\t\t\t\t\tmbuf_tx_check, NULL);\n+\t\t\t\t\tif (!port->tx_checks_cb[qi])\n+\t\t\t\t\t\tdiag = -1;\n+\t\t\t\t}\n+\n \t\t\t\tif (diag == 0)\n \t\t\t\t\tcontinue;\n \n@@ -1753,6 +1857,25 @@ start_port(portid_t pid)\n \t\t\t\t\t     &(port->rx_conf[qi]),\n \t\t\t\t\t     mp);\n \t\t\t\t}\n+\n+\t\t\t\tif (diag == 0 &&\n+\t\t\t\t    port->rx_checks_cb[qi]) {\n+\t\t\t\t\tif (!rte_eth_remove_rx_callback(pi, qi,\n+\t\t\t\t\t\t\tport->rx_checks_cb[qi]))\n+\t\t\t\t\t\tport->rx_checks_cb[qi] = NULL;\n+\t\t\t\t\telse\n+\t\t\t\t\t\tdiag = -1;\n+\t\t\t\t}\n+\n+\t\t\t\tif (diag == 0 &&\n+\t\t\t\t    port->sanity_checks & SANITY_CHECK_RX) {\n+\t\t\t\t\tport->rx_checks_cb[qi] =\n+\t\t\t\t\t\trte_eth_add_rx_callback(pi, qi,\n+\t\t\t\t\t\t\tmbuf_rx_check, NULL);\n+\t\t\t\t\tif (!port->rx_checks_cb[qi])\n+\t\t\t\t\t\tdiag = -1;\n+\t\t\t\t}\n+\n \t\t\t\tif (diag == 0)\n \t\t\t\t\tcontinue;\n \ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex a1f661472..bdab372b2 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -180,6 +180,11 @@ struct rte_port {\n \tuint32_t                mc_addr_nb; /**< nb. of addr. in mc_addr_pool */\n \tuint8_t                 slave_flag; /**< bonding slave port */\n \tstruct port_flow        *flow_list; /**< Associated flows. */\n+#define SANITY_CHECK_RX ((uint8_t)1 << 0)\n+#define SANITY_CHECK_TX ((uint8_t)1 << 1)\n+\tuint8_t                 sanity_checks;\n+\tconst struct rte_eth_rxtx_callback *rx_checks_cb[MAX_QUEUE_ID+1];\n+\tconst struct rte_eth_rxtx_callback *tx_checks_cb[MAX_QUEUE_ID+1];\n #ifdef SOFTNIC\n \tstruct softnic_port     softport;  /**< softnic params */\n #endif\n@@ -378,6 +383,8 @@ extern int16_t tx_rs_thresh;\n extern uint8_t dcb_config;\n extern uint8_t dcb_test;\n \n+extern uint8_t sanity_checks;\n+\n extern uint16_t mbuf_data_size; /**< Mbuf data space size. */\n extern uint32_t param_total_num_mbufs;\n \n@@ -730,6 +737,8 @@ int close_file(uint8_t *buf);\n \n void port_queue_region_info_display(portid_t port_id, void *buf);\n \n+int set_sanity_checks(const char *arg);\n+\n enum print_warning {\n \tENABLED_WARN = 0,\n \tDISABLED_WARN\n",
    "prefixes": [
        "3/3"
    ]
}