dev.dpdk.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] add support for buffered tx to ethdev
@ 2016-01-15 14:43 Tomasz Kulasek
  2016-01-15 14:43 ` [PATCH 1/2] ethdev: add buffered tx api Tomasz Kulasek
                   ` (3 more replies)
  0 siblings, 4 replies; 44+ messages in thread
From: Tomasz Kulasek @ 2016-01-15 14:43 UTC (permalink / raw)
  To: dev

Many sample apps include internal buffering for single-packet-at-a-time
operation. Since this is such a common paradigm, this functionality is
better suited to being inside the core ethdev API.
The new APIs in the ethdev library are:
* rte_eth_tx_buffer - buffer up a single packet for future transmission
* rte_eth_tx_buffer_flush - flush any unsent buffered packets
* rte_eth_tx_buffer_set_err_callback - set up a callback to be called in
  case transmitting a buffered burst fails. By default, we just free the
  unsent packets.

As well as these, an additional reference callback is provided, which
frees the packets (as the default callback does), as well as updating a
user-provided counter, so that the number of dropped packets can be
tracked.

The internal buffering of packets for TX in sample apps is no longer
needed, so this patchset also replaces this code with calls to the new
rte_eth_tx_buffer* APIs in:

* l2fwd-jobstats
* l2fwd-keepalive
* l2fwd
* l3fwd-acl
* l3fwd-power
* link_status_interrupt
* client_server_mp
* l2fwd_fork
* packet_ordering
* qos_meter

Tomasz Kulasek (2):
  ethdev: add buffered tx api
  examples: sample apps rework to use buffered tx api

 config/common_bsdapp                               |    1 +
 config/common_linuxapp                             |    1 +
 examples/l2fwd-jobstats/main.c                     |   73 ++-----
 examples/l2fwd-keepalive/main.c                    |   79 ++------
 examples/l2fwd/main.c                              |   80 ++------
 examples/l3fwd-acl/main.c                          |   64 +-----
 examples/l3fwd-power/main.c                        |   63 +-----
 examples/link_status_interrupt/main.c              |   83 ++------
 .../client_server_mp/mp_client/client.c            |   77 +++----
 examples/multi_process/l2fwd_fork/main.c           |   81 ++------
 examples/packet_ordering/main.c                    |   62 +++---
 examples/qos_meter/main.c                          |   46 +----
 lib/librte_ether/rte_ethdev.c                      |   63 +++++-
 lib/librte_ether/rte_ethdev.h                      |  211 +++++++++++++++++++-
 lib/librte_ether/rte_ether_version.map             |    8 +
 15 files changed, 445 insertions(+), 547 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 44+ messages in thread
* [PATCH 2/2] examples: sample apps rework to use buffered tx api
@ 2016-01-15 14:26 Tomasz Kulasek
  0 siblings, 0 replies; 44+ messages in thread
From: Tomasz Kulasek @ 2016-01-15 14:26 UTC (permalink / raw)
  To: dev

Date: Fri, 15 Jan 2016 15:25:32 +0100
Message-Id: <1452867932-5548-3-git-send-email-tomaszx.kulasek@intel.com>
X-Mailer: git-send-email 2.1.4
In-Reply-To: <1452867932-5548-1-git-send-email-tomaszx.kulasek@intel.com>
References: <1452867932-5548-1-git-send-email-tomaszx.kulasek@intel.com>

The internal buffering of packets for TX in sample apps is no longer

needed, so this patchset replaces this code with calls to the new

rte_eth_tx_buffer* APIs in:



* l2fwd-jobstats

* l2fwd-keepalive

* l2fwd

* l3fwd-acl

* l3fwd-power

* link_status_interrupt

* client_server_mp

* l2fwd_fork

* packet_ordering

* qos_meter



Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>

---

 examples/l2fwd-jobstats/main.c                     |   73 +++++------------

 examples/l2fwd-keepalive/main.c                    |   79 ++++---------------

 examples/l2fwd/main.c                              |   80 ++++---------------

 examples/l3fwd-acl/main.c                          |   64 ++-------------

 examples/l3fwd-power/main.c                        |   63 ++-------------

 examples/link_status_interrupt/main.c              |   83 ++++----------------

 .../client_server_mp/mp_client/client.c            |   77 ++++++++----------

 examples/multi_process/l2fwd_fork/main.c           |   81 ++++---------------

 examples/packet_ordering/main.c                    |   62 +++++++--------

 examples/qos_meter/main.c                          |   46 ++---------

 10 files changed, 166 insertions(+), 542 deletions(-)



diff --git a/examples/l2fwd-jobstats/main.c b/examples/l2fwd-jobstats/main.c

index 7b59f4e..9a6e6ea 100644

--- a/examples/l2fwd-jobstats/main.c

+++ b/examples/l2fwd-jobstats/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -99,8 +99,6 @@ static unsigned int l2fwd_rx_queue_per_lcore = 1;

 

 struct mbuf_table {

 	uint64_t next_flush_time;

-	unsigned len;

-	struct rte_mbuf *mbufs[MAX_PKT_BURST];

 };

 

 #define MAX_RX_QUEUE_PER_LCORE 16

@@ -373,58 +371,12 @@ show_stats_cb(__rte_unused void *param)

 	rte_eal_alarm_set(timer_period * US_PER_S, show_stats_cb, NULL);

 }

 

-/* Send the burst of packets on an output interface */

-static void

-l2fwd_send_burst(struct lcore_queue_conf *qconf, uint8_t port)

-{

-	struct mbuf_table *m_table;

-	uint16_t ret;

-	uint16_t queueid = 0;

-	uint16_t n;

-

-	m_table = &qconf->tx_mbufs[port];

-	n = m_table->len;

-

-	m_table->next_flush_time = rte_get_timer_cycles() + drain_tsc;

-	m_table->len = 0;

-

-	ret = rte_eth_tx_burst(port, queueid, m_table->mbufs, n);

-

-	port_statistics[port].tx += ret;

-	if (unlikely(ret < n)) {

-		port_statistics[port].dropped += (n - ret);

-		do {

-			rte_pktmbuf_free(m_table->mbufs[ret]);

-		} while (++ret < n);

-	}

-}

-

-/* Enqueue packets for TX and prepare them to be sent */

-static int

-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)

-{

-	const unsigned lcore_id = rte_lcore_id();

-	struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id];

-	struct mbuf_table *m_table = &qconf->tx_mbufs[port];

-	uint16_t len = qconf->tx_mbufs[port].len;

-

-	m_table->mbufs[len] = m;

-

-	len++;

-	m_table->len = len;

-

-	/* Enough pkts to be sent. */

-	if (unlikely(len == MAX_PKT_BURST))

-		l2fwd_send_burst(qconf, port);

-

-	return 0;

-}

-

 static void

 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 {

 	struct ether_hdr *eth;

 	void *tmp;

+	int sent;

 	unsigned dst_port;

 

 	dst_port = l2fwd_dst_ports[portid];

@@ -437,7 +389,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 	/* src addr */

 	ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);

 

-	l2fwd_send_packet(m, (uint8_t) dst_port);

+	sent = rte_eth_tx_buffer(dst_port, 0, m);

+	if (sent)

+		port_statistics[dst_port].tx += sent;

 }

 

 static void

@@ -513,6 +467,8 @@ l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg)

 	struct lcore_queue_conf *qconf;

 	struct mbuf_table *m_table;

 	uint8_t portid;

+	unsigned i;

+	uint32_t sent;

 

 	lcore_id = rte_lcore_id();

 	qconf = &lcore_queue_conf[lcore_id];

@@ -522,12 +478,19 @@ l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg)

 	now = rte_get_timer_cycles();

 	lcore_id = rte_lcore_id();

 	qconf = &lcore_queue_conf[lcore_id];

-	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-		m_table = &qconf->tx_mbufs[portid];

-		if (m_table->len == 0 || m_table->next_flush_time <= now)

+

+	for (i = 0; i < qconf->n_rx_port; i++) {

+		m_table = &qconf->tx_mbufs[i];

+

+		if (m_table->next_flush_time <= now)

 			continue;

+		m_table->next_flush_time = rte_get_timer_cycles() + drain_tsc;

 

-		l2fwd_send_burst(qconf, portid);

+		portid = qconf->rx_port_list[i];

+		portid = l2fwd_dst_ports[portid];

+		sent = rte_eth_tx_buffer_flush(portid, 0);

+		if (sent)

+			port_statistics[portid].tx += sent;

 	}

 

 

diff --git a/examples/l2fwd-keepalive/main.c b/examples/l2fwd-keepalive/main.c

index f4d52f2..b59ff6d 100644

--- a/examples/l2fwd-keepalive/main.c

+++ b/examples/l2fwd-keepalive/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -97,17 +97,11 @@ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];

 

 static unsigned int l2fwd_rx_queue_per_lcore = 1;

 

-struct mbuf_table {

-	unsigned len;

-	struct rte_mbuf *m_table[MAX_PKT_BURST];

-};

-

 #define MAX_RX_QUEUE_PER_LCORE 16

 #define MAX_TX_QUEUE_PER_PORT 16

 struct lcore_queue_conf {

 	unsigned n_rx_port;

 	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];

-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];

 

 } __rte_cache_aligned;

 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];

@@ -132,7 +126,7 @@ struct rte_mempool *l2fwd_pktmbuf_pool = NULL;

 struct l2fwd_port_statistics {

 	uint64_t tx;

 	uint64_t rx;

-	uint64_t dropped;

+	unsigned long dropped;

 } __rte_cache_aligned;

 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];

 

@@ -192,57 +186,12 @@ print_stats(__attribute__((unused)) struct rte_timer *ptr_timer,

 	printf("\n====================================================\n");

 }

 

-/* Send the burst of packets on an output interface */

-static int

-l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)

-{

-	struct rte_mbuf **m_table;

-	unsigned ret;

-	unsigned queueid = 0;

-

-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;

-

-	ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);

-	port_statistics[port].tx += ret;

-	if (unlikely(ret < n)) {

-		port_statistics[port].dropped += (n - ret);

-		do {

-			rte_pktmbuf_free(m_table[ret]);

-		} while (++ret < n);

-	}

-

-	return 0;

-}

-

-/* Enqueue packets for TX and prepare them to be sent */

-static int

-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)

-{

-	unsigned lcore_id, len;

-	struct lcore_queue_conf *qconf;

-

-	lcore_id = rte_lcore_id();

-

-	qconf = &lcore_queue_conf[lcore_id];

-	len = qconf->tx_mbufs[port].len;

-	qconf->tx_mbufs[port].m_table[len] = m;

-	len++;

-

-	/* enough pkts to be sent */

-	if (unlikely(len == MAX_PKT_BURST)) {

-		l2fwd_send_burst(qconf, MAX_PKT_BURST, port);

-		len = 0;

-	}

-

-	qconf->tx_mbufs[port].len = len;

-	return 0;

-}

-

 static void

 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 {

 	struct ether_hdr *eth;

 	void *tmp;

+	int sent;

 	unsigned dst_port;

 

 	dst_port = l2fwd_dst_ports[portid];

@@ -255,7 +204,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 	/* src addr */

 	ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);

 

-	l2fwd_send_packet(m, (uint8_t) dst_port);

+	sent = rte_eth_tx_buffer(dst_port, 0, m);

+	if (sent)

+		port_statistics[dst_port].tx += sent;

 }

 

 /* main processing loop */

@@ -265,6 +216,7 @@ l2fwd_main_loop(void)

 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];

 	struct rte_mbuf *m;

 	unsigned lcore_id;

+	int sent;

 	uint64_t prev_tsc, diff_tsc, cur_tsc;

 	unsigned i, j, portid, nb_rx;

 	struct lcore_queue_conf *qconf;

@@ -312,13 +264,12 @@ l2fwd_main_loop(void)

 		diff_tsc = cur_tsc - prev_tsc;

 		if (unlikely(diff_tsc > drain_tsc)) {

 

-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-				if (qconf->tx_mbufs[portid].len == 0)

-					continue;

-				l2fwd_send_burst(&lcore_queue_conf[lcore_id],

-						 qconf->tx_mbufs[portid].len,

-						 (uint8_t) portid);

-				qconf->tx_mbufs[portid].len = 0;

+			for (i = 0; i < qconf->n_rx_port; i++) {

+				portid = qconf->rx_port_list[i];

+				portid = l2fwd_dst_ports[portid];

+				sent = rte_eth_tx_buffer_flush(portid, 0);

+				if (sent)

+					port_statistics[portid].tx += sent;

 			}

 

 			prev_tsc = cur_tsc;

@@ -713,6 +664,10 @@ main(int argc, char **argv)

 				"rte_eth_tx_queue_setup:err=%d, port=%u\n",

 				ret, (unsigned) portid);

 

+		rte_eth_tx_buffer_set_err_callback(portid, 0,

+				rte_eth_count_unsent_packet_callback,

+				&port_statistics[portid].dropped);

+

 		/* Start device */

 		ret = rte_eth_dev_start(portid);

 		if (ret < 0)

diff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c

index 720fd5a..e6dce27 100644

--- a/examples/l2fwd/main.c

+++ b/examples/l2fwd/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -95,17 +95,11 @@ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];

 

 static unsigned int l2fwd_rx_queue_per_lcore = 1;

 

-struct mbuf_table {

-	unsigned len;

-	struct rte_mbuf *m_table[MAX_PKT_BURST];

-};

-

 #define MAX_RX_QUEUE_PER_LCORE 16

 #define MAX_TX_QUEUE_PER_PORT 16

 struct lcore_queue_conf {

 	unsigned n_rx_port;

 	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];

-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];

 

 } __rte_cache_aligned;

 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];

@@ -130,7 +124,7 @@ struct rte_mempool * l2fwd_pktmbuf_pool = NULL;

 struct l2fwd_port_statistics {

 	uint64_t tx;

 	uint64_t rx;

-	uint64_t dropped;

+	unsigned long dropped;

 } __rte_cache_aligned;

 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];

 

@@ -185,57 +179,12 @@ print_stats(void)

 	printf("\n====================================================\n");

 }

 

-/* Send the burst of packets on an output interface */

-static int

-l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)

-{

-	struct rte_mbuf **m_table;

-	unsigned ret;

-	unsigned queueid =0;

-

-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;

-

-	ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);

-	port_statistics[port].tx += ret;

-	if (unlikely(ret < n)) {

-		port_statistics[port].dropped += (n - ret);

-		do {

-			rte_pktmbuf_free(m_table[ret]);

-		} while (++ret < n);

-	}

-

-	return 0;

-}

-

-/* Enqueue packets for TX and prepare them to be sent */

-static int

-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)

-{

-	unsigned lcore_id, len;

-	struct lcore_queue_conf *qconf;

-

-	lcore_id = rte_lcore_id();

-

-	qconf = &lcore_queue_conf[lcore_id];

-	len = qconf->tx_mbufs[port].len;

-	qconf->tx_mbufs[port].m_table[len] = m;

-	len++;

-

-	/* enough pkts to be sent */

-	if (unlikely(len == MAX_PKT_BURST)) {

-		l2fwd_send_burst(qconf, MAX_PKT_BURST, port);

-		len = 0;

-	}

-

-	qconf->tx_mbufs[port].len = len;

-	return 0;

-}

-

 static void

 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 {

 	struct ether_hdr *eth;

 	void *tmp;

+	int sent;

 	unsigned dst_port;

 

 	dst_port = l2fwd_dst_ports[portid];

@@ -248,7 +197,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 	/* src addr */

 	ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);

 

-	l2fwd_send_packet(m, (uint8_t) dst_port);

+	sent = rte_eth_tx_buffer(dst_port, 0, m);

+	if (sent)

+		port_statistics[dst_port].tx += sent;

 }

 

 /* main processing loop */

@@ -258,6 +209,7 @@ l2fwd_main_loop(void)

 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];

 	struct rte_mbuf *m;

 	unsigned lcore_id;

+	int sent;

 	uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;

 	unsigned i, j, portid, nb_rx;

 	struct lcore_queue_conf *qconf;

@@ -277,7 +229,6 @@ l2fwd_main_loop(void)

 	RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);

 

 	for (i = 0; i < qconf->n_rx_port; i++) {

-

 		portid = qconf->rx_port_list[i];

 		RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,

 			portid);

@@ -293,13 +244,12 @@ l2fwd_main_loop(void)

 		diff_tsc = cur_tsc - prev_tsc;

 		if (unlikely(diff_tsc > drain_tsc)) {

 

-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-				if (qconf->tx_mbufs[portid].len == 0)

-					continue;

-				l2fwd_send_burst(&lcore_queue_conf[lcore_id],

-						 qconf->tx_mbufs[portid].len,

-						 (uint8_t) portid);

-				qconf->tx_mbufs[portid].len = 0;

+			for (i = 0; i < qconf->n_rx_port; i++) {

+				portid = qconf->rx_port_list[i];

+				portid = l2fwd_dst_ports[portid];

+				sent = rte_eth_tx_buffer_flush(portid, 0);

+				if (sent)

+					port_statistics[portid].tx += sent;

 			}

 

 			/* if timer is enabled */

@@ -666,6 +616,10 @@ main(int argc, char **argv)

 			rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",

 				ret, (unsigned) portid);

 

+		rte_eth_tx_buffer_set_err_callback(portid, 0,

+				rte_eth_count_unsent_packet_callback,

+				&port_statistics[portid].dropped);

+

 		/* Start device */

 		ret = rte_eth_dev_start(portid);

 		if (ret < 0)

diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c

index f676d14..810cdac 100644

--- a/examples/l3fwd-acl/main.c

+++ b/examples/l3fwd-acl/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -119,11 +119,6 @@ static uint32_t enabled_port_mask;

 static int promiscuous_on; /**< Ports set in promiscuous mode off by default. */

 static int numa_on = 1; /**< NUMA is enabled by default. */

 

-struct mbuf_table {

-	uint16_t len;

-	struct rte_mbuf *m_table[MAX_PKT_BURST];

-};

-

 struct lcore_rx_queue {

 	uint8_t port_id;

 	uint8_t queue_id;

@@ -187,7 +182,7 @@ static struct rte_mempool *pktmbuf_pool[NB_SOCKETS];

 static inline int

 is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len);

 #endif

-static inline int

+static inline void

 send_single_packet(struct rte_mbuf *m, uint8_t port);

 

 #define MAX_ACL_RULE_NUM	100000

@@ -1292,55 +1287,17 @@ struct lcore_conf {

 	uint16_t n_rx_queue;

 	struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];

 	uint16_t tx_queue_id[RTE_MAX_ETHPORTS];

-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];

 } __rte_cache_aligned;

 

 static struct lcore_conf lcore_conf[RTE_MAX_LCORE];

 

-/* Send burst of packets on an output interface */

-static inline int

-send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port)

-{

-	struct rte_mbuf **m_table;

-	int ret;

-	uint16_t queueid;

-

-	queueid = qconf->tx_queue_id[port];

-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;

-

-	ret = rte_eth_tx_burst(port, queueid, m_table, n);

-	if (unlikely(ret < n)) {

-		do {

-			rte_pktmbuf_free(m_table[ret]);

-		} while (++ret < n);

-	}

-

-	return 0;

-}

-

 /* Enqueue a single packet, and send burst if queue is filled */

-static inline int

+static inline void

 send_single_packet(struct rte_mbuf *m, uint8_t port)

 {

-	uint32_t lcore_id;

-	uint16_t len;

-	struct lcore_conf *qconf;

-

-	lcore_id = rte_lcore_id();

-

-	qconf = &lcore_conf[lcore_id];

-	len = qconf->tx_mbufs[port].len;

-	qconf->tx_mbufs[port].m_table[len] = m;

-	len++;

-

-	/* enough pkts to be sent */

-	if (unlikely(len == MAX_PKT_BURST)) {

-		send_burst(qconf, MAX_PKT_BURST, port);

-		len = 0;

-	}

+	uint16_t q = lcore_conf[rte_lcore_id()].tx_queue_id[port];

 

-	qconf->tx_mbufs[port].len = len;

-	return 0;

+	rte_eth_tx_buffer(port, q, m);

 }

 

 #ifdef DO_RFC_1812_CHECKS

@@ -1433,14 +1390,9 @@ main_loop(__attribute__((unused)) void *dummy)

 			 * This could be optimized (use queueid instead of

 			 * portid), but it is not called so often

 			 */

-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-				if (qconf->tx_mbufs[portid].len == 0)

-					continue;

-				send_burst(&lcore_conf[lcore_id],

-					qconf->tx_mbufs[portid].len,

-					portid);

-				qconf->tx_mbufs[portid].len = 0;

-			}

+			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)

+				rte_eth_tx_buffer_flush(portid,

+						qconf->tx_queue_id[portid]);

 

 			prev_tsc = cur_tsc;

 		}

diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c

index 828c18a..6f32242 100644

--- a/examples/l3fwd-power/main.c

+++ b/examples/l3fwd-power/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -173,11 +173,6 @@ enum freq_scale_hint_t

 	FREQ_HIGHEST  =       2

 };

 

-struct mbuf_table {

-	uint16_t len;

-	struct rte_mbuf *m_table[MAX_PKT_BURST];

-};

-

 struct lcore_rx_queue {

 	uint8_t port_id;

 	uint8_t queue_id;

@@ -348,7 +343,6 @@ struct lcore_conf {

 	uint16_t n_rx_queue;

 	struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];

 	uint16_t tx_queue_id[RTE_MAX_ETHPORTS];

-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];

 	lookup_struct_t * ipv4_lookup_struct;

 	lookup_struct_t * ipv6_lookup_struct;

 } __rte_cache_aligned;

@@ -442,50 +436,12 @@ power_timer_cb(__attribute__((unused)) struct rte_timer *tim,

 	stats[lcore_id].sleep_time = 0;

 }

 

-/* Send burst of packets on an output interface */

-static inline int

-send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port)

-{

-	struct rte_mbuf **m_table;

-	int ret;

-	uint16_t queueid;

-

-	queueid = qconf->tx_queue_id[port];

-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;

-

-	ret = rte_eth_tx_burst(port, queueid, m_table, n);

-	if (unlikely(ret < n)) {

-		do {

-			rte_pktmbuf_free(m_table[ret]);

-		} while (++ret < n);

-	}

-

-	return 0;

-}

-

-/* Enqueue a single packet, and send burst if queue is filled */

-static inline int

+static inline void

 send_single_packet(struct rte_mbuf *m, uint8_t port)

 {

-	uint32_t lcore_id;

-	uint16_t len;

-	struct lcore_conf *qconf;

-

-	lcore_id = rte_lcore_id();

+	uint16_t q = lcore_conf[rte_lcore_id()].tx_queue_id[port];

 

-	qconf = &lcore_conf[lcore_id];

-	len = qconf->tx_mbufs[port].len;

-	qconf->tx_mbufs[port].m_table[len] = m;

-	len++;

-

-	/* enough pkts to be sent */

-	if (unlikely(len == MAX_PKT_BURST)) {

-		send_burst(qconf, MAX_PKT_BURST, port);

-		len = 0;

-	}

-

-	qconf->tx_mbufs[port].len = len;

-	return 0;

+	rte_eth_tx_buffer(port, q, m);

 }

 

 #ifdef DO_RFC_1812_CHECKS

@@ -910,14 +866,9 @@ main_loop(__attribute__((unused)) void *dummy)

 			 * This could be optimized (use queueid instead of

 			 * portid), but it is not called so often

 			 */

-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-				if (qconf->tx_mbufs[portid].len == 0)

-					continue;

-				send_burst(&lcore_conf[lcore_id],

-					qconf->tx_mbufs[portid].len,

-					portid);

-				qconf->tx_mbufs[portid].len = 0;

-			}

+			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)

+				rte_eth_tx_buffer_flush(portid,

+						qconf->tx_queue_id[portid]);

 

 			prev_tsc = cur_tsc;

 		}

diff --git a/examples/link_status_interrupt/main.c b/examples/link_status_interrupt/main.c

index c57a08a..ec51cbe 100644

--- a/examples/link_status_interrupt/main.c

+++ b/examples/link_status_interrupt/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -96,19 +96,12 @@ static unsigned int lsi_rx_queue_per_lcore = 1;

 /* destination port for L2 forwarding */

 static unsigned lsi_dst_ports[RTE_MAX_ETHPORTS] = {0};

 

-#define MAX_PKT_BURST 32

-struct mbuf_table {

-	unsigned len;

-	struct rte_mbuf *m_table[MAX_PKT_BURST];

-};

-

 #define MAX_RX_QUEUE_PER_LCORE 16

 #define MAX_TX_QUEUE_PER_PORT 16

 struct lcore_queue_conf {

 	unsigned n_rx_port;

 	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];

 	unsigned tx_queue_id;

-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];

 

 } __rte_cache_aligned;

 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];

@@ -136,7 +129,7 @@ struct rte_mempool * lsi_pktmbuf_pool = NULL;

 struct lsi_port_statistics {

 	uint64_t tx;

 	uint64_t rx;

-	uint64_t dropped;

+	unsigned long dropped;

 } __rte_cache_aligned;

 struct lsi_port_statistics port_statistics[RTE_MAX_ETHPORTS];

 

@@ -202,58 +195,12 @@ print_stats(void)

 	printf("\n====================================================\n");

 }

 

-/* Send the packet on an output interface */

-static int

-lsi_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)

-{

-	struct rte_mbuf **m_table;

-	unsigned ret;

-	unsigned queueid;

-

-	queueid = (uint16_t) qconf->tx_queue_id;

-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;

-

-	ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);

-	port_statistics[port].tx += ret;

-	if (unlikely(ret < n)) {

-		port_statistics[port].dropped += (n - ret);

-		do {

-			rte_pktmbuf_free(m_table[ret]);

-		} while (++ret < n);

-	}

-

-	return 0;

-}

-

-/* Send the packet on an output interface */

-static int

-lsi_send_packet(struct rte_mbuf *m, uint8_t port)

-{

-	unsigned lcore_id, len;

-	struct lcore_queue_conf *qconf;

-

-	lcore_id = rte_lcore_id();

-

-	qconf = &lcore_queue_conf[lcore_id];

-	len = qconf->tx_mbufs[port].len;

-	qconf->tx_mbufs[port].m_table[len] = m;

-	len++;

-

-	/* enough pkts to be sent */

-	if (unlikely(len == MAX_PKT_BURST)) {

-		lsi_send_burst(qconf, MAX_PKT_BURST, port);

-		len = 0;

-	}

-

-	qconf->tx_mbufs[port].len = len;

-	return 0;

-}

-

 static void

 lsi_simple_forward(struct rte_mbuf *m, unsigned portid)

 {

 	struct ether_hdr *eth;

 	void *tmp;

+	unsigned sent;

 	unsigned dst_port = lsi_dst_ports[portid];

 

 	eth = rte_pktmbuf_mtod(m, struct ether_hdr *);

@@ -265,7 +212,9 @@ lsi_simple_forward(struct rte_mbuf *m, unsigned portid)

 	/* src addr */

 	ether_addr_copy(&lsi_ports_eth_addr[dst_port], &eth->s_addr);

 

-	lsi_send_packet(m, (uint8_t) dst_port);

+	sent = rte_eth_tx_buffer(dst_port, 0, m);

+	if (sent)

+		port_statistics[dst_port].tx += sent;

 }

 

 /* main processing loop */

@@ -275,6 +224,7 @@ lsi_main_loop(void)

 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];

 	struct rte_mbuf *m;

 	unsigned lcore_id;

+	unsigned sent;

 	uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;

 	unsigned i, j, portid, nb_rx;

 	struct lcore_queue_conf *qconf;

@@ -310,15 +260,12 @@ lsi_main_loop(void)

 		diff_tsc = cur_tsc - prev_tsc;

 		if (unlikely(diff_tsc > drain_tsc)) {

 

-			/* this could be optimized (use queueid instead of

-			 * portid), but it is not called so often */

-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-				if (qconf->tx_mbufs[portid].len == 0)

-					continue;

-				lsi_send_burst(&lcore_queue_conf[lcore_id],

-						 qconf->tx_mbufs[portid].len,

-						 (uint8_t) portid);

-				qconf->tx_mbufs[portid].len = 0;

+			for (i = 0; i < qconf->n_rx_port; i++) {

+				portid = qconf->rx_port_list[i];

+				portid = lsi_dst_ports[portid];

+				sent = rte_eth_tx_buffer_flush(portid, 0);

+				if (sent)

+					port_statistics[portid].tx += sent;

 			}

 

 			/* if timer is enabled */

@@ -700,6 +647,10 @@ main(int argc, char **argv)

 		rte_eth_dev_callback_register(portid,

 			RTE_ETH_EVENT_INTR_LSC, lsi_event_callback, NULL);

 

+		rte_eth_tx_buffer_set_err_callback(portid, 0,

+				rte_eth_count_unsent_packet_callback,

+				&port_statistics[portid].dropped);

+

 		rte_eth_macaddr_get(portid,

 				    &lsi_ports_eth_addr[portid]);

 

diff --git a/examples/multi_process/client_server_mp/mp_client/client.c b/examples/multi_process/client_server_mp/mp_client/client.c

index bf049a4..2321550 100644

--- a/examples/multi_process/client_server_mp/mp_client/client.c

+++ b/examples/multi_process/client_server_mp/mp_client/client.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -72,22 +72,12 @@

  * queue to write to. */

 static uint8_t client_id = 0;

 

-struct mbuf_queue {

-#define MBQ_CAPACITY 32

-	struct rte_mbuf *bufs[MBQ_CAPACITY];

-	uint16_t top;

-};

-

 /* maps input ports to output ports for packets */

 static uint8_t output_ports[RTE_MAX_ETHPORTS];

 

-/* buffers up a set of packet that are ready to send */

-static struct mbuf_queue output_bufs[RTE_MAX_ETHPORTS];

-

 /* shared data from server. We update statistics here */

 static volatile struct tx_stats *tx_stats;

 

-

 /*

  * print a usage message

  */

@@ -149,6 +139,23 @@ parse_app_args(int argc, char *argv[])

 }

 

 /*

+ * Tx buffer error callback

+ */

+static void

+flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,

+		void *userdata) {

+	int i;

+	uint8_t port = (uintptr_t)userdata;

+

+	tx_stats->tx_drop[port] += count;

+

+	/* free the mbufs which failed from transmit */

+	for (i = 0; i < count; i++)

+		rte_pktmbuf_free(unsent[i]);

+

+}

+

+/*

  * set up output ports so that all traffic on port gets sent out

  * its paired port. Index using actual port numbers since that is

  * what comes in the mbuf structure.

@@ -164,41 +171,14 @@ static void configure_output_ports(const struct port_info *ports)

 		uint8_t p2 = ports->id[i+1];

 		output_ports[p1] = p2;

 		output_ports[p2] = p1;

-	}

-}

-

 

-static inline void

-send_packets(uint8_t port)

-{

-	uint16_t i, sent;

-	struct mbuf_queue *mbq = &output_bufs[port];

+		rte_eth_tx_buffer_set_err_callback(p1, client_id,

+				flush_tx_error_callback, (void *)(intptr_t)p1);

 

-	if (unlikely(mbq->top == 0))

-		return;

+		rte_eth_tx_buffer_set_err_callback(p2, client_id,

+				flush_tx_error_callback, (void *)(intptr_t)p2);

 

-	sent = rte_eth_tx_burst(port, client_id, mbq->bufs, mbq->top);

-	if (unlikely(sent < mbq->top)){

-		for (i = sent; i < mbq->top; i++)

-			rte_pktmbuf_free(mbq->bufs[i]);

-		tx_stats->tx_drop[port] += (mbq->top - sent);

 	}

-	tx_stats->tx[port] += sent;

-	mbq->top = 0;

-}

-

-/*

- * Enqueue a packet to be sent on a particular port, but

- * don't send it yet. Only when the buffer is full.

- */

-static inline void

-enqueue_packet(struct rte_mbuf *buf, uint8_t port)

-{

-	struct mbuf_queue *mbq = &output_bufs[port];

-	mbq->bufs[mbq->top++] = buf;

-

-	if (mbq->top == MBQ_CAPACITY)

-		send_packets(port);

 }

 

 /*

@@ -209,10 +189,13 @@ enqueue_packet(struct rte_mbuf *buf, uint8_t port)

 static void

 handle_packet(struct rte_mbuf *buf)

 {

+	unsigned sent;

 	const uint8_t in_port = buf->port;

 	const uint8_t out_port = output_ports[in_port];

 

-	enqueue_packet(buf, out_port);

+	sent = rte_eth_tx_buffer(out_port, client_id, buf);

+	if (unlikely(sent))

+		tx_stats->tx[out_port] += sent;

 }

 

 /*

@@ -229,6 +212,7 @@ main(int argc, char *argv[])

 	int need_flush = 0; /* indicates whether we have unsent packets */

 	int retval;

 	void *pkts[PKT_READ_SIZE];

+	uint16_t sent;

 

 	if ((retval = rte_eal_init(argc, argv)) < 0)

 		return -1;

@@ -274,8 +258,11 @@ main(int argc, char *argv[])

 

 		if (unlikely(rx_pkts == 0)){

 			if (need_flush)

-				for (port = 0; port < ports->num_ports; port++)

-					send_packets(ports->id[port]);

+				for (port = 0; port < ports->num_ports; port++) {

+					sent = rte_eth_tx_buffer_flush(ports->id[port], client_id);

+					if (unlikely(sent))

+						tx_stats->tx[port] += sent;

+				}

 			need_flush = 0;

 			continue;

 		}

diff --git a/examples/multi_process/l2fwd_fork/main.c b/examples/multi_process/l2fwd_fork/main.c

index f2d7eab..f919e07 100644

--- a/examples/multi_process/l2fwd_fork/main.c

+++ b/examples/multi_process/l2fwd_fork/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -117,18 +117,11 @@ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];

 

 static unsigned int l2fwd_rx_queue_per_lcore = 1;

 

-struct mbuf_table {

-	unsigned len;

-	struct rte_mbuf *m_table[MAX_PKT_BURST];

-};

-

 #define MAX_RX_QUEUE_PER_LCORE 16

 #define MAX_TX_QUEUE_PER_PORT 16

 struct lcore_queue_conf {

 	unsigned n_rx_port;

 	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];

-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];

-

 } __rte_cache_aligned;

 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];

 

@@ -176,7 +169,7 @@ static struct rte_mempool * l2fwd_pktmbuf_pool[RTE_MAX_ETHPORTS];

 struct l2fwd_port_statistics {

 	uint64_t tx;

 	uint64_t rx;

-	uint64_t dropped;

+	unsigned long dropped;

 } __rte_cache_aligned;

 struct l2fwd_port_statistics *port_statistics;

 /**

@@ -583,57 +576,12 @@ slave_exit_cb(unsigned slaveid, __attribute__((unused))int stat)

 	rte_spinlock_unlock(&res_lock);

 }

 

-/* Send the packet on an output interface */

-static int

-l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)

-{

-	struct rte_mbuf **m_table;

-	unsigned ret;

-	unsigned queueid =0;

-

-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;

-

-	ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);

-	port_statistics[port].tx += ret;

-	if (unlikely(ret < n)) {

-		port_statistics[port].dropped += (n - ret);

-		do {

-			rte_pktmbuf_free(m_table[ret]);

-		} while (++ret < n);

-	}

-

-	return 0;

-}

-

-/* Send the packet on an output interface */

-static int

-l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)

-{

-	unsigned lcore_id, len;

-	struct lcore_queue_conf *qconf;

-

-	lcore_id = rte_lcore_id();

-

-	qconf = &lcore_queue_conf[lcore_id];

-	len = qconf->tx_mbufs[port].len;

-	qconf->tx_mbufs[port].m_table[len] = m;

-	len++;

-

-	/* enough pkts to be sent */

-	if (unlikely(len == MAX_PKT_BURST)) {

-		l2fwd_send_burst(qconf, MAX_PKT_BURST, port);

-		len = 0;

-	}

-

-	qconf->tx_mbufs[port].len = len;

-	return 0;

-}

-

 static void

 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 {

 	struct ether_hdr *eth;

 	void *tmp;

+	unsigned sent;

 	unsigned dst_port;

 

 	dst_port = l2fwd_dst_ports[portid];

@@ -646,7 +594,9 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)

 	/* src addr */

 	ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);

 

-	l2fwd_send_packet(m, (uint8_t) dst_port);

+	sent = rte_eth_tx_buffer(dst_port, 0, m);

+	if (sent)

+		port_statistics[dst_port].tx += sent;

 }

 

 /* main processing loop */

@@ -656,6 +606,7 @@ l2fwd_main_loop(void)

 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];

 	struct rte_mbuf *m;

 	unsigned lcore_id;

+	unsigned sent;

 	uint64_t prev_tsc, diff_tsc, cur_tsc;

 	unsigned i, j, portid, nb_rx;

 	struct lcore_queue_conf *qconf;

@@ -698,14 +649,12 @@ l2fwd_main_loop(void)

 		 */

 		diff_tsc = cur_tsc - prev_tsc;

 		if (unlikely(diff_tsc > drain_tsc)) {

-

-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {

-				if (qconf->tx_mbufs[portid].len == 0)

-					continue;

-				l2fwd_send_burst(&lcore_queue_conf[lcore_id],

-						 qconf->tx_mbufs[portid].len,

-						 (uint8_t) portid);

-				qconf->tx_mbufs[portid].len = 0;

+			for (i = 0; i < qconf->n_rx_port; i++) {

+				portid = qconf->rx_port_list[i];

+				portid = l2fwd_dst_ports[portid];

+				sent = rte_eth_tx_buffer_flush(portid, 0);

+				if (sent)

+					port_statistics[portid].tx += sent;

 			}

 		}

 

@@ -1144,6 +1093,10 @@ main(int argc, char **argv)

 			rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",

 				ret, (unsigned) portid);

 

+		rte_eth_tx_buffer_set_err_callback(portid, 0,

+				rte_eth_count_unsent_packet_callback,

+				&port_statistics[portid].dropped);

+

 		/* Start device */

 		ret = rte_eth_dev_start(portid);

 		if (ret < 0)

diff --git a/examples/packet_ordering/main.c b/examples/packet_ordering/main.c

index 1d9a86f..a11d68e 100644

--- a/examples/packet_ordering/main.c

+++ b/examples/packet_ordering/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -86,11 +86,6 @@ struct send_thread_args {

 	struct rte_reorder_buffer *buffer;

 };

 

-struct output_buffer {

-	unsigned count;

-	struct rte_mbuf *mbufs[MAX_PKTS_BURST];

-};

-

 volatile struct app_stats {

 	struct {

 		uint64_t rx_pkts;

@@ -235,6 +230,20 @@ parse_args(int argc, char **argv)

 	return 0;

 }

 

+/*

+ * Tx buffer error callback

+ */

+static void

+flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,

+		void *userdata __rte_unused) {

+

+	/* free the mbufs which failed from transmit */

+	app_stats.tx.ro_tx_failed_pkts += count;

+	LOG_DEBUG(REORDERAPP, "%s:Packet loss with tx_burst\n", __func__);

+	pktmbuf_free_bulk(unsent, count);

+

+}

+

 static inline int

 configure_eth_port(uint8_t port_id)

 {

@@ -266,6 +275,9 @@ configure_eth_port(uint8_t port_id)

 			return ret;

 	}

 

+	rte_eth_tx_buffer_set_err_callback(port_id, 0, flush_tx_error_callback,

+			NULL);

+

 	ret = rte_eth_dev_start(port_id);

 	if (ret < 0)

 		return ret;

@@ -438,22 +450,6 @@ worker_thread(void *args_ptr)

 	return 0;

 }

 

-static inline void

-flush_one_port(struct output_buffer *outbuf, uint8_t outp)

-{

-	unsigned nb_tx = rte_eth_tx_burst(outp, 0, outbuf->mbufs,

-			outbuf->count);

-	app_stats.tx.ro_tx_pkts += nb_tx;

-

-	if (unlikely(nb_tx < outbuf->count)) {

-		/* free the mbufs which failed from transmit */

-		app_stats.tx.ro_tx_failed_pkts += (outbuf->count - nb_tx);

-		LOG_DEBUG(REORDERAPP, "%s:Packet loss with tx_burst\n", __func__);

-		pktmbuf_free_bulk(&outbuf->mbufs[nb_tx], outbuf->count - nb_tx);

-	}

-	outbuf->count = 0;

-}

-

 /**

  * Dequeue mbufs from the workers_to_tx ring and reorder them before

  * transmitting.

@@ -464,8 +460,8 @@ send_thread(struct send_thread_args *args)

 	int ret;

 	unsigned int i, dret;

 	uint16_t nb_dq_mbufs;

+	uint16_t sent;

 	uint8_t outp;

-	static struct output_buffer tx_buffers[RTE_MAX_ETHPORTS];

 	struct rte_mbuf *mbufs[MAX_PKTS_BURST];

 	struct rte_mbuf *rombufs[MAX_PKTS_BURST] = {NULL};

 

@@ -515,7 +511,6 @@ send_thread(struct send_thread_args *args)

 		dret = rte_reorder_drain(args->buffer, rombufs, MAX_PKTS_BURST);

 		for (i = 0; i < dret; i++) {

 

-			struct output_buffer *outbuf;

 			uint8_t outp1;

 

 			outp1 = rombufs[i]->port;

@@ -525,10 +520,10 @@ send_thread(struct send_thread_args *args)

 				continue;

 			}

 

-			outbuf = &tx_buffers[outp1];

-			outbuf->mbufs[outbuf->count++] = rombufs[i];

-			if (outbuf->count == MAX_PKTS_BURST)

-				flush_one_port(outbuf, outp1);

+			sent = rte_eth_tx_buffer(outp1, 0, rombufs[i]);

+			if (sent)

+				app_stats.tx.ro_tx_pkts += sent;

+

 		}

 	}

 	return 0;

@@ -541,10 +536,9 @@ static int

 tx_thread(struct rte_ring *ring_in)

 {

 	uint32_t i, dqnum;

+	uint16_t sent;

 	uint8_t outp;

-	static struct output_buffer tx_buffers[RTE_MAX_ETHPORTS];

 	struct rte_mbuf *mbufs[MAX_PKTS_BURST];

-	struct output_buffer *outbuf;

 

 	RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__,

 							rte_lcore_id());

@@ -567,10 +561,10 @@ tx_thread(struct rte_ring *ring_in)

 				continue;

 			}

 

-			outbuf = &tx_buffers[outp];

-			outbuf->mbufs[outbuf->count++] = mbufs[i];

-			if (outbuf->count == MAX_PKTS_BURST)

-				flush_one_port(outbuf, outp);

+			sent = rte_eth_tx_buffer(outp, 0, mbufs[i]);

+			if (sent)

+				app_stats.tx.ro_tx_pkts += sent;

+

 		}

 	}

 

diff --git a/examples/qos_meter/main.c b/examples/qos_meter/main.c

index 0de5e7f..7d901d2 100644

--- a/examples/qos_meter/main.c

+++ b/examples/qos_meter/main.c

@@ -1,7 +1,7 @@

 /*-

  *   BSD LICENSE

  *

- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.

  *   All rights reserved.

  *

  *   Redistribution and use in source and binary forms, with or without

@@ -118,8 +118,6 @@ static struct rte_eth_conf port_conf = {

 static uint8_t port_rx;

 static uint8_t port_tx;

 static struct rte_mbuf *pkts_rx[PKT_RX_BURST_MAX];

-static struct rte_mbuf *pkts_tx[PKT_TX_BURST_MAX];

-static uint16_t pkts_tx_len = 0;

 

 

 struct rte_meter_srtcm_params app_srtcm_params[] = {

@@ -188,26 +186,9 @@ main_loop(__attribute__((unused)) void *dummy)

 		current_time = rte_rdtsc();

 		time_diff = current_time - last_time;

 		if (unlikely(time_diff > TIME_TX_DRAIN)) {

-			int ret;

 

-			if (pkts_tx_len == 0) {

-				last_time = current_time;

-

-				continue;

-			}

-

-			/* Write packet burst to NIC TX */

-			ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, pkts_tx_len);

-

-			/* Free buffers for any packets not written successfully */

-			if (unlikely(ret < pkts_tx_len)) {

-				for ( ; ret < pkts_tx_len; ret ++) {

-					rte_pktmbuf_free(pkts_tx[ret]);

-				}

-			}

-

-			/* Empty the output buffer */

-			pkts_tx_len = 0;

+			/* Flush tx buffer */

+			rte_eth_tx_buffer_flush(port_tx, NIC_TX_QUEUE);

 

 			last_time = current_time;

 		}

@@ -222,26 +203,9 @@ main_loop(__attribute__((unused)) void *dummy)

 			/* Handle current packet */

 			if (app_pkt_handle(pkt, current_time) == DROP)

 				rte_pktmbuf_free(pkt);

-			else {

-				pkts_tx[pkts_tx_len] = pkt;

-				pkts_tx_len ++;

-			}

-

-			/* Write packets from output buffer to NIC TX when full burst is available */

-			if (unlikely(pkts_tx_len == PKT_TX_BURST_MAX)) {

-				/* Write packet burst to NIC TX */

-				int ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, PKT_TX_BURST_MAX);

+			else

+				rte_eth_tx_buffer(port_tx, NIC_TX_QUEUE, pkt);

 

-				/* Free buffers for any packets not written successfully */

-				if (unlikely(ret < PKT_TX_BURST_MAX)) {

-					for ( ; ret < PKT_TX_BURST_MAX; ret ++) {

-						rte_pktmbuf_free(pkts_tx[ret]);

-					}

-				}

-

-				/* Empty the output buffer */

-				pkts_tx_len = 0;

-			}

 		}

 	}

 }

-- 

1.7.9.5

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2016-03-11 16:41 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-15 14:43 [PATCH 0/2] add support for buffered tx to ethdev Tomasz Kulasek
2016-01-15 14:43 ` [PATCH 1/2] ethdev: add buffered tx api Tomasz Kulasek
2016-01-15 18:13   ` Stephen Hemminger
2016-01-15 18:14   ` Stephen Hemminger
2016-01-15 18:44   ` Ananyev, Konstantin
2016-02-02 10:00     ` Kulasek, TomaszX
2016-02-02 13:49       ` Ananyev, Konstantin
2016-02-09 17:02         ` Kulasek, TomaszX
2016-02-09 23:56           ` Ananyev, Konstantin
2016-02-12 11:44             ` Ananyev, Konstantin
2016-02-12 16:40               ` Ivan Boule
2016-02-12 17:33                 ` Bruce Richardson
2016-01-15 14:43 ` [PATCH 2/2] examples: sample apps rework to use " Tomasz Kulasek
2016-01-15 18:12 ` [PATCH 0/2] add support for buffered tx to ethdev Stephen Hemminger
2016-02-24 17:08 ` [PATCH v2 " Tomasz Kulasek
2016-02-24 17:08   ` [PATCH v2 1/2] ethdev: add buffered tx api Tomasz Kulasek
2016-03-08 22:52     ` Thomas Monjalon
2016-03-09 13:36       ` Ananyev, Konstantin
2016-03-09 14:25         ` Thomas Monjalon
2016-03-09 15:23           ` Ananyev, Konstantin
2016-03-09 15:26             ` Thomas Monjalon
2016-03-09 15:32               ` Kulasek, TomaszX
2016-03-09 15:37                 ` Thomas Monjalon
2016-03-09 15:42               ` Ananyev, Konstantin
2016-03-09 15:52                 ` Thomas Monjalon
2016-03-09 16:17                   ` Ananyev, Konstantin
2016-03-09 16:21                     ` Thomas Monjalon
2016-03-09 16:35       ` Kulasek, TomaszX
2016-03-09 17:06         ` Thomas Monjalon
2016-03-09 18:12           ` Kulasek, TomaszX
2016-02-24 17:08   ` [PATCH v2 2/2] examples: rework to use " Tomasz Kulasek
2016-02-25 16:17   ` [PATCH v2 0/2] add support for buffered tx to ethdev Ananyev, Konstantin
2016-03-10 10:57   ` [PATCH v3 " Tomasz Kulasek
2016-03-10 10:57     ` [PATCH v3 1/2] ethdev: add buffered tx api Tomasz Kulasek
2016-03-10 16:23       ` Thomas Monjalon
2016-03-10 17:15         ` Kulasek, TomaszX
2016-03-10 10:57     ` [PATCH v3 2/2] examples: rework to use buffered tx Tomasz Kulasek
2016-03-10 11:31     ` [PATCH v3 0/2] add support for buffered tx to ethdev Ananyev, Konstantin
2016-03-10 16:01       ` Jastrzebski, MichalX K
2016-03-10 17:19     ` [PATCH v4 " Tomasz Kulasek
2016-03-10 17:19       ` [PATCH v4 1/2] ethdev: add buffered tx api Tomasz Kulasek
2016-03-10 17:19       ` [PATCH v4 2/2] examples: rework to use buffered tx Tomasz Kulasek
2016-03-11 16:39       ` [PATCH v4 0/2] add support for buffered tx to ethdev Thomas Monjalon
  -- strict thread matches above, loose matches on Subject: below --
2016-01-15 14:26 [PATCH 2/2] examples: sample apps rework to use buffered tx api Tomasz Kulasek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).