get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 466,
    "url": "http://patches.dpdk.org/api/patches/466/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1411478290-28807-2-git-send-email-declan.doherty@intel.com/",
    "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": "<1411478290-28807-2-git-send-email-declan.doherty@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1411478290-28807-2-git-send-email-declan.doherty@intel.com",
    "date": "2014-09-23T13:18:06",
    "name": "[dpdk-dev,v3,1/5] bond: free mbufs if transmission fails in bonding tx_burst functions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "8198ef8ac90b2e127a9b0b0a726fd8b7ceefc793",
    "submitter": {
        "id": 11,
        "url": "http://patches.dpdk.org/api/people/11/?format=api",
        "name": "Doherty, Declan",
        "email": "declan.doherty@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1411478290-28807-2-git-send-email-declan.doherty@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/466/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/466/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 36259B349;\n\tTue, 23 Sep 2014 15:13:03 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 11977333\n\tfor <dev@dpdk.org>; Tue, 23 Sep 2014 15:12:54 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP; 23 Sep 2014 06:12:42 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby orsmga002.jf.intel.com with ESMTP; 23 Sep 2014 06:18:19 -0700",
            "from sivswdev02.ir.intel.com (sivswdev02.ir.intel.com\n\t[10.237.217.46])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\ts8NDIIAc001209; Tue, 23 Sep 2014 14:18:18 +0100",
            "from sivswdev02.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev02.ir.intel.com with ESMTP id s8NDIIIG031250;\n\tTue, 23 Sep 2014 14:18:18 +0100",
            "(from dwdohert@localhost)\n\tby sivswdev02.ir.intel.com with  id s8NDII5j031246;\n\tTue, 23 Sep 2014 14:18:18 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.04,580,1406617200\"; d=\"scan'208\";a=\"607159613\"",
        "From": "Declan Doherty <declan.doherty@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 23 Sep 2014 14:18:06 +0100",
        "Message-Id": "<1411478290-28807-2-git-send-email-declan.doherty@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1411478290-28807-1-git-send-email-declan.doherty@intel.com>",
        "References": "<1409560289-29558-5-git-send-email-declan.doherty@intel.com>\n\t<1411478290-28807-1-git-send-email-declan.doherty@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 1/5] bond: free mbufs if transmission fails in\n\tbonding tx_burst functions",
        "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": "Fixing a number of corner cases that if transmission failed on slave devices then this\ncould lead to leaked mbufs \n\nSigned-off-by: Declan Doherty <declan.doherty@intel.com>\n---\n app/test/test_link_bonding.c           |  393 +++++++++++++++++++++++++++++++-\n app/test/virtual_pmd.c                 |   80 +++++--\n app/test/virtual_pmd.h                 |    7 +\n lib/librte_pmd_bond/rte_eth_bond_pmd.c |   83 ++++++--\n 4 files changed, 525 insertions(+), 38 deletions(-)",
    "diff": "diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c\nindex cce32ed..1a847eb 100644\n--- a/app/test/test_link_bonding.c\n+++ b/app/test/test_link_bonding.c\n@@ -663,6 +663,9 @@ enable_bonded_slaves(void)\n \tint i;\n \n \tfor (i = 0; i < test_params->bonded_slave_count; i++) {\n+\t\tvirtual_ethdev_tx_burst_fn_set_success(test_params->slave_port_ids[i],\n+\t\t\t\t1);\n+\n \t\tvirtual_ethdev_simulate_link_status_interrupt(\n \t\t\t\ttest_params->slave_port_ids[i], 1);\n \t}\n@@ -1413,6 +1416,135 @@ test_roundrobin_tx_burst(void)\n }\n \n static int\n+verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)\n+{\n+\tint i, refcnt;\n+\n+\tfor (i = 0; i < nb_mbufs; i++) {\n+\t\trefcnt = rte_mbuf_refcnt_read(mbufs[i]);\n+\t\tTEST_ASSERT_EQUAL(refcnt, val,\n+\t\t\t\"mbuf ref count (%d)is not the expected value (%d)\",\n+\t\t\trefcnt, val);\n+\t}\n+\treturn 0;\n+}\n+\n+\n+static void\n+free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < nb_mbufs; i++)\n+\t\trte_pktmbuf_free(mbufs[i]);\n+}\n+\n+#define TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT\t\t(2)\n+#define TEST_RR_SLAVE_TX_FAIL_BURST_SIZE\t\t(64)\n+#define TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT\t\t(22)\n+#define TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX\t(1)\n+\n+static int\n+test_roundrobin_tx_burst_slave_tx_fail(void)\n+{\n+\tstruct rte_mbuf *pkt_burst[MAX_PKT_BURST];\n+\tstruct rte_mbuf *expected_tx_fail_pkts[MAX_PKT_BURST];\n+\n+\tstruct rte_eth_stats port_stats;\n+\n+\tint i, first_fail_idx, tx_count;\n+\n+\tTEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(\n+\t\t\tBONDING_MODE_ROUND_ROBIN, 0,\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT, 1),\n+\t\t\t\"Failed to intialise bonded device\");\n+\n+\t/* Generate test bursts of packets to transmit */\n+\tTEST_ASSERT_EQUAL(generate_test_burst(pkt_burst,\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_BURST_SIZE, 0, 1, 0, 0, 0),\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_BURST_SIZE,\n+\t\t\t\"Failed to generate test packet burst\");\n+\n+\t/* Copy references to packets which we expect not to be transmitted */\n+\tfirst_fail_idx = (TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\t(TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT *\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)) +\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX;\n+\n+\tfor (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {\n+\t\texpected_tx_fail_pkts[i] = pkt_burst[first_fail_idx +\n+\t\t\t\t(i * TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)];\n+\t}\n+\n+\t/* Set virtual slave to only fail transmission of\n+\t * TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT packets in burst */\n+\tvirtual_ethdev_tx_burst_fn_set_success(\n+\t\t\ttest_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],\n+\t\t\t0);\n+\n+\tvirtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(\n+\t\t\ttest_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\ttx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_BURST_SIZE);\n+\n+\tTEST_ASSERT_EQUAL(tx_count, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,\n+\t\t\t\"Transmitted (%d) an unexpected (%d) number of packets\", tx_count,\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\t/* Verify that failed packet are expected failed packets */\n+\tfor (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {\n+\t\tTEST_ASSERT_EQUAL(expected_tx_fail_pkts[i], pkt_burst[i + tx_count],\n+\t\t\t\t\"expected mbuf (%d) pointer %p not expected pointer %p\",\n+\t\t\t\ti, expected_tx_fail_pkts[i], pkt_burst[i + tx_count]);\n+\t}\n+\n+\t/* Verify bonded port tx stats */\n+\trte_eth_stats_get(test_params->bonded_port_id, &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t(uint64_t)TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,\n+\t\t\t\"Bonded Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\ttest_params->bonded_port_id, (unsigned int)port_stats.opackets,\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\t/* Verify slave ports tx stats */\n+\tfor (i = 0; i < test_params->bonded_slave_count; i++) {\n+\t\tint slave_expected_tx_count;\n+\n+\t\trte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);\n+\n+\t\tslave_expected_tx_count = TEST_RR_SLAVE_TX_FAIL_BURST_SIZE /\n+\t\t\t\ttest_params->bonded_slave_count;\n+\n+\t\tif (i == TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX)\n+\t\t\tslave_expected_tx_count = slave_expected_tx_count -\n+\t\t\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT;\n+\n+\t\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t\t(uint64_t)slave_expected_tx_count,\n+\t\t\t\t\"Slave Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\t\ttest_params->slave_port_ids[i],\n+\t\t\t\t(unsigned int)port_stats.opackets, slave_expected_tx_count);\n+\t}\n+\n+\t/* Verify that all mbufs have a ref value of zero */\n+\tTEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkt_burst[tx_count],\n+\t\t\tTEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, 1),\n+\t\t\t\"mbufs refcnts not as expected\");\n+\n+\tfree_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\t/* Clean up and remove slaves from bonded device */\n+\treturn remove_slaves_and_stop_bonded_device();\n+}\n+\n+static int\n test_roundrobin_rx_burst_on_single_slave(void)\n {\n \tstruct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };\n@@ -2900,6 +3032,141 @@ test_balance_l34_tx_burst_ipv6_toggle_udp_port(void)\n \treturn balance_l34_tx_burst(0, 0, 0, 0, 1);\n }\n \n+#define TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT\t\t\t(2)\n+#define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1\t\t\t(40)\n+#define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2\t\t\t(20)\n+#define TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT\t\t(25)\n+#define TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX\t(0)\n+\n+static int\n+test_balance_tx_burst_slave_tx_fail(void)\n+{\n+\tstruct rte_mbuf *pkts_burst_1[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1];\n+\tstruct rte_mbuf *pkts_burst_2[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2];\n+\n+\tstruct rte_mbuf *expected_fail_pkts[TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT];\n+\n+\tstruct rte_eth_stats port_stats;\n+\n+\tint i, first_tx_fail_idx, tx_count_1, tx_count_2;\n+\n+\tTEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(\n+\t\t\tBONDING_MODE_BALANCE, 0,\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT, 1),\n+\t\t\t\"Failed to intialise bonded device\");\n+\n+\tTEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(\n+\t\t\ttest_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),\n+\t\t\t\"Failed to set balance xmit policy.\");\n+\n+\n+\t/* Generate test bursts for transmission */\n+\tTEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_1,\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1, 0, 0, 0, 0, 0),\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1,\n+\t\t\t\"Failed to generate test packet burst 1\");\n+\n+\tfirst_tx_fail_idx = TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT;\n+\n+\t/* copy mbuf referneces for expected transmission failures */\n+\tfor (i = 0; i < TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {\n+\t\texpected_fail_pkts[i] = pkts_burst_1[i + first_tx_fail_idx];\n+\t}\n+\n+\tTEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2,\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, 0, 0, 1, 0, 0),\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,\n+\t\t\t\"Failed to generate test packet burst 2\");\n+\n+\n+\t/* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail\n+\t * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */\n+\tvirtual_ethdev_tx_burst_fn_set_success(\n+\t\t\ttest_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],\n+\t\t\t0);\n+\n+\tvirtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(\n+\t\t\ttest_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\n+\t/* Transmit burst 1 */\n+\ttx_count_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1);\n+\n+\tTEST_ASSERT_EQUAL(tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,\n+\t\t\t\"Transmitted (%d) packets, expected to transmit (%d) packets\",\n+\t\t\ttx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\t/* Verify that failed packet are expected failed packets */\n+\tfor (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {\n+\t\tTEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst_1[i + tx_count_1],\n+\t\t\t\t\"expected mbuf (%d) pointer %p not expected pointer %p\",\n+\t\t\t\ti, expected_fail_pkts[i], pkts_burst_1[i + tx_count_1]);\n+\t}\n+\n+\t/* Transmit burst 2 */\n+\ttx_count_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);\n+\n+\tTEST_ASSERT_EQUAL(tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,\n+\t\t\t\"Transmitted (%d) packets, expected to transmit (%d) packets\",\n+\t\t\ttx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);\n+\n+\n+\t/* Verify bonded port tx stats */\n+\trte_eth_stats_get(test_params->bonded_port_id, &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t(uint64_t)((TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2),\n+\t\t\t\"Bonded Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\ttest_params->bonded_port_id, (unsigned int)port_stats.opackets,\n+\t\t\t(TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);\n+\n+\t/* Verify slave ports tx stats */\n+\n+\trte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)\n+\t\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,\n+\t\t\t\t\"Slave Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\t\ttest_params->slave_port_ids[0],\n+\t\t\t\t(unsigned int)port_stats.opackets,\n+\t\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -\n+\t\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\n+\n+\n+\trte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t\t(uint64_t)TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,\n+\t\t\t\t\"Slave Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\t\ttest_params->slave_port_ids[1],\n+\t\t\t\t(unsigned int)port_stats.opackets,\n+\t\t\t\tTEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);\n+\n+\t/* Verify that all mbufs have a ref value of zero */\n+\tTEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst_1[tx_count_1],\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, 1),\n+\t\t\t\"mbufs refcnts not as expected\");\n+\n+\tfree_mbufs(&pkts_burst_1[tx_count_1],\n+\t\t\tTEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);\n+\n+\t/* Clean up and remove slaves from bonded device */\n+\treturn remove_slaves_and_stop_bonded_device();\n+}\n+\n #define TEST_BALANCE_RX_BURST_SLAVE_COUNT (3)\n \n static int\n@@ -3412,7 +3679,7 @@ test_broadcast_tx_burst(void)\n \t/* Send burst on bonded port */\n \tnb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,\n \t\t\tburst_size);\n-\tif (nb_tx != burst_size * test_params->bonded_slave_count) {\n+\tif (nb_tx != burst_size) {\n \t\tprintf(\"Bonded Port (%d) rx burst failed, packets transmitted value (%u) not as expected (%d)\\n\",\n \t\t\t\ttest_params->bonded_port_id,\n \t\t\t\tnb_tx, burst_size);\n@@ -3455,6 +3722,125 @@ test_broadcast_tx_burst(void)\n \treturn remove_slaves_and_stop_bonded_device();\n }\n \n+\n+#define TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT\t\t(3)\n+#define TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE\t\t\t(40)\n+#define TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT\t(15)\n+#define TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT\t(10)\n+\n+static int\n+test_broadcast_tx_burst_slave_tx_fail(void)\n+{\n+\tstruct rte_mbuf *pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE];\n+\tstruct rte_mbuf *expected_fail_pkts[TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT];\n+\n+\tstruct rte_eth_stats port_stats;\n+\n+\tint i, tx_count;\n+\n+\tTEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(\n+\t\t\tBONDING_MODE_BROADCAST, 0,\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT, 1),\n+\t\t\t\"Failed to intialise bonded device\");\n+\n+\t/* Generate test bursts for transmission */\n+\tTEST_ASSERT_EQUAL(generate_test_burst(pkts_burst,\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE, 0, 0, 0, 0, 0),\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE,\n+\t\t\t\"Failed to generate test packet burst\");\n+\n+\tfor (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {\n+\t\texpected_fail_pkts[i] = pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT + i];\n+\t}\n+\n+\t/* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail\n+\t * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */\n+\tvirtual_ethdev_tx_burst_fn_set_success(\n+\t\t\ttest_params->slave_port_ids[0],\n+\t\t\t0);\n+\tvirtual_ethdev_tx_burst_fn_set_success(\n+\t\t\ttest_params->slave_port_ids[1],\n+\t\t\t0);\n+\tvirtual_ethdev_tx_burst_fn_set_success(\n+\t\t\ttest_params->slave_port_ids[2],\n+\t\t\t0);\n+\n+\tvirtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(\n+\t\t\ttest_params->slave_port_ids[0],\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);\n+\n+\tvirtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(\n+\t\t\ttest_params->slave_port_ids[1],\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);\n+\n+\tvirtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(\n+\t\t\ttest_params->slave_port_ids[2],\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);\n+\n+\t/* Transmit burst */\n+\ttx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE);\n+\n+\tTEST_ASSERT_EQUAL(tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,\n+\t\t\t\"Transmitted (%d) packets, expected to transmit (%d) packets\",\n+\t\t\ttx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);\n+\n+\t/* Verify that failed packet are expected failed packets */\n+\tfor (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {\n+\t\tTEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst[i + tx_count],\n+\t\t\t\t\"expected mbuf (%d) pointer %p not expected pointer %p\",\n+\t\t\t\ti, expected_fail_pkts[i], pkts_burst[i + tx_count]);\n+\t}\n+\n+\t/* Verify slave ports tx stats */\n+\n+\trte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t(uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,\n+\t\t\t\"Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\ttest_params->bonded_port_id, (unsigned int)port_stats.opackets,\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);\n+\n+\n+\trte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t(uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,\n+\t\t\t\"Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\ttest_params->bonded_port_id, (unsigned int)port_stats.opackets,\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);\n+\n+\trte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);\n+\n+\tTEST_ASSERT_EQUAL(port_stats.opackets,\n+\t\t\t(uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,\n+\t\t\t\"Port (%d) opackets value (%u) not as expected (%d)\",\n+\t\t\ttest_params->bonded_port_id, (unsigned int)port_stats.opackets,\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);\n+\n+\n+\t/* Verify that all mbufs who transmission failed have a ref value of one */\n+\tTEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst[tx_count],\n+\t\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, 1),\n+\t\t\t\"mbufs refcnts not as expected\");\n+\n+\tfree_mbufs(&pkts_burst[tx_count],\n+\t\tTEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);\n+\n+\t/* Clean up and remove slaves from bonded device */\n+\treturn remove_slaves_and_stop_bonded_device();\n+}\n+\n #define BROADCAST_RX_BURST_NUM_OF_SLAVES (3)\n \n static int\n@@ -3767,7 +4153,7 @@ test_broadcast_verify_slave_link_status_change_behaviour(void)\n \t}\n \n \tif (rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0],\n-\t\t\tburst_size) != (burst_size * slave_count)) {\n+\t\t\tburst_size) != burst_size) {\n \t\tprintf(\"rte_eth_tx_burst failed\\n\");\n \t\treturn -1;\n \t}\n@@ -3915,6 +4301,7 @@ static struct unit_test_suite link_bonding_test_suite  = {\n \t\tTEST_CASE(test_status_interrupt),\n \t\tTEST_CASE(test_adding_slave_after_bonded_device_started),\n \t\tTEST_CASE(test_roundrobin_tx_burst),\n+\t\tTEST_CASE(test_roundrobin_tx_burst_slave_tx_fail),\n \t\tTEST_CASE(test_roundrobin_rx_burst_on_single_slave),\n \t\tTEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves),\n \t\tTEST_CASE(test_roundrobin_verify_promiscuous_enable_disable),\n@@ -3938,11 +4325,13 @@ static struct unit_test_suite link_bonding_test_suite  = {\n \t\tTEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr),\n \t\tTEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr),\n \t\tTEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port),\n+\t\tTEST_CASE(test_balance_tx_burst_slave_tx_fail),\n \t\tTEST_CASE(test_balance_rx_burst),\n \t\tTEST_CASE(test_balance_verify_promiscuous_enable_disable),\n \t\tTEST_CASE(test_balance_verify_mac_assignment),\n \t\tTEST_CASE(test_balance_verify_slave_link_status_change_behaviour),\n \t\tTEST_CASE(test_broadcast_tx_burst),\n+\t\tTEST_CASE(test_broadcast_tx_burst_slave_tx_fail),\n \t\tTEST_CASE(test_broadcast_rx_burst),\n \t\tTEST_CASE(test_broadcast_verify_promiscuous_enable_disable),\n \t\tTEST_CASE(test_broadcast_verify_mac_assignment),\ndiff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c\nindex e861c5b..f9bd841 100644\n--- a/app/test/virtual_pmd.c\n+++ b/app/test/virtual_pmd.c\n@@ -48,6 +48,8 @@ struct virtual_ethdev_private {\n \n \tstruct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST];\n \tint rx_pkt_burst_len;\n+\n+\tint tx_burst_fail_count;\n };\n \n struct virtual_ethdev_queue {\n@@ -350,42 +352,67 @@ virtual_ethdev_rx_burst_fail(void *queue __rte_unused,\n }\n \n static uint16_t\n-virtual_ethdev_tx_burst_success(void *queue,\n-\t\t\t\t\t\t\t struct rte_mbuf **bufs __rte_unused,\n-\t\t\t\t\t\t\t uint16_t nb_pkts)\n+virtual_ethdev_tx_burst_success(void *queue, struct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n {\n+\tstruct virtual_ethdev_queue *tx_q = (struct virtual_ethdev_queue *)queue;\n+\n \tstruct rte_eth_dev *vrtl_eth_dev;\n-\tstruct virtual_ethdev_queue *tx_q;\n \tstruct virtual_ethdev_private *dev_private;\n-\tint i;\n \n-\ttx_q = (struct virtual_ethdev_queue *)queue;\n+\tint i;\n \n \tvrtl_eth_dev = &rte_eth_devices[tx_q->port_id];\n+\tdev_private = vrtl_eth_dev->data->dev_private;\n \n \tif (vrtl_eth_dev->data->dev_link.link_status) {\n-\t\tdev_private = vrtl_eth_dev->data->dev_private;\n+\t\t/* increment opacket count */\n \t\tdev_private->eth_stats.opackets += nb_pkts;\n \n-\t\treturn nb_pkts;\n-\t}\n-\n-\t/* free packets in burst */\n-\tfor (i = 0; i < nb_pkts; i++) {\n-\t\tif (bufs[i] != NULL)\n+\t\t/* free packets in burst */\n+\t\tfor (i = 0; i < nb_pkts; i++) {\n \t\t\trte_pktmbuf_free(bufs[i]);\n+\t\t\tbufs[i] = NULL;\n+\t\t}\n \n-\t\tbufs[i] = NULL;\n+\t\treturn nb_pkts;\n \t}\n \n \treturn 0;\n }\n \n-\n static uint16_t\n-virtual_ethdev_tx_burst_fail(void *queue __rte_unused,\n-\t\tstruct rte_mbuf **bufs __rte_unused, uint16_t nb_pkts __rte_unused)\n+virtual_ethdev_tx_burst_fail(void *queue, struct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n {\n+\tstruct rte_eth_dev *vrtl_eth_dev = NULL;\n+\tstruct virtual_ethdev_queue *tx_q = NULL;\n+\tstruct virtual_ethdev_private *dev_private = NULL;\n+\n+\tint i;\n+\n+\ttx_q = (struct virtual_ethdev_queue *)queue;\n+\tvrtl_eth_dev = &rte_eth_devices[tx_q->port_id];\n+\tdev_private = vrtl_eth_dev->data->dev_private;\n+\n+\tif (dev_private->tx_burst_fail_count < nb_pkts) {\n+\t\tint successfully_txd = nb_pkts - dev_private->tx_burst_fail_count;\n+\n+\t\t/* increment opacket count */\n+\t\tdev_private->eth_stats.opackets += successfully_txd;\n+\n+\t\t/* free packets in burst */\n+\t\tfor (i = 0; i < successfully_txd; i++) {\n+\t\t\t/* free packets in burst */\n+\t\t\tif (bufs[i] != NULL)\n+\t\t\t\trte_pktmbuf_free(bufs[i]);\n+\n+\t\t\tbufs[i] = NULL;\n+\t\t}\n+\n+\t\treturn successfully_txd;\n+\t}\n+\n \treturn 0;\n }\n \n@@ -405,17 +432,34 @@ virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success)\n void\n virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success)\n {\n+\tstruct virtual_ethdev_private *dev_private = NULL;\n \tstruct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];\n \n+\tdev_private = vrtl_eth_dev->data->dev_private;\n+\n \tif (success)\n \t\tvrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;\n \telse\n \t\tvrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_fail;\n+\n+\tdev_private->tx_burst_fail_count = 0;\n }\n \n+void\n+virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id,\n+\t\tuint8_t packet_fail_count)\n+{\n+\tstruct virtual_ethdev_private *dev_private = NULL;\n+\tstruct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];\n+\n+\n+\tdev_private = vrtl_eth_dev->data->dev_private;\n+\tdev_private->tx_burst_fail_count = packet_fail_count;\n+}\n \n void\n-virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id, uint8_t link_status)\n+virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id,\n+\t\tuint8_t link_status)\n {\n \tstruct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];\n \ndiff --git a/app/test/virtual_pmd.h b/app/test/virtual_pmd.h\nindex 766b6ac..3b5c911 100644\n--- a/app/test/virtual_pmd.h\n+++ b/app/test/virtual_pmd.h\n@@ -67,6 +67,13 @@ void virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success);\n \n void virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success);\n \n+/* if a value greater than zero is set for packet_fail_count then virtual\n+ * device tx burst function will fail that many packet from burst or all\n+ * packets if packet_fail_count is greater than the number of packets in the\n+ * burst */\n+void virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id,\n+\t\tuint8_t packet_fail_count);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\nindex 54d3e38..6018feb 100644\n--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c\n@@ -101,10 +101,10 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,\n \tuint8_t num_of_slaves;\n \tuint8_t slaves[RTE_MAX_ETHPORTS];\n \n-\tuint16_t num_tx_total = 0;\n+\tuint16_t num_tx_total = 0, num_tx_slave;\n \n \tstatic int slave_idx = 0;\n-\tint i, cs_idx = 0;\n+\tint i, cslave_idx = 0, tx_fail_total = 0;\n \n \tbd_tx_q = (struct bond_tx_queue *)queue;\n \tinternals = bd_tx_q->dev_private;\n@@ -120,19 +120,32 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,\n \n \t/* Populate slaves mbuf with which packets are to be sent on it  */\n \tfor (i = 0; i < nb_pkts; i++) {\n-\t\tcs_idx = (slave_idx + i) % num_of_slaves;\n-\t\tslave_bufs[cs_idx][(slave_nb_pkts[cs_idx])++] = bufs[i];\n+\t\tcslave_idx = (slave_idx + i) % num_of_slaves;\n+\t\tslave_bufs[cslave_idx][(slave_nb_pkts[cslave_idx])++] = bufs[i];\n \t}\n \n \t/* increment current slave index so the next call to tx burst starts on the\n \t * next slave */\n-\tslave_idx = ++cs_idx;\n+\tslave_idx = ++cslave_idx;\n \n \t/* Send packet burst on each slave device */\n-\tfor (i = 0; i < num_of_slaves; i++)\n-\t\tif (slave_nb_pkts[i] > 0)\n-\t\t\tnum_tx_total += rte_eth_tx_burst(slaves[i],\n-\t\t\t\t\tbd_tx_q->queue_id, slave_bufs[i], slave_nb_pkts[i]);\n+\tfor (i = 0; i < num_of_slaves; i++) {\n+\t\tif (slave_nb_pkts[i] > 0) {\n+\t\t\tnum_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n+\t\t\t\t\tslave_bufs[i], slave_nb_pkts[i]);\n+\n+\t\t\t/* if tx burst fails move packets to end of bufs */\n+\t\t\tif (unlikely(num_tx_slave < slave_nb_pkts[i])) {\n+\t\t\t\tint tx_fail_slave = slave_nb_pkts[i] - num_tx_slave;\n+\n+\t\t\t\ttx_fail_total += tx_fail_slave;\n+\n+\t\t\t\tmemcpy(&bufs[nb_pkts - tx_fail_total],\n+\t\t\t\t\t\t&slave_bufs[i][num_tx_slave], tx_fail_slave * sizeof(bufs[0]));\n+\t\t\t}\n+\t\t\tnum_tx_total += num_tx_slave;\n+\t\t}\n+\t}\n \n \treturn num_tx_total;\n }\n@@ -283,7 +296,7 @@ bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,\n \tuint8_t num_of_slaves;\n \tuint8_t slaves[RTE_MAX_ETHPORTS];\n \n-\tuint16_t num_tx_total = 0;\n+\tuint16_t num_tx_total = 0, num_tx_slave = 0, tx_fail_total = 0;\n \n \tint i, op_slave_id;\n \n@@ -315,11 +328,23 @@ bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,\n \t/* Send packet burst on each slave device */\n \tfor (i = 0; i < num_of_slaves; i++) {\n \t\tif (slave_nb_pkts[i] > 0) {\n-\t\t\tnum_tx_total += rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n+\t\t\tnum_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n \t\t\t\t\tslave_bufs[i], slave_nb_pkts[i]);\n+\n+\t\t\t/* if tx burst fails move packets to end of bufs */\n+\t\t\tif (unlikely(num_tx_slave < slave_nb_pkts[i])) {\n+\t\t\t\tint slave_tx_fail_count = slave_nb_pkts[i] - num_tx_slave;\n+\n+\t\t\t\ttx_fail_total += slave_tx_fail_count;\n+\t\t\t\tmemcpy(bufs[nb_pkts - tx_fail_total],\n+\t\t\t\t\t\tslave_bufs[i][num_tx_slave], slave_tx_fail_count);\n+\t\t\t}\n+\n+\t\t\tnum_tx_total += num_tx_slave;\n \t\t}\n \t}\n \n+\n \treturn num_tx_total;\n }\n \n@@ -330,12 +355,13 @@ bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,\n \tstruct bond_dev_private *internals;\n \tstruct bond_tx_queue *bd_tx_q;\n \n-\tuint8_t num_of_slaves;\n+\tuint8_t tx_failed_flag = 0, num_of_slaves;\n \tuint8_t slaves[RTE_MAX_ETHPORTS];\n \n-\tuint16_t num_tx_total = 0;\n+\tuint16_t max_nb_of_tx_pkts = 0;\n \n-\tint i;\n+\tint slave_tx_total[RTE_MAX_ETHPORTS];\n+\tint i, most_scuccesful_tx_slave;\n \n \tbd_tx_q = (struct bond_tx_queue *)queue;\n \tinternals = bd_tx_q->dev_private;\n@@ -354,11 +380,32 @@ bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,\n \t\trte_mbuf_refcnt_update(bufs[i], num_of_slaves - 1);\n \n \t/* Transmit burst on each active slave */\n-\tfor (i = 0; i < num_of_slaves; i++)\n-\t\tnum_tx_total += rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n-\t\t\t\tbufs, nb_pkts);\n+\tfor (i = 0; i < num_of_slaves; i++) {\n+\t\tslave_tx_total[i] = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,\n+\t\t\t\t\tbufs, nb_pkts);\n \n-\treturn num_tx_total;\n+\t\tif (unlikely(slave_tx_total[i] < nb_pkts))\n+\t\t\ttx_failed_flag = 1;\n+\n+\t\t/* record the value and slave index for the slave which transmits the\n+\t\t * maximum number of packets */\n+\t\tif (slave_tx_total[i] > max_nb_of_tx_pkts) {\n+\t\t\tmax_nb_of_tx_pkts = slave_tx_total[i];\n+\t\t\tmost_scuccesful_tx_slave = i;\n+\t\t}\n+\t}\n+\n+\t/* if slaves fail to transmit packets from burst, the calling application\n+\t * is not expected to know about multiple references to packets so we must\n+\t * handle failures of all packets except those of the most successful slave\n+\t */\n+\tif (unlikely(tx_failed_flag))\n+\t\tfor (i = 0; i < num_of_slaves; i++)\n+\t\t\tif (i != most_scuccesful_tx_slave)\n+\t\t\t\twhile (slave_tx_total[i] < nb_pkts)\n+\t\t\t\t\trte_pktmbuf_free(bufs[slave_tx_total[i]++]);\n+\n+\treturn max_nb_of_tx_pkts;\n }\n \n void\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "1/5"
    ]
}