get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 9920,
    "url": "http://patches.dpdk.org/api/patches/9920/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1452869038-9140-3-git-send-email-tomaszx.kulasek@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": "<1452869038-9140-3-git-send-email-tomaszx.kulasek@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1452869038-9140-3-git-send-email-tomaszx.kulasek@intel.com",
    "date": "2016-01-15T14:43:58",
    "name": "[dpdk-dev,2/2] examples: sample apps rework to use buffered tx api",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1375d02aebde008bc36d034dbdab3a57732ca707",
    "submitter": {
        "id": 155,
        "url": "http://patches.dpdk.org/api/people/155/?format=api",
        "name": "Tomasz Kulasek",
        "email": "tomaszx.kulasek@intel.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/project/dpdk/patch/1452869038-9140-3-git-send-email-tomaszx.kulasek@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/9920/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/9920/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 EE9A08E6A;\n\tFri, 15 Jan 2016 15:45:19 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id D82FE8E5E\n\tfor <dev@dpdk.org>; Fri, 15 Jan 2016 15:45:17 +0100 (CET)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby orsmga102.jf.intel.com with ESMTP; 15 Jan 2016 06:45:13 -0800",
            "from unknown (HELO Sent) ([10.217.248.171])\n\tby orsmga001.jf.intel.com with SMTP; 15 Jan 2016 06:45:11 -0800",
            "by Sent (sSMTP sendmail emulation); Fri, 15 Jan 2016 15:44:49 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.22,299,1449561600\"; d=\"scan'208\";a=\"861192879\"",
        "From": "Tomasz Kulasek <tomaszx.kulasek@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri, 15 Jan 2016 15:43:58 +0100",
        "Message-Id": "<1452869038-9140-3-git-send-email-tomaszx.kulasek@intel.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<1452869038-9140-1-git-send-email-tomaszx.kulasek@intel.com>",
        "References": "<1452869038-9140-1-git-send-email-tomaszx.kulasek@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 2/2] examples: sample apps rework to use buffered\n\ttx api",
        "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": "The internal buffering of packets for TX in sample apps is no longer\nneeded, so this patchset replaces this code with calls to the new\nrte_eth_tx_buffer* APIs in:\n\n* l2fwd-jobstats\n* l2fwd-keepalive\n* l2fwd\n* l3fwd-acl\n* l3fwd-power\n* link_status_interrupt\n* client_server_mp\n* l2fwd_fork\n* packet_ordering\n* qos_meter\n\nSigned-off-by: Bruce Richardson <bruce.richardson@intel.com>\nSigned-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>\n---\n examples/l2fwd-jobstats/main.c                     |   73 +++++------------\n examples/l2fwd-keepalive/main.c                    |   79 ++++---------------\n examples/l2fwd/main.c                              |   80 ++++---------------\n examples/l3fwd-acl/main.c                          |   64 ++-------------\n examples/l3fwd-power/main.c                        |   63 ++-------------\n examples/link_status_interrupt/main.c              |   83 ++++----------------\n .../client_server_mp/mp_client/client.c            |   77 ++++++++----------\n examples/multi_process/l2fwd_fork/main.c           |   81 ++++---------------\n examples/packet_ordering/main.c                    |   62 +++++++--------\n examples/qos_meter/main.c                          |   46 ++---------\n 10 files changed, 166 insertions(+), 542 deletions(-)",
    "diff": "diff --git a/examples/l2fwd-jobstats/main.c b/examples/l2fwd-jobstats/main.c\nindex 7b59f4e..9a6e6ea 100644\n--- a/examples/l2fwd-jobstats/main.c\n+++ b/examples/l2fwd-jobstats/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -99,8 +99,6 @@ static unsigned int l2fwd_rx_queue_per_lcore = 1;\n \n struct mbuf_table {\n \tuint64_t next_flush_time;\n-\tunsigned len;\n-\tstruct rte_mbuf *mbufs[MAX_PKT_BURST];\n };\n \n #define MAX_RX_QUEUE_PER_LCORE 16\n@@ -373,58 +371,12 @@ show_stats_cb(__rte_unused void *param)\n \trte_eal_alarm_set(timer_period * US_PER_S, show_stats_cb, NULL);\n }\n \n-/* Send the burst of packets on an output interface */\n-static void\n-l2fwd_send_burst(struct lcore_queue_conf *qconf, uint8_t port)\n-{\n-\tstruct mbuf_table *m_table;\n-\tuint16_t ret;\n-\tuint16_t queueid = 0;\n-\tuint16_t n;\n-\n-\tm_table = &qconf->tx_mbufs[port];\n-\tn = m_table->len;\n-\n-\tm_table->next_flush_time = rte_get_timer_cycles() + drain_tsc;\n-\tm_table->len = 0;\n-\n-\tret = rte_eth_tx_burst(port, queueid, m_table->mbufs, n);\n-\n-\tport_statistics[port].tx += ret;\n-\tif (unlikely(ret < n)) {\n-\t\tport_statistics[port].dropped += (n - ret);\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table->mbufs[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-}\n-\n-/* Enqueue packets for TX and prepare them to be sent */\n-static int\n-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)\n-{\n-\tconst unsigned lcore_id = rte_lcore_id();\n-\tstruct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id];\n-\tstruct mbuf_table *m_table = &qconf->tx_mbufs[port];\n-\tuint16_t len = qconf->tx_mbufs[port].len;\n-\n-\tm_table->mbufs[len] = m;\n-\n-\tlen++;\n-\tm_table->len = len;\n-\n-\t/* Enough pkts to be sent. */\n-\tif (unlikely(len == MAX_PKT_BURST))\n-\t\tl2fwd_send_burst(qconf, port);\n-\n-\treturn 0;\n-}\n-\n static void\n l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n {\n \tstruct ether_hdr *eth;\n \tvoid *tmp;\n+\tint sent;\n \tunsigned dst_port;\n \n \tdst_port = l2fwd_dst_ports[portid];\n@@ -437,7 +389,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n \t/* src addr */\n \tether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);\n \n-\tl2fwd_send_packet(m, (uint8_t) dst_port);\n+\tsent = rte_eth_tx_buffer(dst_port, 0, m);\n+\tif (sent)\n+\t\tport_statistics[dst_port].tx += sent;\n }\n \n static void\n@@ -513,6 +467,8 @@ l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg)\n \tstruct lcore_queue_conf *qconf;\n \tstruct mbuf_table *m_table;\n \tuint8_t portid;\n+\tunsigned i;\n+\tuint32_t sent;\n \n \tlcore_id = rte_lcore_id();\n \tqconf = &lcore_queue_conf[lcore_id];\n@@ -522,12 +478,19 @@ l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg)\n \tnow = rte_get_timer_cycles();\n \tlcore_id = rte_lcore_id();\n \tqconf = &lcore_queue_conf[lcore_id];\n-\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\tm_table = &qconf->tx_mbufs[portid];\n-\t\tif (m_table->len == 0 || m_table->next_flush_time <= now)\n+\n+\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\t\tm_table = &qconf->tx_mbufs[i];\n+\n+\t\tif (m_table->next_flush_time <= now)\n \t\t\tcontinue;\n+\t\tm_table->next_flush_time = rte_get_timer_cycles() + drain_tsc;\n \n-\t\tl2fwd_send_burst(qconf, portid);\n+\t\tportid = qconf->rx_port_list[i];\n+\t\tportid = l2fwd_dst_ports[portid];\n+\t\tsent = rte_eth_tx_buffer_flush(portid, 0);\n+\t\tif (sent)\n+\t\t\tport_statistics[portid].tx += sent;\n \t}\n \n \ndiff --git a/examples/l2fwd-keepalive/main.c b/examples/l2fwd-keepalive/main.c\nindex f4d52f2..b59ff6d 100644\n--- a/examples/l2fwd-keepalive/main.c\n+++ b/examples/l2fwd-keepalive/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -97,17 +97,11 @@ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];\n \n static unsigned int l2fwd_rx_queue_per_lcore = 1;\n \n-struct mbuf_table {\n-\tunsigned len;\n-\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n-};\n-\n #define MAX_RX_QUEUE_PER_LCORE 16\n #define MAX_TX_QUEUE_PER_PORT 16\n struct lcore_queue_conf {\n \tunsigned n_rx_port;\n \tunsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];\n-\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n \n } __rte_cache_aligned;\n struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];\n@@ -132,7 +126,7 @@ struct rte_mempool *l2fwd_pktmbuf_pool = NULL;\n struct l2fwd_port_statistics {\n \tuint64_t tx;\n \tuint64_t rx;\n-\tuint64_t dropped;\n+\tunsigned long dropped;\n } __rte_cache_aligned;\n struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];\n \n@@ -192,57 +186,12 @@ print_stats(__attribute__((unused)) struct rte_timer *ptr_timer,\n \tprintf(\"\\n====================================================\\n\");\n }\n \n-/* Send the burst of packets on an output interface */\n-static int\n-l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)\n-{\n-\tstruct rte_mbuf **m_table;\n-\tunsigned ret;\n-\tunsigned queueid = 0;\n-\n-\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n-\n-\tret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);\n-\tport_statistics[port].tx += ret;\n-\tif (unlikely(ret < n)) {\n-\t\tport_statistics[port].dropped += (n - ret);\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Enqueue packets for TX and prepare them to be sent */\n-static int\n-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)\n-{\n-\tunsigned lcore_id, len;\n-\tstruct lcore_queue_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n-\n-\tqconf = &lcore_queue_conf[lcore_id];\n-\tlen = qconf->tx_mbufs[port].len;\n-\tqconf->tx_mbufs[port].m_table[len] = m;\n-\tlen++;\n-\n-\t/* enough pkts to be sent */\n-\tif (unlikely(len == MAX_PKT_BURST)) {\n-\t\tl2fwd_send_burst(qconf, MAX_PKT_BURST, port);\n-\t\tlen = 0;\n-\t}\n-\n-\tqconf->tx_mbufs[port].len = len;\n-\treturn 0;\n-}\n-\n static void\n l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n {\n \tstruct ether_hdr *eth;\n \tvoid *tmp;\n+\tint sent;\n \tunsigned dst_port;\n \n \tdst_port = l2fwd_dst_ports[portid];\n@@ -255,7 +204,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n \t/* src addr */\n \tether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);\n \n-\tl2fwd_send_packet(m, (uint8_t) dst_port);\n+\tsent = rte_eth_tx_buffer(dst_port, 0, m);\n+\tif (sent)\n+\t\tport_statistics[dst_port].tx += sent;\n }\n \n /* main processing loop */\n@@ -265,6 +216,7 @@ l2fwd_main_loop(void)\n \tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n \tstruct rte_mbuf *m;\n \tunsigned lcore_id;\n+\tint sent;\n \tuint64_t prev_tsc, diff_tsc, cur_tsc;\n \tunsigned i, j, portid, nb_rx;\n \tstruct lcore_queue_conf *qconf;\n@@ -312,13 +264,12 @@ l2fwd_main_loop(void)\n \t\tdiff_tsc = cur_tsc - prev_tsc;\n \t\tif (unlikely(diff_tsc > drain_tsc)) {\n \n-\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tl2fwd_send_burst(&lcore_queue_conf[lcore_id],\n-\t\t\t\t\t\t qconf->tx_mbufs[portid].len,\n-\t\t\t\t\t\t (uint8_t) portid);\n-\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n+\t\t\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\t\t\t\tportid = qconf->rx_port_list[i];\n+\t\t\t\tportid = l2fwd_dst_ports[portid];\n+\t\t\t\tsent = rte_eth_tx_buffer_flush(portid, 0);\n+\t\t\t\tif (sent)\n+\t\t\t\t\tport_statistics[portid].tx += sent;\n \t\t\t}\n \n \t\t\tprev_tsc = cur_tsc;\n@@ -713,6 +664,10 @@ main(int argc, char **argv)\n \t\t\t\t\"rte_eth_tx_queue_setup:err=%d, port=%u\\n\",\n \t\t\t\tret, (unsigned) portid);\n \n+\t\trte_eth_tx_buffer_set_err_callback(portid, 0,\n+\t\t\t\trte_eth_count_unsent_packet_callback,\n+\t\t\t\t&port_statistics[portid].dropped);\n+\n \t\t/* Start device */\n \t\tret = rte_eth_dev_start(portid);\n \t\tif (ret < 0)\ndiff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c\nindex 720fd5a..e6dce27 100644\n--- a/examples/l2fwd/main.c\n+++ b/examples/l2fwd/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -95,17 +95,11 @@ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];\n \n static unsigned int l2fwd_rx_queue_per_lcore = 1;\n \n-struct mbuf_table {\n-\tunsigned len;\n-\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n-};\n-\n #define MAX_RX_QUEUE_PER_LCORE 16\n #define MAX_TX_QUEUE_PER_PORT 16\n struct lcore_queue_conf {\n \tunsigned n_rx_port;\n \tunsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];\n-\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n \n } __rte_cache_aligned;\n struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];\n@@ -130,7 +124,7 @@ struct rte_mempool * l2fwd_pktmbuf_pool = NULL;\n struct l2fwd_port_statistics {\n \tuint64_t tx;\n \tuint64_t rx;\n-\tuint64_t dropped;\n+\tunsigned long dropped;\n } __rte_cache_aligned;\n struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];\n \n@@ -185,57 +179,12 @@ print_stats(void)\n \tprintf(\"\\n====================================================\\n\");\n }\n \n-/* Send the burst of packets on an output interface */\n-static int\n-l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)\n-{\n-\tstruct rte_mbuf **m_table;\n-\tunsigned ret;\n-\tunsigned queueid =0;\n-\n-\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n-\n-\tret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);\n-\tport_statistics[port].tx += ret;\n-\tif (unlikely(ret < n)) {\n-\t\tport_statistics[port].dropped += (n - ret);\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Enqueue packets for TX and prepare them to be sent */\n-static int\n-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)\n-{\n-\tunsigned lcore_id, len;\n-\tstruct lcore_queue_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n-\n-\tqconf = &lcore_queue_conf[lcore_id];\n-\tlen = qconf->tx_mbufs[port].len;\n-\tqconf->tx_mbufs[port].m_table[len] = m;\n-\tlen++;\n-\n-\t/* enough pkts to be sent */\n-\tif (unlikely(len == MAX_PKT_BURST)) {\n-\t\tl2fwd_send_burst(qconf, MAX_PKT_BURST, port);\n-\t\tlen = 0;\n-\t}\n-\n-\tqconf->tx_mbufs[port].len = len;\n-\treturn 0;\n-}\n-\n static void\n l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n {\n \tstruct ether_hdr *eth;\n \tvoid *tmp;\n+\tint sent;\n \tunsigned dst_port;\n \n \tdst_port = l2fwd_dst_ports[portid];\n@@ -248,7 +197,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n \t/* src addr */\n \tether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);\n \n-\tl2fwd_send_packet(m, (uint8_t) dst_port);\n+\tsent = rte_eth_tx_buffer(dst_port, 0, m);\n+\tif (sent)\n+\t\tport_statistics[dst_port].tx += sent;\n }\n \n /* main processing loop */\n@@ -258,6 +209,7 @@ l2fwd_main_loop(void)\n \tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n \tstruct rte_mbuf *m;\n \tunsigned lcore_id;\n+\tint sent;\n \tuint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;\n \tunsigned i, j, portid, nb_rx;\n \tstruct lcore_queue_conf *qconf;\n@@ -277,7 +229,6 @@ l2fwd_main_loop(void)\n \tRTE_LOG(INFO, L2FWD, \"entering main loop on lcore %u\\n\", lcore_id);\n \n \tfor (i = 0; i < qconf->n_rx_port; i++) {\n-\n \t\tportid = qconf->rx_port_list[i];\n \t\tRTE_LOG(INFO, L2FWD, \" -- lcoreid=%u portid=%u\\n\", lcore_id,\n \t\t\tportid);\n@@ -293,13 +244,12 @@ l2fwd_main_loop(void)\n \t\tdiff_tsc = cur_tsc - prev_tsc;\n \t\tif (unlikely(diff_tsc > drain_tsc)) {\n \n-\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tl2fwd_send_burst(&lcore_queue_conf[lcore_id],\n-\t\t\t\t\t\t qconf->tx_mbufs[portid].len,\n-\t\t\t\t\t\t (uint8_t) portid);\n-\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n+\t\t\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\t\t\t\tportid = qconf->rx_port_list[i];\n+\t\t\t\tportid = l2fwd_dst_ports[portid];\n+\t\t\t\tsent = rte_eth_tx_buffer_flush(portid, 0);\n+\t\t\t\tif (sent)\n+\t\t\t\t\tport_statistics[portid].tx += sent;\n \t\t\t}\n \n \t\t\t/* if timer is enabled */\n@@ -666,6 +616,10 @@ main(int argc, char **argv)\n \t\t\trte_exit(EXIT_FAILURE, \"rte_eth_tx_queue_setup:err=%d, port=%u\\n\",\n \t\t\t\tret, (unsigned) portid);\n \n+\t\trte_eth_tx_buffer_set_err_callback(portid, 0,\n+\t\t\t\trte_eth_count_unsent_packet_callback,\n+\t\t\t\t&port_statistics[portid].dropped);\n+\n \t\t/* Start device */\n \t\tret = rte_eth_dev_start(portid);\n \t\tif (ret < 0)\ndiff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c\nindex f676d14..810cdac 100644\n--- a/examples/l3fwd-acl/main.c\n+++ b/examples/l3fwd-acl/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -119,11 +119,6 @@ static uint32_t enabled_port_mask;\n static int promiscuous_on; /**< Ports set in promiscuous mode off by default. */\n static int numa_on = 1; /**< NUMA is enabled by default. */\n \n-struct mbuf_table {\n-\tuint16_t len;\n-\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n-};\n-\n struct lcore_rx_queue {\n \tuint8_t port_id;\n \tuint8_t queue_id;\n@@ -187,7 +182,7 @@ static struct rte_mempool *pktmbuf_pool[NB_SOCKETS];\n static inline int\n is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len);\n #endif\n-static inline int\n+static inline void\n send_single_packet(struct rte_mbuf *m, uint8_t port);\n \n #define MAX_ACL_RULE_NUM\t100000\n@@ -1292,55 +1287,17 @@ struct lcore_conf {\n \tuint16_t n_rx_queue;\n \tstruct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];\n \tuint16_t tx_queue_id[RTE_MAX_ETHPORTS];\n-\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n } __rte_cache_aligned;\n \n static struct lcore_conf lcore_conf[RTE_MAX_LCORE];\n \n-/* Send burst of packets on an output interface */\n-static inline int\n-send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port)\n-{\n-\tstruct rte_mbuf **m_table;\n-\tint ret;\n-\tuint16_t queueid;\n-\n-\tqueueid = qconf->tx_queue_id[port];\n-\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n-\n-\tret = rte_eth_tx_burst(port, queueid, m_table, n);\n-\tif (unlikely(ret < n)) {\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-\n-\treturn 0;\n-}\n-\n /* Enqueue a single packet, and send burst if queue is filled */\n-static inline int\n+static inline void\n send_single_packet(struct rte_mbuf *m, uint8_t port)\n {\n-\tuint32_t lcore_id;\n-\tuint16_t len;\n-\tstruct lcore_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n-\n-\tqconf = &lcore_conf[lcore_id];\n-\tlen = qconf->tx_mbufs[port].len;\n-\tqconf->tx_mbufs[port].m_table[len] = m;\n-\tlen++;\n-\n-\t/* enough pkts to be sent */\n-\tif (unlikely(len == MAX_PKT_BURST)) {\n-\t\tsend_burst(qconf, MAX_PKT_BURST, port);\n-\t\tlen = 0;\n-\t}\n+\tuint16_t q = lcore_conf[rte_lcore_id()].tx_queue_id[port];\n \n-\tqconf->tx_mbufs[port].len = len;\n-\treturn 0;\n+\trte_eth_tx_buffer(port, q, m);\n }\n \n #ifdef DO_RFC_1812_CHECKS\n@@ -1433,14 +1390,9 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\t\t * This could be optimized (use queueid instead of\n \t\t\t * portid), but it is not called so often\n \t\t\t */\n-\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tsend_burst(&lcore_conf[lcore_id],\n-\t\t\t\t\tqconf->tx_mbufs[portid].len,\n-\t\t\t\t\tportid);\n-\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n-\t\t\t}\n+\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)\n+\t\t\t\trte_eth_tx_buffer_flush(portid,\n+\t\t\t\t\t\tqconf->tx_queue_id[portid]);\n \n \t\t\tprev_tsc = cur_tsc;\n \t\t}\ndiff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c\nindex 828c18a..6f32242 100644\n--- a/examples/l3fwd-power/main.c\n+++ b/examples/l3fwd-power/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -173,11 +173,6 @@ enum freq_scale_hint_t\n \tFREQ_HIGHEST  =       2\n };\n \n-struct mbuf_table {\n-\tuint16_t len;\n-\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n-};\n-\n struct lcore_rx_queue {\n \tuint8_t port_id;\n \tuint8_t queue_id;\n@@ -348,7 +343,6 @@ struct lcore_conf {\n \tuint16_t n_rx_queue;\n \tstruct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];\n \tuint16_t tx_queue_id[RTE_MAX_ETHPORTS];\n-\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n \tlookup_struct_t * ipv4_lookup_struct;\n \tlookup_struct_t * ipv6_lookup_struct;\n } __rte_cache_aligned;\n@@ -442,50 +436,12 @@ power_timer_cb(__attribute__((unused)) struct rte_timer *tim,\n \tstats[lcore_id].sleep_time = 0;\n }\n \n-/* Send burst of packets on an output interface */\n-static inline int\n-send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port)\n-{\n-\tstruct rte_mbuf **m_table;\n-\tint ret;\n-\tuint16_t queueid;\n-\n-\tqueueid = qconf->tx_queue_id[port];\n-\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n-\n-\tret = rte_eth_tx_burst(port, queueid, m_table, n);\n-\tif (unlikely(ret < n)) {\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Enqueue a single packet, and send burst if queue is filled */\n-static inline int\n+static inline void\n send_single_packet(struct rte_mbuf *m, uint8_t port)\n {\n-\tuint32_t lcore_id;\n-\tuint16_t len;\n-\tstruct lcore_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n+\tuint16_t q = lcore_conf[rte_lcore_id()].tx_queue_id[port];\n \n-\tqconf = &lcore_conf[lcore_id];\n-\tlen = qconf->tx_mbufs[port].len;\n-\tqconf->tx_mbufs[port].m_table[len] = m;\n-\tlen++;\n-\n-\t/* enough pkts to be sent */\n-\tif (unlikely(len == MAX_PKT_BURST)) {\n-\t\tsend_burst(qconf, MAX_PKT_BURST, port);\n-\t\tlen = 0;\n-\t}\n-\n-\tqconf->tx_mbufs[port].len = len;\n-\treturn 0;\n+\trte_eth_tx_buffer(port, q, m);\n }\n \n #ifdef DO_RFC_1812_CHECKS\n@@ -910,14 +866,9 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\t\t * This could be optimized (use queueid instead of\n \t\t\t * portid), but it is not called so often\n \t\t\t */\n-\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tsend_burst(&lcore_conf[lcore_id],\n-\t\t\t\t\tqconf->tx_mbufs[portid].len,\n-\t\t\t\t\tportid);\n-\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n-\t\t\t}\n+\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)\n+\t\t\t\trte_eth_tx_buffer_flush(portid,\n+\t\t\t\t\t\tqconf->tx_queue_id[portid]);\n \n \t\t\tprev_tsc = cur_tsc;\n \t\t}\ndiff --git a/examples/link_status_interrupt/main.c b/examples/link_status_interrupt/main.c\nindex c57a08a..ec51cbe 100644\n--- a/examples/link_status_interrupt/main.c\n+++ b/examples/link_status_interrupt/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -96,19 +96,12 @@ static unsigned int lsi_rx_queue_per_lcore = 1;\n /* destination port for L2 forwarding */\n static unsigned lsi_dst_ports[RTE_MAX_ETHPORTS] = {0};\n \n-#define MAX_PKT_BURST 32\n-struct mbuf_table {\n-\tunsigned len;\n-\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n-};\n-\n #define MAX_RX_QUEUE_PER_LCORE 16\n #define MAX_TX_QUEUE_PER_PORT 16\n struct lcore_queue_conf {\n \tunsigned n_rx_port;\n \tunsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];\n \tunsigned tx_queue_id;\n-\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n \n } __rte_cache_aligned;\n struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];\n@@ -136,7 +129,7 @@ struct rte_mempool * lsi_pktmbuf_pool = NULL;\n struct lsi_port_statistics {\n \tuint64_t tx;\n \tuint64_t rx;\n-\tuint64_t dropped;\n+\tunsigned long dropped;\n } __rte_cache_aligned;\n struct lsi_port_statistics port_statistics[RTE_MAX_ETHPORTS];\n \n@@ -202,58 +195,12 @@ print_stats(void)\n \tprintf(\"\\n====================================================\\n\");\n }\n \n-/* Send the packet on an output interface */\n-static int\n-lsi_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)\n-{\n-\tstruct rte_mbuf **m_table;\n-\tunsigned ret;\n-\tunsigned queueid;\n-\n-\tqueueid = (uint16_t) qconf->tx_queue_id;\n-\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n-\n-\tret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);\n-\tport_statistics[port].tx += ret;\n-\tif (unlikely(ret < n)) {\n-\t\tport_statistics[port].dropped += (n - ret);\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Send the packet on an output interface */\n-static int\n-lsi_send_packet(struct rte_mbuf *m, uint8_t port)\n-{\n-\tunsigned lcore_id, len;\n-\tstruct lcore_queue_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n-\n-\tqconf = &lcore_queue_conf[lcore_id];\n-\tlen = qconf->tx_mbufs[port].len;\n-\tqconf->tx_mbufs[port].m_table[len] = m;\n-\tlen++;\n-\n-\t/* enough pkts to be sent */\n-\tif (unlikely(len == MAX_PKT_BURST)) {\n-\t\tlsi_send_burst(qconf, MAX_PKT_BURST, port);\n-\t\tlen = 0;\n-\t}\n-\n-\tqconf->tx_mbufs[port].len = len;\n-\treturn 0;\n-}\n-\n static void\n lsi_simple_forward(struct rte_mbuf *m, unsigned portid)\n {\n \tstruct ether_hdr *eth;\n \tvoid *tmp;\n+\tunsigned sent;\n \tunsigned dst_port = lsi_dst_ports[portid];\n \n \teth = rte_pktmbuf_mtod(m, struct ether_hdr *);\n@@ -265,7 +212,9 @@ lsi_simple_forward(struct rte_mbuf *m, unsigned portid)\n \t/* src addr */\n \tether_addr_copy(&lsi_ports_eth_addr[dst_port], &eth->s_addr);\n \n-\tlsi_send_packet(m, (uint8_t) dst_port);\n+\tsent = rte_eth_tx_buffer(dst_port, 0, m);\n+\tif (sent)\n+\t\tport_statistics[dst_port].tx += sent;\n }\n \n /* main processing loop */\n@@ -275,6 +224,7 @@ lsi_main_loop(void)\n \tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n \tstruct rte_mbuf *m;\n \tunsigned lcore_id;\n+\tunsigned sent;\n \tuint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;\n \tunsigned i, j, portid, nb_rx;\n \tstruct lcore_queue_conf *qconf;\n@@ -310,15 +260,12 @@ lsi_main_loop(void)\n \t\tdiff_tsc = cur_tsc - prev_tsc;\n \t\tif (unlikely(diff_tsc > drain_tsc)) {\n \n-\t\t\t/* this could be optimized (use queueid instead of\n-\t\t\t * portid), but it is not called so often */\n-\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tlsi_send_burst(&lcore_queue_conf[lcore_id],\n-\t\t\t\t\t\t qconf->tx_mbufs[portid].len,\n-\t\t\t\t\t\t (uint8_t) portid);\n-\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n+\t\t\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\t\t\t\tportid = qconf->rx_port_list[i];\n+\t\t\t\tportid = lsi_dst_ports[portid];\n+\t\t\t\tsent = rte_eth_tx_buffer_flush(portid, 0);\n+\t\t\t\tif (sent)\n+\t\t\t\t\tport_statistics[portid].tx += sent;\n \t\t\t}\n \n \t\t\t/* if timer is enabled */\n@@ -700,6 +647,10 @@ main(int argc, char **argv)\n \t\trte_eth_dev_callback_register(portid,\n \t\t\tRTE_ETH_EVENT_INTR_LSC, lsi_event_callback, NULL);\n \n+\t\trte_eth_tx_buffer_set_err_callback(portid, 0,\n+\t\t\t\trte_eth_count_unsent_packet_callback,\n+\t\t\t\t&port_statistics[portid].dropped);\n+\n \t\trte_eth_macaddr_get(portid,\n \t\t\t\t    &lsi_ports_eth_addr[portid]);\n \ndiff --git a/examples/multi_process/client_server_mp/mp_client/client.c b/examples/multi_process/client_server_mp/mp_client/client.c\nindex bf049a4..2321550 100644\n--- a/examples/multi_process/client_server_mp/mp_client/client.c\n+++ b/examples/multi_process/client_server_mp/mp_client/client.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -72,22 +72,12 @@\n  * queue to write to. */\n static uint8_t client_id = 0;\n \n-struct mbuf_queue {\n-#define MBQ_CAPACITY 32\n-\tstruct rte_mbuf *bufs[MBQ_CAPACITY];\n-\tuint16_t top;\n-};\n-\n /* maps input ports to output ports for packets */\n static uint8_t output_ports[RTE_MAX_ETHPORTS];\n \n-/* buffers up a set of packet that are ready to send */\n-static struct mbuf_queue output_bufs[RTE_MAX_ETHPORTS];\n-\n /* shared data from server. We update statistics here */\n static volatile struct tx_stats *tx_stats;\n \n-\n /*\n  * print a usage message\n  */\n@@ -149,6 +139,23 @@ parse_app_args(int argc, char *argv[])\n }\n \n /*\n+ * Tx buffer error callback\n+ */\n+static void\n+flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,\n+\t\tvoid *userdata) {\n+\tint i;\n+\tuint8_t port = (uintptr_t)userdata;\n+\n+\ttx_stats->tx_drop[port] += count;\n+\n+\t/* free the mbufs which failed from transmit */\n+\tfor (i = 0; i < count; i++)\n+\t\trte_pktmbuf_free(unsent[i]);\n+\n+}\n+\n+/*\n  * set up output ports so that all traffic on port gets sent out\n  * its paired port. Index using actual port numbers since that is\n  * what comes in the mbuf structure.\n@@ -164,41 +171,14 @@ static void configure_output_ports(const struct port_info *ports)\n \t\tuint8_t p2 = ports->id[i+1];\n \t\toutput_ports[p1] = p2;\n \t\toutput_ports[p2] = p1;\n-\t}\n-}\n-\n \n-static inline void\n-send_packets(uint8_t port)\n-{\n-\tuint16_t i, sent;\n-\tstruct mbuf_queue *mbq = &output_bufs[port];\n+\t\trte_eth_tx_buffer_set_err_callback(p1, client_id,\n+\t\t\t\tflush_tx_error_callback, (void *)(intptr_t)p1);\n \n-\tif (unlikely(mbq->top == 0))\n-\t\treturn;\n+\t\trte_eth_tx_buffer_set_err_callback(p2, client_id,\n+\t\t\t\tflush_tx_error_callback, (void *)(intptr_t)p2);\n \n-\tsent = rte_eth_tx_burst(port, client_id, mbq->bufs, mbq->top);\n-\tif (unlikely(sent < mbq->top)){\n-\t\tfor (i = sent; i < mbq->top; i++)\n-\t\t\trte_pktmbuf_free(mbq->bufs[i]);\n-\t\ttx_stats->tx_drop[port] += (mbq->top - sent);\n \t}\n-\ttx_stats->tx[port] += sent;\n-\tmbq->top = 0;\n-}\n-\n-/*\n- * Enqueue a packet to be sent on a particular port, but\n- * don't send it yet. Only when the buffer is full.\n- */\n-static inline void\n-enqueue_packet(struct rte_mbuf *buf, uint8_t port)\n-{\n-\tstruct mbuf_queue *mbq = &output_bufs[port];\n-\tmbq->bufs[mbq->top++] = buf;\n-\n-\tif (mbq->top == MBQ_CAPACITY)\n-\t\tsend_packets(port);\n }\n \n /*\n@@ -209,10 +189,13 @@ enqueue_packet(struct rte_mbuf *buf, uint8_t port)\n static void\n handle_packet(struct rte_mbuf *buf)\n {\n+\tunsigned sent;\n \tconst uint8_t in_port = buf->port;\n \tconst uint8_t out_port = output_ports[in_port];\n \n-\tenqueue_packet(buf, out_port);\n+\tsent = rte_eth_tx_buffer(out_port, client_id, buf);\n+\tif (unlikely(sent))\n+\t\ttx_stats->tx[out_port] += sent;\n }\n \n /*\n@@ -229,6 +212,7 @@ main(int argc, char *argv[])\n \tint need_flush = 0; /* indicates whether we have unsent packets */\n \tint retval;\n \tvoid *pkts[PKT_READ_SIZE];\n+\tuint16_t sent;\n \n \tif ((retval = rte_eal_init(argc, argv)) < 0)\n \t\treturn -1;\n@@ -274,8 +258,11 @@ main(int argc, char *argv[])\n \n \t\tif (unlikely(rx_pkts == 0)){\n \t\t\tif (need_flush)\n-\t\t\t\tfor (port = 0; port < ports->num_ports; port++)\n-\t\t\t\t\tsend_packets(ports->id[port]);\n+\t\t\t\tfor (port = 0; port < ports->num_ports; port++) {\n+\t\t\t\t\tsent = rte_eth_tx_buffer_flush(ports->id[port], client_id);\n+\t\t\t\t\tif (unlikely(sent))\n+\t\t\t\t\t\ttx_stats->tx[port] += sent;\n+\t\t\t\t}\n \t\t\tneed_flush = 0;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/examples/multi_process/l2fwd_fork/main.c b/examples/multi_process/l2fwd_fork/main.c\nindex f2d7eab..f919e07 100644\n--- a/examples/multi_process/l2fwd_fork/main.c\n+++ b/examples/multi_process/l2fwd_fork/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -117,18 +117,11 @@ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];\n \n static unsigned int l2fwd_rx_queue_per_lcore = 1;\n \n-struct mbuf_table {\n-\tunsigned len;\n-\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n-};\n-\n #define MAX_RX_QUEUE_PER_LCORE 16\n #define MAX_TX_QUEUE_PER_PORT 16\n struct lcore_queue_conf {\n \tunsigned n_rx_port;\n \tunsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];\n-\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n-\n } __rte_cache_aligned;\n struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];\n \n@@ -176,7 +169,7 @@ static struct rte_mempool * l2fwd_pktmbuf_pool[RTE_MAX_ETHPORTS];\n struct l2fwd_port_statistics {\n \tuint64_t tx;\n \tuint64_t rx;\n-\tuint64_t dropped;\n+\tunsigned long dropped;\n } __rte_cache_aligned;\n struct l2fwd_port_statistics *port_statistics;\n /**\n@@ -583,57 +576,12 @@ slave_exit_cb(unsigned slaveid, __attribute__((unused))int stat)\n \trte_spinlock_unlock(&res_lock);\n }\n \n-/* Send the packet on an output interface */\n-static int\n-l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)\n-{\n-\tstruct rte_mbuf **m_table;\n-\tunsigned ret;\n-\tunsigned queueid =0;\n-\n-\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n-\n-\tret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);\n-\tport_statistics[port].tx += ret;\n-\tif (unlikely(ret < n)) {\n-\t\tport_statistics[port].dropped += (n - ret);\n-\t\tdo {\n-\t\t\trte_pktmbuf_free(m_table[ret]);\n-\t\t} while (++ret < n);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Send the packet on an output interface */\n-static int\n-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)\n-{\n-\tunsigned lcore_id, len;\n-\tstruct lcore_queue_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n-\n-\tqconf = &lcore_queue_conf[lcore_id];\n-\tlen = qconf->tx_mbufs[port].len;\n-\tqconf->tx_mbufs[port].m_table[len] = m;\n-\tlen++;\n-\n-\t/* enough pkts to be sent */\n-\tif (unlikely(len == MAX_PKT_BURST)) {\n-\t\tl2fwd_send_burst(qconf, MAX_PKT_BURST, port);\n-\t\tlen = 0;\n-\t}\n-\n-\tqconf->tx_mbufs[port].len = len;\n-\treturn 0;\n-}\n-\n static void\n l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n {\n \tstruct ether_hdr *eth;\n \tvoid *tmp;\n+\tunsigned sent;\n \tunsigned dst_port;\n \n \tdst_port = l2fwd_dst_ports[portid];\n@@ -646,7 +594,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n \t/* src addr */\n \tether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);\n \n-\tl2fwd_send_packet(m, (uint8_t) dst_port);\n+\tsent = rte_eth_tx_buffer(dst_port, 0, m);\n+\tif (sent)\n+\t\tport_statistics[dst_port].tx += sent;\n }\n \n /* main processing loop */\n@@ -656,6 +606,7 @@ l2fwd_main_loop(void)\n \tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n \tstruct rte_mbuf *m;\n \tunsigned lcore_id;\n+\tunsigned sent;\n \tuint64_t prev_tsc, diff_tsc, cur_tsc;\n \tunsigned i, j, portid, nb_rx;\n \tstruct lcore_queue_conf *qconf;\n@@ -698,14 +649,12 @@ l2fwd_main_loop(void)\n \t\t */\n \t\tdiff_tsc = cur_tsc - prev_tsc;\n \t\tif (unlikely(diff_tsc > drain_tsc)) {\n-\n-\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n-\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tl2fwd_send_burst(&lcore_queue_conf[lcore_id],\n-\t\t\t\t\t\t qconf->tx_mbufs[portid].len,\n-\t\t\t\t\t\t (uint8_t) portid);\n-\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n+\t\t\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\t\t\t\tportid = qconf->rx_port_list[i];\n+\t\t\t\tportid = l2fwd_dst_ports[portid];\n+\t\t\t\tsent = rte_eth_tx_buffer_flush(portid, 0);\n+\t\t\t\tif (sent)\n+\t\t\t\t\tport_statistics[portid].tx += sent;\n \t\t\t}\n \t\t}\n \n@@ -1144,6 +1093,10 @@ main(int argc, char **argv)\n \t\t\trte_exit(EXIT_FAILURE, \"rte_eth_tx_queue_setup:err=%d, port=%u\\n\",\n \t\t\t\tret, (unsigned) portid);\n \n+\t\trte_eth_tx_buffer_set_err_callback(portid, 0,\n+\t\t\t\trte_eth_count_unsent_packet_callback,\n+\t\t\t\t&port_statistics[portid].dropped);\n+\n \t\t/* Start device */\n \t\tret = rte_eth_dev_start(portid);\n \t\tif (ret < 0)\ndiff --git a/examples/packet_ordering/main.c b/examples/packet_ordering/main.c\nindex 1d9a86f..a11d68e 100644\n--- a/examples/packet_ordering/main.c\n+++ b/examples/packet_ordering/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -86,11 +86,6 @@ struct send_thread_args {\n \tstruct rte_reorder_buffer *buffer;\n };\n \n-struct output_buffer {\n-\tunsigned count;\n-\tstruct rte_mbuf *mbufs[MAX_PKTS_BURST];\n-};\n-\n volatile struct app_stats {\n \tstruct {\n \t\tuint64_t rx_pkts;\n@@ -235,6 +230,20 @@ parse_args(int argc, char **argv)\n \treturn 0;\n }\n \n+/*\n+ * Tx buffer error callback\n+ */\n+static void\n+flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,\n+\t\tvoid *userdata __rte_unused) {\n+\n+\t/* free the mbufs which failed from transmit */\n+\tapp_stats.tx.ro_tx_failed_pkts += count;\n+\tLOG_DEBUG(REORDERAPP, \"%s:Packet loss with tx_burst\\n\", __func__);\n+\tpktmbuf_free_bulk(unsent, count);\n+\n+}\n+\n static inline int\n configure_eth_port(uint8_t port_id)\n {\n@@ -266,6 +275,9 @@ configure_eth_port(uint8_t port_id)\n \t\t\treturn ret;\n \t}\n \n+\trte_eth_tx_buffer_set_err_callback(port_id, 0, flush_tx_error_callback,\n+\t\t\tNULL);\n+\n \tret = rte_eth_dev_start(port_id);\n \tif (ret < 0)\n \t\treturn ret;\n@@ -438,22 +450,6 @@ worker_thread(void *args_ptr)\n \treturn 0;\n }\n \n-static inline void\n-flush_one_port(struct output_buffer *outbuf, uint8_t outp)\n-{\n-\tunsigned nb_tx = rte_eth_tx_burst(outp, 0, outbuf->mbufs,\n-\t\t\toutbuf->count);\n-\tapp_stats.tx.ro_tx_pkts += nb_tx;\n-\n-\tif (unlikely(nb_tx < outbuf->count)) {\n-\t\t/* free the mbufs which failed from transmit */\n-\t\tapp_stats.tx.ro_tx_failed_pkts += (outbuf->count - nb_tx);\n-\t\tLOG_DEBUG(REORDERAPP, \"%s:Packet loss with tx_burst\\n\", __func__);\n-\t\tpktmbuf_free_bulk(&outbuf->mbufs[nb_tx], outbuf->count - nb_tx);\n-\t}\n-\toutbuf->count = 0;\n-}\n-\n /**\n  * Dequeue mbufs from the workers_to_tx ring and reorder them before\n  * transmitting.\n@@ -464,8 +460,8 @@ send_thread(struct send_thread_args *args)\n \tint ret;\n \tunsigned int i, dret;\n \tuint16_t nb_dq_mbufs;\n+\tuint16_t sent;\n \tuint8_t outp;\n-\tstatic struct output_buffer tx_buffers[RTE_MAX_ETHPORTS];\n \tstruct rte_mbuf *mbufs[MAX_PKTS_BURST];\n \tstruct rte_mbuf *rombufs[MAX_PKTS_BURST] = {NULL};\n \n@@ -515,7 +511,6 @@ send_thread(struct send_thread_args *args)\n \t\tdret = rte_reorder_drain(args->buffer, rombufs, MAX_PKTS_BURST);\n \t\tfor (i = 0; i < dret; i++) {\n \n-\t\t\tstruct output_buffer *outbuf;\n \t\t\tuint8_t outp1;\n \n \t\t\toutp1 = rombufs[i]->port;\n@@ -525,10 +520,10 @@ send_thread(struct send_thread_args *args)\n \t\t\t\tcontinue;\n \t\t\t}\n \n-\t\t\toutbuf = &tx_buffers[outp1];\n-\t\t\toutbuf->mbufs[outbuf->count++] = rombufs[i];\n-\t\t\tif (outbuf->count == MAX_PKTS_BURST)\n-\t\t\t\tflush_one_port(outbuf, outp1);\n+\t\t\tsent = rte_eth_tx_buffer(outp1, 0, rombufs[i]);\n+\t\t\tif (sent)\n+\t\t\t\tapp_stats.tx.ro_tx_pkts += sent;\n+\n \t\t}\n \t}\n \treturn 0;\n@@ -541,10 +536,9 @@ static int\n tx_thread(struct rte_ring *ring_in)\n {\n \tuint32_t i, dqnum;\n+\tuint16_t sent;\n \tuint8_t outp;\n-\tstatic struct output_buffer tx_buffers[RTE_MAX_ETHPORTS];\n \tstruct rte_mbuf *mbufs[MAX_PKTS_BURST];\n-\tstruct output_buffer *outbuf;\n \n \tRTE_LOG(INFO, REORDERAPP, \"%s() started on lcore %u\\n\", __func__,\n \t\t\t\t\t\t\trte_lcore_id());\n@@ -567,10 +561,10 @@ tx_thread(struct rte_ring *ring_in)\n \t\t\t\tcontinue;\n \t\t\t}\n \n-\t\t\toutbuf = &tx_buffers[outp];\n-\t\t\toutbuf->mbufs[outbuf->count++] = mbufs[i];\n-\t\t\tif (outbuf->count == MAX_PKTS_BURST)\n-\t\t\t\tflush_one_port(outbuf, outp);\n+\t\t\tsent = rte_eth_tx_buffer(outp, 0, mbufs[i]);\n+\t\t\tif (sent)\n+\t\t\t\tapp_stats.tx.ro_tx_pkts += sent;\n+\n \t\t}\n \t}\n \ndiff --git a/examples/qos_meter/main.c b/examples/qos_meter/main.c\nindex 0de5e7f..7d901d2 100644\n--- a/examples/qos_meter/main.c\n+++ b/examples/qos_meter/main.c\n@@ -1,7 +1,7 @@\n /*-\n  *   BSD LICENSE\n  *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n  *   All rights reserved.\n  *\n  *   Redistribution and use in source and binary forms, with or without\n@@ -118,8 +118,6 @@ static struct rte_eth_conf port_conf = {\n static uint8_t port_rx;\n static uint8_t port_tx;\n static struct rte_mbuf *pkts_rx[PKT_RX_BURST_MAX];\n-static struct rte_mbuf *pkts_tx[PKT_TX_BURST_MAX];\n-static uint16_t pkts_tx_len = 0;\n \n \n struct rte_meter_srtcm_params app_srtcm_params[] = {\n@@ -188,26 +186,9 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\tcurrent_time = rte_rdtsc();\n \t\ttime_diff = current_time - last_time;\n \t\tif (unlikely(time_diff > TIME_TX_DRAIN)) {\n-\t\t\tint ret;\n \n-\t\t\tif (pkts_tx_len == 0) {\n-\t\t\t\tlast_time = current_time;\n-\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\t/* Write packet burst to NIC TX */\n-\t\t\tret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, pkts_tx_len);\n-\n-\t\t\t/* Free buffers for any packets not written successfully */\n-\t\t\tif (unlikely(ret < pkts_tx_len)) {\n-\t\t\t\tfor ( ; ret < pkts_tx_len; ret ++) {\n-\t\t\t\t\trte_pktmbuf_free(pkts_tx[ret]);\n-\t\t\t\t}\n-\t\t\t}\n-\n-\t\t\t/* Empty the output buffer */\n-\t\t\tpkts_tx_len = 0;\n+\t\t\t/* Flush tx buffer */\n+\t\t\trte_eth_tx_buffer_flush(port_tx, NIC_TX_QUEUE);\n \n \t\t\tlast_time = current_time;\n \t\t}\n@@ -222,26 +203,9 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\t\t/* Handle current packet */\n \t\t\tif (app_pkt_handle(pkt, current_time) == DROP)\n \t\t\t\trte_pktmbuf_free(pkt);\n-\t\t\telse {\n-\t\t\t\tpkts_tx[pkts_tx_len] = pkt;\n-\t\t\t\tpkts_tx_len ++;\n-\t\t\t}\n-\n-\t\t\t/* Write packets from output buffer to NIC TX when full burst is available */\n-\t\t\tif (unlikely(pkts_tx_len == PKT_TX_BURST_MAX)) {\n-\t\t\t\t/* Write packet burst to NIC TX */\n-\t\t\t\tint ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, PKT_TX_BURST_MAX);\n+\t\t\telse\n+\t\t\t\trte_eth_tx_buffer(port_tx, NIC_TX_QUEUE, pkt);\n \n-\t\t\t\t/* Free buffers for any packets not written successfully */\n-\t\t\t\tif (unlikely(ret < PKT_TX_BURST_MAX)) {\n-\t\t\t\t\tfor ( ; ret < PKT_TX_BURST_MAX; ret ++) {\n-\t\t\t\t\t\trte_pktmbuf_free(pkts_tx[ret]);\n-\t\t\t\t\t}\n-\t\t\t\t}\n-\n-\t\t\t\t/* Empty the output buffer */\n-\t\t\t\tpkts_tx_len = 0;\n-\t\t\t}\n \t\t}\n \t}\n }\n",
    "prefixes": [
        "dpdk-dev",
        "2/2"
    ]
}