get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 13754,
    "url": "https://patches.dpdk.org/api/patches/13754/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1465945686-142094-2-git-send-email-zhihong.wang@intel.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": "<1465945686-142094-2-git-send-email-zhihong.wang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1465945686-142094-2-git-send-email-zhihong.wang@intel.com",
    "date": "2016-06-14T23:08:02",
    "name": "[dpdk-dev,v3,1/5] testpmd: add retry option",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "859738811c508a6fea422e4dc2dee5f8a50b1d9a",
    "submitter": {
        "id": 156,
        "url": "https://patches.dpdk.org/api/people/156/?format=api",
        "name": "Zhihong Wang",
        "email": "zhihong.wang@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1465945686-142094-2-git-send-email-zhihong.wang@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/13754/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/13754/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 05F98ADFB;\n\tWed, 15 Jun 2016 08:13:56 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 45A61ADD2\n\tfor <dev@dpdk.org>; Wed, 15 Jun 2016 08:13:51 +0200 (CEST)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga103.fm.intel.com with ESMTP; 14 Jun 2016 23:13:43 -0700",
            "from unknown (HELO dpdk5.sh.intel.com) ([10.239.129.244])\n\tby FMSMGA003.fm.intel.com with ESMTP; 14 Jun 2016 23:13:38 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.26,474,1459839600\"; d=\"scan'208\";a=\"719268284\"",
        "From": "Zhihong Wang <zhihong.wang@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "konstantin.ananyev@intel.com, bruce.richardson@intel.com,\n\tpablo.de.lara.guarch@intel.com, thomas.monjalon@6wind.com,\n\tZhihong Wang <zhihong.wang@intel.com>",
        "Date": "Tue, 14 Jun 2016 19:08:02 -0400",
        "Message-Id": "<1465945686-142094-2-git-send-email-zhihong.wang@intel.com>",
        "X-Mailer": "git-send-email 2.5.0",
        "In-Reply-To": "<1465945686-142094-1-git-send-email-zhihong.wang@intel.com>",
        "References": "<1462488421-118990-1-git-send-email-zhihong.wang@intel.com>\n\t<1465945686-142094-1-git-send-email-zhihong.wang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 1/5] testpmd: add retry option",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch adds retry option in testpmd to prevent most packet losses.\nIt can be enabled by \"set fwd <mode> retry\". All modes except rxonly\nsupport this option.\n\nAdding retry mechanism expands test case coverage to support scenarios\nwhere packet loss affects test results.\n\n\nSigned-off-by: Zhihong Wang <zhihong.wang@intel.com>\nAcked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>\n---\n app/test-pmd/Makefile                       |   1 -\n app/test-pmd/cmdline.c                      |  75 ++++++++++++-\n app/test-pmd/config.c                       |  43 ++++++-\n app/test-pmd/csumonly.c                     |  12 ++\n app/test-pmd/flowgen.c                      |  12 ++\n app/test-pmd/icmpecho.c                     |  15 +++\n app/test-pmd/iofwd.c                        |  22 +++-\n app/test-pmd/macfwd-retry.c                 | 167 ----------------------------\n app/test-pmd/macfwd.c                       |  13 +++\n app/test-pmd/macswap.c                      |  12 ++\n app/test-pmd/testpmd.c                      |   4 +-\n app/test-pmd/testpmd.h                      |  11 +-\n app/test-pmd/txonly.c                       |  12 ++\n doc/guides/testpmd_app_ug/run_app.rst       |   1 -\n doc/guides/testpmd_app_ug/testpmd_funcs.rst |  12 +-\n 15 files changed, 224 insertions(+), 188 deletions(-)\n delete mode 100644 app/test-pmd/macfwd-retry.c",
    "diff": "diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile\nindex 40039a1..2a0b5a5 100644\n--- a/app/test-pmd/Makefile\n+++ b/app/test-pmd/Makefile\n@@ -50,7 +50,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c\n SRCS-y += config.c\n SRCS-y += iofwd.c\n SRCS-y += macfwd.c\n-SRCS-y += macfwd-retry.c\n SRCS-y += macswap.c\n SRCS-y += flowgen.c\n SRCS-y += rxonly.c\ndiff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex fd389ac..e414c0f 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -246,8 +246,8 @@ static void cmd_help_long_parsed(void *parsed_result,\n \t\t\t\"    Set number of packets per burst.\\n\\n\"\n \n \t\t\t\"set burst tx delay (microseconds) retry (num)\\n\"\n-\t\t\t\"    Set the transmit delay time and number of retries\"\n-\t\t\t\" in mac_retry forwarding mode.\\n\\n\"\n+\t\t\t\"    Set the transmit delay time and number of retries,\"\n+\t\t\t\" effective when retry is enabled.\\n\\n\"\n \n \t\t\t\"set txpkts (x[,y]*)\\n\"\n \t\t\t\"    Set the length of each segment of TXONLY\"\n@@ -4557,6 +4557,7 @@ static void cmd_set_fwd_mode_parsed(void *parsed_result,\n {\n \tstruct cmd_set_fwd_mode_result *res = parsed_result;\n \n+\tretry_enabled = 0;\n \tset_pkt_forwarding_mode(res->mode);\n }\n \n@@ -4602,6 +4603,74 @@ static void cmd_set_fwd_mode_init(void)\n \ttoken_struct->string_data.str = token;\n }\n \n+/* *** SET RETRY FORWARDING MODE *** */\n+struct cmd_set_fwd_retry_mode_result {\n+\tcmdline_fixed_string_t set;\n+\tcmdline_fixed_string_t fwd;\n+\tcmdline_fixed_string_t mode;\n+\tcmdline_fixed_string_t retry;\n+};\n+\n+static void cmd_set_fwd_retry_mode_parsed(void *parsed_result,\n+\t\t\t    __attribute__((unused)) struct cmdline *cl,\n+\t\t\t    __attribute__((unused)) void *data)\n+{\n+\tstruct cmd_set_fwd_retry_mode_result *res = parsed_result;\n+\n+\tretry_enabled = 1;\n+\tset_pkt_forwarding_mode(res->mode);\n+}\n+\n+cmdline_parse_token_string_t cmd_setfwd_retry_set =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,\n+\t\t\tset, \"set\");\n+cmdline_parse_token_string_t cmd_setfwd_retry_fwd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,\n+\t\t\tfwd, \"fwd\");\n+cmdline_parse_token_string_t cmd_setfwd_retry_mode =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,\n+\t\t\tmode,\n+\t\t\"\" /* defined at init */);\n+cmdline_parse_token_string_t cmd_setfwd_retry_retry =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,\n+\t\t\tretry, \"retry\");\n+\n+cmdline_parse_inst_t cmd_set_fwd_retry_mode = {\n+\t.f = cmd_set_fwd_retry_mode_parsed,\n+\t.data = NULL,\n+\t.help_str = NULL, /* defined at init */\n+\t.tokens = {\n+\t\t(void *)&cmd_setfwd_retry_set,\n+\t\t(void *)&cmd_setfwd_retry_fwd,\n+\t\t(void *)&cmd_setfwd_retry_mode,\n+\t\t(void *)&cmd_setfwd_retry_retry,\n+\t\tNULL,\n+\t},\n+};\n+\n+static void cmd_set_fwd_retry_mode_init(void)\n+{\n+\tchar *modes, *c;\n+\tstatic char token[128];\n+\tstatic char help[256];\n+\tcmdline_parse_token_string_t *token_struct;\n+\n+\tmodes = list_pkt_forwarding_retry_modes();\n+\tsnprintf(help, sizeof(help), \"set fwd %s retry - \"\n+\t\t\"set packet forwarding mode with retry\", modes);\n+\tcmd_set_fwd_retry_mode.help_str = help;\n+\n+\t/* string token separator is # */\n+\tfor (c = token; *modes != '\\0'; modes++)\n+\t\tif (*modes == '|')\n+\t\t\t*c++ = '#';\n+\t\telse\n+\t\t\t*c++ = *modes;\n+\ttoken_struct = (cmdline_parse_token_string_t *)\n+\t\tcmd_set_fwd_retry_mode.tokens[2];\n+\ttoken_struct->string_data.str = token;\n+}\n+\n /* *** SET BURST TX DELAY TIME RETRY NUMBER *** */\n struct cmd_set_burst_tx_retry_result {\n \tcmdline_fixed_string_t set;\n@@ -10482,6 +10551,7 @@ cmdline_parse_ctx_t main_ctx[] = {\n \t(cmdline_parse_inst_t *)&cmd_set_fwd_list,\n \t(cmdline_parse_inst_t *)&cmd_set_fwd_mask,\n \t(cmdline_parse_inst_t *)&cmd_set_fwd_mode,\n+\t(cmdline_parse_inst_t *)&cmd_set_fwd_retry_mode,\n \t(cmdline_parse_inst_t *)&cmd_set_burst_tx_retry,\n \t(cmdline_parse_inst_t *)&cmd_set_promisc_mode_one,\n \t(cmdline_parse_inst_t *)&cmd_set_promisc_mode_all,\n@@ -10621,6 +10691,7 @@ prompt(void)\n {\n \t/* initialize non-constant commands */\n \tcmd_set_fwd_mode_init();\n+\tcmd_set_fwd_retry_mode_init();\n \n \ttestpmd_cl = cmdline_stdin_new(main_ctx, \"testpmd> \");\n \tif (testpmd_cl == NULL)\ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex 1c552e4..a85bb5f 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -893,8 +893,9 @@ fwd_lcores_config_display(void)\n void\n rxtx_config_display(void)\n {\n-\tprintf(\"  %s packet forwarding - CRC stripping %s - \"\n+\tprintf(\"  %s packet forwarding%s - CRC stripping %s - \"\n \t       \"packets/burst=%d\\n\", cur_fwd_eng->fwd_mode_name,\n+\t       retry_enabled == 0 ? \"\" : \" with retry\",\n \t       rx_mode.hw_strip_crc ? \"enabled\" : \"disabled\",\n \t       nb_pkt_per_burst);\n \n@@ -1131,6 +1132,7 @@ simple_fwd_config_setup(void)\n \t\tfwd_streams[i]->tx_port   = fwd_ports_ids[j];\n \t\tfwd_streams[i]->tx_queue  = 0;\n \t\tfwd_streams[i]->peer_addr = j;\n+\t\tfwd_streams[i]->retry_enabled = retry_enabled;\n \n \t\tif (port_topology == PORT_TOPOLOGY_PAIRED) {\n \t\t\tfwd_streams[j]->rx_port   = fwd_ports_ids[j];\n@@ -1138,6 +1140,7 @@ simple_fwd_config_setup(void)\n \t\t\tfwd_streams[j]->tx_port   = fwd_ports_ids[i];\n \t\t\tfwd_streams[j]->tx_queue  = 0;\n \t\t\tfwd_streams[j]->peer_addr = i;\n+\t\t\tfwd_streams[j]->retry_enabled = retry_enabled;\n \t\t}\n \t}\n }\n@@ -1206,6 +1209,7 @@ rss_fwd_config_setup(void)\n \t\tfs->tx_port = fwd_ports_ids[txp];\n \t\tfs->tx_queue = rxq;\n \t\tfs->peer_addr = fs->tx_port;\n+\t\tfs->retry_enabled = retry_enabled;\n \t\trxq = (queueid_t) (rxq + 1);\n \t\tif (rxq < nb_q)\n \t\t\tcontinue;\n@@ -1280,6 +1284,7 @@ dcb_fwd_config_setup(void)\n \t\t\t\tfs->tx_port = fwd_ports_ids[txp];\n \t\t\t\tfs->tx_queue = txq + j % nb_tx_queue;\n \t\t\t\tfs->peer_addr = fs->tx_port;\n+\t\t\t\tfs->retry_enabled = retry_enabled;\n \t\t\t}\n \t\t\tfwd_lcores[lc_id]->stream_nb +=\n \t\t\t\trxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;\n@@ -1350,6 +1355,7 @@ icmp_echo_config_setup(void)\n \t\t\tfs->tx_port = fs->rx_port;\n \t\t\tfs->tx_queue = rxq;\n \t\t\tfs->peer_addr = fs->tx_port;\n+\t\t\tfs->retry_enabled = retry_enabled;\n \t\t\tif (verbose_level > 0)\n \t\t\t\tprintf(\"  stream=%d port=%d rxq=%d txq=%d\\n\",\n \t\t\t\t       sm_id, fs->rx_port, fs->rx_queue,\n@@ -1388,14 +1394,15 @@ pkt_fwd_config_display(struct fwd_config *cfg)\n \tlcoreid_t  lc_id;\n \tstreamid_t sm_id;\n \n-\tprintf(\"%s packet forwarding - ports=%d - cores=%d - streams=%d - \"\n+\tprintf(\"%s packet forwarding%s - ports=%d - cores=%d - streams=%d - \"\n \t\t\"NUMA support %s, MP over anonymous pages %s\\n\",\n \t\tcfg->fwd_eng->fwd_mode_name,\n+\t\tretry_enabled == 0 ? \"\" : \" with retry\",\n \t\tcfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,\n \t\tnuma_support == 1 ? \"enabled\" : \"disabled\",\n \t\tmp_anon != 0 ? \"enabled\" : \"disabled\");\n \n-\tif (strcmp(cfg->fwd_eng->fwd_mode_name, \"mac_retry\") == 0)\n+\tif (retry_enabled)\n \t\tprintf(\"TX retry num: %u, delay between TX retries: %uus\\n\",\n \t\t\tburst_tx_retry_num, burst_tx_delay_time);\n \tfor (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) {\n@@ -1684,6 +1691,31 @@ list_pkt_forwarding_modes(void)\n \treturn fwd_modes;\n }\n \n+char*\n+list_pkt_forwarding_retry_modes(void)\n+{\n+\tstatic char fwd_modes[128] = \"\";\n+\tconst char *separator = \"|\";\n+\tstruct fwd_engine *fwd_eng;\n+\tunsigned i = 0;\n+\n+\tif (strlen(fwd_modes) == 0) {\n+\t\twhile ((fwd_eng = fwd_engines[i++]) != NULL) {\n+\t\t\tif (fwd_eng == &rx_only_engine)\n+\t\t\t\tcontinue;\n+\t\t\tstrncat(fwd_modes, fwd_eng->fwd_mode_name,\n+\t\t\t\t\tsizeof(fwd_modes) -\n+\t\t\t\t\tstrlen(fwd_modes) - 1);\n+\t\t\tstrncat(fwd_modes, separator,\n+\t\t\t\t\tsizeof(fwd_modes) -\n+\t\t\t\t\tstrlen(fwd_modes) - 1);\n+\t\t}\n+\t\tfwd_modes[strlen(fwd_modes) - strlen(separator)] = '\\0';\n+\t}\n+\n+\treturn fwd_modes;\n+}\n+\n void\n set_pkt_forwarding_mode(const char *fwd_mode_name)\n {\n@@ -1693,8 +1725,9 @@ set_pkt_forwarding_mode(const char *fwd_mode_name)\n \ti = 0;\n \twhile ((fwd_eng = fwd_engines[i]) != NULL) {\n \t\tif (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) {\n-\t\t\tprintf(\"Set %s packet forwarding mode\\n\",\n-\t\t\t       fwd_mode_name);\n+\t\t\tprintf(\"Set %s packet forwarding mode%s\\n\",\n+\t\t\t       fwd_mode_name,\n+\t\t\t       retry_enabled == 0 ? \"\" : \" with retry\");\n \t\t\tcur_fwd_eng = fwd_eng;\n \t\t\treturn;\n \t\t}\ndiff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c\nindex 1d6cda1..ac4bd8f 100644\n--- a/app/test-pmd/csumonly.c\n+++ b/app/test-pmd/csumonly.c\n@@ -643,6 +643,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)\n \tuint16_t i;\n \tuint64_t ol_flags;\n \tuint16_t testpmd_ol_flags;\n+\tuint32_t retry;\n \tuint32_t rx_bad_ip_csum;\n \tuint32_t rx_bad_l4_csum;\n \tstruct testpmd_offload_info info;\n@@ -848,6 +849,17 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)\n \t\t}\n \t}\n \tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);\n+\t/*\n+\t * Retry if necessary\n+\t */\n+\tif (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t}\n+\t}\n \tfs->tx_packets += nb_tx;\n \tfs->rx_bad_ip_csum += rx_bad_ip_csum;\n \tfs->rx_bad_l4_csum += rx_bad_l4_csum;\ndiff --git a/app/test-pmd/flowgen.c b/app/test-pmd/flowgen.c\nindex 18b754b..a6abe91 100644\n--- a/app/test-pmd/flowgen.c\n+++ b/app/test-pmd/flowgen.c\n@@ -131,6 +131,7 @@ pkt_burst_flow_gen(struct fwd_stream *fs)\n \tuint16_t nb_tx;\n \tuint16_t nb_pkt;\n \tuint16_t i;\n+\tuint32_t retry;\n #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n \tuint64_t start_tsc;\n \tuint64_t end_tsc;\n@@ -207,6 +208,17 @@ pkt_burst_flow_gen(struct fwd_stream *fs)\n \t}\n \n \tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt);\n+\t/*\n+\t * Retry if necessary\n+\t */\n+\tif (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t}\n+\t}\n \tfs->tx_packets += nb_tx;\n \n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\ndiff --git a/app/test-pmd/icmpecho.c b/app/test-pmd/icmpecho.c\nindex ed6e924..be308c9 100644\n--- a/app/test-pmd/icmpecho.c\n+++ b/app/test-pmd/icmpecho.c\n@@ -311,6 +311,7 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)\n \tstruct ipv4_hdr *ip_h;\n \tstruct icmp_hdr *icmp_h;\n \tstruct ether_addr eth_addr;\n+\tuint32_t retry;\n \tuint32_t ip_addr;\n \tuint16_t nb_rx;\n \tuint16_t nb_tx;\n@@ -518,6 +519,20 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)\n \tif (nb_replies > 0) {\n \t\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst,\n \t\t\t\t\t nb_replies);\n+\t\t/*\n+\t\t * Retry if necessary\n+\t\t */\n+\t\tif (unlikely(nb_tx < nb_replies) && fs->retry_enabled) {\n+\t\t\tretry = 0;\n+\t\t\twhile (nb_tx < nb_replies &&\n+\t\t\t\t\tretry++ < burst_tx_retry_num) {\n+\t\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port,\n+\t\t\t\t\t\tfs->tx_queue,\n+\t\t\t\t\t\t&pkts_burst[nb_tx],\n+\t\t\t\t\t\tnb_replies - nb_tx);\n+\t\t\t}\n+\t\t}\n \t\tfs->tx_packets += nb_tx;\n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n \t\tfs->tx_burst_stats.pkt_burst_spread[nb_tx]++;\ndiff --git a/app/test-pmd/iofwd.c b/app/test-pmd/iofwd.c\nindex 8840d86..7b6033a 100644\n--- a/app/test-pmd/iofwd.c\n+++ b/app/test-pmd/iofwd.c\n@@ -80,6 +80,8 @@ pkt_burst_io_forward(struct fwd_stream *fs)\n \tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n \tuint16_t nb_rx;\n \tuint16_t nb_tx;\n+\tuint32_t retry;\n+\n #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n \tuint64_t start_tsc;\n \tuint64_t end_tsc;\n@@ -93,16 +95,28 @@ pkt_burst_io_forward(struct fwd_stream *fs)\n \t/*\n \t * Receive a burst of packets and forward them.\n \t */\n-\tnb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,\n-\t\t\t\t nb_pkt_per_burst);\n+\tnb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,\n+\t\t\tpkts_burst, nb_pkt_per_burst);\n \tif (unlikely(nb_rx == 0))\n \t\treturn;\n+\tfs->rx_packets += nb_rx;\n \n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n \tfs->rx_burst_stats.pkt_burst_spread[nb_rx]++;\n #endif\n-\tfs->rx_packets += nb_rx;\n-\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);\n+\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\tpkts_burst, nb_rx);\n+\t/*\n+\t * Retry if necessary\n+\t */\n+\tif (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t}\n+\t}\n \tfs->tx_packets += nb_tx;\n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n \tfs->tx_burst_stats.pkt_burst_spread[nb_tx]++;\ndiff --git a/app/test-pmd/macfwd-retry.c b/app/test-pmd/macfwd-retry.c\ndeleted file mode 100644\nindex d8cd069..0000000\n--- a/app/test-pmd/macfwd-retry.c\n+++ /dev/null\n@@ -1,167 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 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-\n-#include <stdarg.h>\n-#include <string.h>\n-#include <stdio.h>\n-#include <errno.h>\n-#include <stdint.h>\n-#include <unistd.h>\n-#include <inttypes.h>\n-\n-#include <sys/queue.h>\n-#include <sys/stat.h>\n-\n-#include <rte_common.h>\n-#include <rte_byteorder.h>\n-#include <rte_log.h>\n-#include <rte_debug.h>\n-#include <rte_cycles.h>\n-#include <rte_memory.h>\n-#include <rte_memcpy.h>\n-#include <rte_memzone.h>\n-#include <rte_launch.h>\n-#include <rte_eal.h>\n-#include <rte_per_lcore.h>\n-#include <rte_lcore.h>\n-#include <rte_atomic.h>\n-#include <rte_branch_prediction.h>\n-#include <rte_ring.h>\n-#include <rte_memory.h>\n-#include <rte_mempool.h>\n-#include <rte_mbuf.h>\n-#include <rte_interrupts.h>\n-#include <rte_pci.h>\n-#include <rte_ether.h>\n-#include <rte_ethdev.h>\n-#include <rte_ip.h>\n-#include <rte_string_fns.h>\n-\n-#include \"testpmd.h\"\n-\n-#define BURST_TX_WAIT_US 10\n-#define BURST_TX_RETRIES 5\n-\n-/*\n- * Global variables that control number of retires and\n- * timeout (in us) between retires.\n- */\n-uint32_t burst_tx_delay_time = BURST_TX_WAIT_US;\n-uint32_t burst_tx_retry_num = BURST_TX_RETRIES;\n-\n-/*\n- * Forwarding of packets in MAC mode with a wait and retry on TX to reduce packet loss.\n- * Change the source and the destination Ethernet addressed of packets\n- * before forwarding them.\n- */\n-static void\n-pkt_burst_mac_retry_forward(struct fwd_stream *fs)\n-{\n-\tstruct rte_mbuf  *pkts_burst[MAX_PKT_BURST];\n-\tstruct rte_mbuf  *mb;\n-\tstruct ether_hdr *eth_hdr;\n-\tuint32_t retry;\n-\tuint16_t nb_rx;\n-\tuint16_t nb_tx;\n-\tuint16_t i;\n-#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n-\tuint64_t start_tsc;\n-\tuint64_t end_tsc;\n-\tuint64_t core_cycles;\n-#endif\n-\n-#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n-\tstart_tsc = rte_rdtsc();\n-#endif\n-\n-\t/*\n-\t * Receive a burst of packets and forward them.\n-\t */\n-\tnb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,\n-\t\t\t\t nb_pkt_per_burst);\n-\tif (unlikely(nb_rx == 0))\n-\t\treturn;\n-\n-#ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n-\tfs->rx_burst_stats.pkt_burst_spread[nb_rx]++;\n-#endif\n-\tfs->rx_packets += nb_rx;\n-\tfor (i = 0; i < nb_rx; i++) {\n-\t\tif (likely(i < nb_rx - 1))\n-\t\t\trte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],\n-\t\t\t\t\t\t       void *));\n-\t\tmb = pkts_burst[i];\n-\t\teth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);\n-\t\tether_addr_copy(&peer_eth_addrs[fs->peer_addr],\n-\t\t\t\t&eth_hdr->d_addr);\n-\t\tether_addr_copy(&ports[fs->tx_port].eth_addr,\n-\t\t\t\t&eth_hdr->s_addr);\n-\t}\n-\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);\n-\n-\t/*\n-\t * If not all packets have been TX'd then wait and retry.\n-\t */\n-\tif (unlikely(nb_tx < nb_rx)) {\n-\t\tfor (retry = 0; retry < burst_tx_retry_num; retry++) {\n-\t\t\trte_delay_us(burst_tx_delay_time);\n-\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n-\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n-\t\t\tif (nb_tx == nb_rx)\n-\t\t\t\tbreak;\n-\t\t}\n-\t}\n-\n-\tfs->tx_packets += nb_tx;\n-#ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n-\tfs->tx_burst_stats.pkt_burst_spread[nb_tx]++;\n-#endif\n-\tif (unlikely(nb_tx < nb_rx)) {\n-\t\tfs->fwd_dropped += (nb_rx - nb_tx);\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(pkts_burst[nb_tx]);\n-\t\t} while (++nb_tx < nb_rx);\n-\t}\n-#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n-\tend_tsc = rte_rdtsc();\n-\tcore_cycles = (end_tsc - start_tsc);\n-\tfs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);\n-#endif\n-}\n-\n-struct fwd_engine mac_retry_fwd_engine = {\n-\t.fwd_mode_name  = \"mac_retry\",\n-\t.port_fwd_begin = NULL,\n-\t.port_fwd_end   = NULL,\n-\t.packet_fwd     = pkt_burst_mac_retry_forward,\n-};\ndiff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c\nindex 07a399a..5d1c161 100644\n--- a/app/test-pmd/macfwd.c\n+++ b/app/test-pmd/macfwd.c\n@@ -81,6 +81,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)\n \tstruct rte_port  *txp;\n \tstruct rte_mbuf  *mb;\n \tstruct ether_hdr *eth_hdr;\n+\tuint32_t retry;\n \tuint16_t nb_rx;\n \tuint16_t nb_tx;\n \tuint16_t i;\n@@ -129,6 +130,18 @@ pkt_burst_mac_forward(struct fwd_stream *fs)\n \t\tmb->vlan_tci_outer = txp->tx_vlan_id_outer;\n \t}\n \tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);\n+\t/*\n+\t * Retry if necessary\n+\t */\n+\tif (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t}\n+\t}\n+\n \tfs->tx_packets += nb_tx;\n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n \tfs->tx_burst_stats.pkt_burst_spread[nb_tx]++;\ndiff --git a/app/test-pmd/macswap.c b/app/test-pmd/macswap.c\nindex c10f4b5..4b0dbeb 100644\n--- a/app/test-pmd/macswap.c\n+++ b/app/test-pmd/macswap.c\n@@ -84,6 +84,7 @@ pkt_burst_mac_swap(struct fwd_stream *fs)\n \tuint16_t nb_rx;\n \tuint16_t nb_tx;\n \tuint16_t i;\n+\tuint32_t retry;\n \tuint64_t ol_flags = 0;\n #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n \tuint64_t start_tsc;\n@@ -131,6 +132,17 @@ pkt_burst_mac_swap(struct fwd_stream *fs)\n \t\tmb->vlan_tci_outer = txp->tx_vlan_id_outer;\n \t}\n \tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);\n+\t/*\n+\t * Retry if necessary\n+\t */\n+\tif (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t}\n+\t}\n \tfs->tx_packets += nb_tx;\n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n \tfs->tx_burst_stats.pkt_burst_spread[nb_tx]++;\ndiff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c\nindex dd6b046..dfd27d5 100644\n--- a/app/test-pmd/testpmd.c\n+++ b/app/test-pmd/testpmd.c\n@@ -144,7 +144,6 @@ streamid_t nb_fwd_streams;       /**< Is equal to (nb_ports * nb_rxq). */\n struct fwd_engine * fwd_engines[] = {\n \t&io_fwd_engine,\n \t&mac_fwd_engine,\n-\t&mac_retry_fwd_engine,\n \t&mac_swap_engine,\n \t&flow_gen_engine,\n \t&rx_only_engine,\n@@ -159,6 +158,9 @@ struct fwd_engine * fwd_engines[] = {\n \n struct fwd_config cur_fwd_config;\n struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */\n+uint32_t retry_enabled;\n+uint32_t burst_tx_delay_time = BURST_TX_WAIT_US;\n+uint32_t burst_tx_retry_num = BURST_TX_RETRIES;\n \n uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */\n uint32_t param_total_num_mbufs = 0;  /**< number of mbufs in all pools - if\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex 0f72ca1..62ec055 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -103,6 +103,8 @@ struct fwd_stream {\n \tqueueid_t  tx_queue;  /**< TX queue to send forwarded packets */\n \tstreamid_t peer_addr; /**< index of peer ethernet address of packets */\n \n+\tunsigned int retry_enabled;\n+\n \t/* \"read-write\" results */\n \tunsigned int rx_packets;  /**< received packets */\n \tunsigned int tx_packets;  /**< received packets transmitted */\n@@ -220,9 +222,14 @@ struct fwd_engine {\n \tpacket_fwd_t     packet_fwd;     /**< Mandatory. */\n };\n \n+#define BURST_TX_WAIT_US 1\n+#define BURST_TX_RETRIES 64\n+\n+extern uint32_t burst_tx_delay_time;\n+extern uint32_t burst_tx_retry_num;\n+\n extern struct fwd_engine io_fwd_engine;\n extern struct fwd_engine mac_fwd_engine;\n-extern struct fwd_engine mac_retry_fwd_engine;\n extern struct fwd_engine mac_swap_engine;\n extern struct fwd_engine flow_gen_engine;\n extern struct fwd_engine rx_only_engine;\n@@ -380,6 +387,7 @@ extern int8_t tx_wthresh;\n \n extern struct fwd_config cur_fwd_config;\n extern struct fwd_engine *cur_fwd_eng;\n+extern uint32_t retry_enabled;\n extern struct fwd_lcore  **fwd_lcores;\n extern struct fwd_stream **fwd_streams;\n \n@@ -523,6 +531,7 @@ void show_tx_pkt_segments(void);\n void set_tx_pkt_split(const char *name);\n void set_nb_pkt_per_burst(uint16_t pkt_burst);\n char *list_pkt_forwarding_modes(void);\n+char *list_pkt_forwarding_retry_modes(void);\n void set_pkt_forwarding_mode(const char *fwd_mode);\n void start_packet_forwarding(int with_tx_first);\n void stop_packet_forwarding(void);\ndiff --git a/app/test-pmd/txonly.c b/app/test-pmd/txonly.c\nindex 0ac2a08..11fd681 100644\n--- a/app/test-pmd/txonly.c\n+++ b/app/test-pmd/txonly.c\n@@ -193,6 +193,7 @@ pkt_burst_transmit(struct fwd_stream *fs)\n \tuint16_t nb_tx;\n \tuint16_t nb_pkt;\n \tuint16_t vlan_tci, vlan_tci_outer;\n+\tuint32_t retry;\n \tuint64_t ol_flags = 0;\n \tuint8_t  i;\n #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n@@ -273,6 +274,17 @@ pkt_burst_transmit(struct fwd_stream *fs)\n \t\tpkts_burst[nb_pkt] = pkt;\n \t}\n \tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt);\n+\t/*\n+\t * Retry if necessary\n+\t */\n+\tif (unlikely(nb_tx < nb_pkt) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_pkt && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_pkt - nb_tx);\n+\t\t}\n+\t}\n \tfs->tx_packets += nb_tx;\n \n #ifdef RTE_TEST_PMD_RECORD_BURST_STATS\ndiff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst\nindex 8fb0651..7712bd2 100644\n--- a/doc/guides/testpmd_app_ug/run_app.rst\n+++ b/doc/guides/testpmd_app_ug/run_app.rst\n@@ -333,7 +333,6 @@ The commandline options are:\n \n        io (the default)\n        mac\n-       mac_retry\n        mac_swap\n        flowgen\n        rxonly\ndiff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\nindex 22bb108..d812989 100644\n--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n@@ -249,8 +249,10 @@ set fwd\n \n Set the packet forwarding mode::\n \n-   testpmd> set fwd (io|mac|mac_retry|macswap|flowgen| \\\n-                     rxonly|txonly|csum|icmpecho)\n+   testpmd> set fwd (io|mac|macswap|flowgen| \\\n+                     rxonly|txonly|csum|icmpecho) (\"\"|retry)\n+\n+``retry`` can be specified for forwarding engines except ``rx_only``.\n \n The available information categories are:\n \n@@ -260,8 +262,6 @@ The available information categories are:\n \n * ``mac``: Changes the source and the destination Ethernet addresses of packets before forwarding them.\n \n-* ``mac_retry``: Same as \"mac\" forwarding mode, but includes retries if the destination queue is full.\n-\n * ``macswap``: MAC swap forwarding mode.\n   Swaps the source and the destination Ethernet addresses of packets before forwarding them.\n \n@@ -392,9 +392,9 @@ Set number of packets per burst::\n \n This is equivalent to the ``--burst command-line`` option.\n \n-In ``mac_retry`` forwarding mode, the transmit delay time and number of retries can also be set::\n+When retry is enabled, the transmit delay time and number of retries can also be set::\n \n-   testpmd> set burst tx delay (micrseconds) retry (num)\n+   testpmd> set burst tx delay (microseconds) retry (num)\n \n set txpkts\n ~~~~~~~~~~\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "1/5"
    ]
}