[dpdk-dev] [PATCH] examples: new txburst application

Bhavesh Davda bhavesh at vmware.com
Tue Nov 18 19:32:55 CET 2014


Test application to transmit 32-packet bursts of 220-byte UDP packets every
50 us, approximating 240,000 pps. We found it useful for testing hypervisor
performance for a transmit-heavy but bursty workload in a VM with DPDK.

Signed-off-by: Bhavesh Davda <bhavesh at vmware.com>
---
 examples/Makefile          |    1 +
 examples/txburst/Makefile  |   53 +++++++++
 examples/txburst/burst.c   |  221 +++++++++++++++++++++++++++++++++++
 examples/txburst/burst.h   |   55 +++++++++
 examples/txburst/txburst.c |  278 ++++++++++++++++++++++++++++++++++++++++++++
 examples/txburst/txburst.h |   40 +++++++
 6 files changed, 648 insertions(+), 0 deletions(-)
 create mode 100644 examples/txburst/Makefile
 create mode 100644 examples/txburst/burst.c
 create mode 100644 examples/txburst/burst.h
 create mode 100644 examples/txburst/txburst.c
 create mode 100644 examples/txburst/txburst.h

diff --git a/examples/Makefile b/examples/Makefile
index 121dab4..12b10e1 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -62,6 +62,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_METER) += qos_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += qos_sched
 DIRS-y += quota_watermark
 DIRS-y += timer
+DIRS-y += txburst
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost
 DIRS-$(CONFIG_RTE_LIBRTE_XEN_DOM0) += vhost_xen
 DIRS-y += vmdq
diff --git a/examples/txburst/Makefile b/examples/txburst/Makefile
new file mode 100644
index 0000000..38334f7
--- /dev/null
+++ b/examples/txburst/Makefile
@@ -0,0 +1,53 @@
+##########################################################
+# Copyright (C) 2014 VMware, Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+##########################################################
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overriden by command line or environment
+RTE_TARGET ?= x86_64-default-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = txburst
+
+# all source are stored in SRCS-y
+SRCS-y := txburst.c burst.c
+
+CFLAGS += $(WERROR_FLAGS)
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+EXTRA_CFLAGS += -O3 -g -Wfatal-errors
+
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/txburst/burst.c b/examples/txburst/burst.c
new file mode 100644
index 0000000..dd682e8
--- /dev/null
+++ b/examples/txburst/burst.c
@@ -0,0 +1,221 @@
+/*********************************************************
+ * Copyright (C) 2014 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#include <rte_byteorder.h>
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+
+#include "burst.h"
+
+#define IP_DEFTTL  64   /* from RFC 1340. */
+#define IP_VERSION 0x40
+#define IP_HDRLEN  0x05 /* default IP header length == five 32-bits words. */
+#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
+
+static void
+copy_buf_to_pkt_segs(void *buf, unsigned len, struct rte_mbuf *pkt,
+		unsigned offset)
+{
+	struct rte_mbuf *seg;
+	void *seg_buf;
+	unsigned copy_len;
+
+	seg = pkt;
+	while (offset >= seg->data_len) {
+		offset -= seg->data_len;
+		seg = seg->next;
+	}
+	copy_len = seg->data_len - offset;
+	seg_buf = rte_pktmbuf_mtod(seg, char *) + offset;
+	while (len > copy_len) {
+		rte_memcpy(seg_buf, buf, (size_t) copy_len);
+		len -= copy_len;
+		buf = ((char *) buf + copy_len);
+		seg = seg->next;
+		seg_buf = rte_pktmbuf_mtod(seg, void *);
+	}
+	rte_memcpy(seg_buf, buf, (size_t) len);
+}
+
+static inline void
+copy_buf_to_pkt(void *buf, unsigned len, struct rte_mbuf *pkt, unsigned offset)
+{
+	if (offset + len <= pkt->data_len) {
+		rte_memcpy(rte_pktmbuf_mtod(pkt, char *) + offset,
+				buf, (size_t) len);
+		return;
+	}
+	copy_buf_to_pkt_segs(buf, len, pkt, offset);
+}
+
+
+uint16_t
+initialize_udp_header(struct udp_hdr *udp_hdr, uint16_t src_port,
+		uint16_t dst_port, uint16_t pkt_data_len)
+{
+	uint16_t pkt_len;
+
+	pkt_len = (uint16_t) (pkt_data_len + sizeof(struct udp_hdr));
+
+	udp_hdr->src_port = rte_cpu_to_be_16(src_port);
+	udp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
+	udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
+	udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
+
+	return pkt_len;
+}
+
+
+uint16_t
+initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr,
+		uint32_t dst_addr, uint16_t pkt_data_len)
+{
+	uint16_t pkt_len;
+	uint16_t *ptr16;
+	uint32_t ip_cksum;
+
+	/*
+	 * Initialize IP header.
+	 */
+	pkt_len = (uint16_t) (pkt_data_len + sizeof(struct ipv4_hdr));
+
+	ip_hdr->version_ihl   = IP_VHL_DEF;
+	ip_hdr->type_of_service   = 0;
+	ip_hdr->fragment_offset = 0;
+	ip_hdr->time_to_live   = IP_DEFTTL;
+	ip_hdr->next_proto_id = IPPROTO_UDP;
+	ip_hdr->packet_id = 0;
+	ip_hdr->total_length   = rte_cpu_to_be_16(pkt_len);
+	ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
+	ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
+
+	/*
+	 * Compute IP header checksum.
+	 */
+	ptr16 = (uint16_t *)ip_hdr;
+	ip_cksum = 0;
+	ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
+	ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
+	ip_cksum += ptr16[4];
+	ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
+	ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
+
+	/*
+	 * Reduce 32 bit checksum to 16 bits and complement it.
+	 */
+	ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
+		(ip_cksum & 0x0000FFFF);
+	ip_cksum %= 65536;
+	ip_cksum = (~ip_cksum) & 0x0000FFFF;
+	if (ip_cksum == 0)
+		ip_cksum = 0xFFFF;
+	ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+
+	return pkt_len;
+}
+
+
+
+/*
+ * The maximum number of segments per packet is used when creating
+ * scattered transmit packets composed of a list of mbufs.
+ */
+#define RTE_MAX_SEGS_PER_PKT 255 /**< pkt.nb_segs is a 8-bit unsigned char. */
+
+#define TXONLY_DEF_PACKET_LEN 64
+#define TXONLY_DEF_PACKET_LEN_220 220
+
+uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN;
+uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = {
+		TXONLY_DEF_PACKET_LEN_220,
+};
+
+uint8_t  tx_pkt_nb_segs = 1;
+
+int
+generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
+		struct ether_hdr *eth_hdr, void *ip_hdr,
+		struct udp_hdr *udp_hdr, int nb_pkt_per_burst)
+{
+	int i, nb_pkt = 0;
+	size_t eth_hdr_size;
+
+	struct rte_mbuf *pkt_seg;
+	struct rte_mbuf *pkt;
+
+	for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+		pkt = rte_pktmbuf_alloc(mp);
+		if (pkt == NULL) {
+nomore_mbuf:
+			if (nb_pkt == 0)
+				return -1;
+			break;
+		}
+
+		pkt->data_len = tx_pkt_seg_lengths[0];
+		pkt_seg = pkt;
+		for (i = 1; i < tx_pkt_nb_segs; i++) {
+			pkt_seg->next = rte_pktmbuf_alloc(mp);
+			if (pkt_seg->next == NULL) {
+				pkt->nb_segs = i;
+				rte_pktmbuf_free(pkt);
+				goto nomore_mbuf;
+			}
+			pkt_seg = pkt_seg->next;
+			pkt_seg->data_len = tx_pkt_seg_lengths[i];
+		}
+		pkt_seg->next = NULL; /* Last segment of packet. */
+
+		/*
+		 * Copy headers in first packet segment(s).
+		 */
+		eth_hdr_size = sizeof(struct ether_hdr);
+
+		copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
+
+		copy_buf_to_pkt(ip_hdr, sizeof(struct ipv4_hdr), pkt,
+			eth_hdr_size);
+		copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
+			eth_hdr_size + sizeof(struct ipv4_hdr));
+
+		/*
+		 * Complete first mbuf of packet and append it to the
+		 * burst of packets to be transmitted.
+		 */
+		pkt->nb_segs = tx_pkt_nb_segs;
+		pkt->pkt_len = tx_pkt_length;
+		pkt->l2_len = eth_hdr_size;
+
+		pkt->vlan_tci  = ETHER_TYPE_IPv4;
+		pkt->l3_len = sizeof(struct ipv4_hdr);
+		pkt->ol_flags = PKT_RX_IPV4_HDR;
+
+		pkts_burst[nb_pkt] = pkt;
+	}
+
+	return nb_pkt;
+}
diff --git a/examples/txburst/burst.h b/examples/txburst/burst.h
new file mode 100644
index 0000000..760c30f
--- /dev/null
+++ b/examples/txburst/burst.h
@@ -0,0 +1,55 @@
+/*********************************************************
+ * Copyright (C) 2014 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef PACKET_BURST_GENERATOR_H_
+#define PACKET_BURST_GENERATOR_H_
+
+#include <rte_mbuf.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+
+
+#define IPV4_ADDR(a, b, c, d)(((a & 0xff) << 24) | ((b & 0xff) << 16) | \
+		((c & 0xff) << 8) | (d & 0xff))
+
+
+uint16_t
+initialize_udp_header(struct udp_hdr *udp_hdr, uint16_t src_port,
+		uint16_t dst_port, uint16_t pkt_data_len);
+
+
+uint16_t
+initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr,
+		uint32_t dst_addr, uint16_t pkt_data_len);
+
+int
+generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
+		struct ether_hdr *eth_hdr, void *ip_hdr,
+		struct udp_hdr *udp_hdr, int nb_pkt_per_burst);
+
+#endif /* PACKET_BURST_GENERATOR_H_ */
diff --git a/examples/txburst/txburst.c b/examples/txburst/txburst.c
new file mode 100644
index 0000000..dbcb831
--- /dev/null
+++ b/examples/txburst/txburst.c
@@ -0,0 +1,278 @@
+/*********************************************************
+ * Copyright (C) 2014 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <time.h>
+#include <sys/time.h>
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_mbuf.h>
+#include <rte_byteorder.h>
+#include "txburst.h"
+#include "burst.h"
+
+#define RX_RING_SIZE 128
+#define RX_FREE_THRESH 32
+#define RX_PTHRESH 8
+#define RX_HTHRESH 8
+#define RX_WTHRESH 0
+
+#define TX_RING_SIZE 512
+#define TX_FREE_THRESH 32
+#define TX_PTHRESH 32
+#define TX_HTHRESH 0
+#define TX_WTHRESH 0
+#define TX_RSBIT_THRESH 32
+#define TX_Q_FLAGS (ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOVLANOFFL |\
+	ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \
+	ETH_TXQ_FLAGS_NOXSUMTCP)
+
+#define NUM_MBUFS 8191
+#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
+#define MBUF_CACHE_SIZE 250
+#define BURST_SIZE 32
+
+static struct rte_eth_conf port_conf_default = {
+	.rxmode = {
+		.mq_mode = ETH_MQ_RX_NONE,
+		.max_rx_pkt_len = ETHER_MAX_LEN,
+		.split_hdr_size = 0,
+		.header_split   = 0, /**< Header Split disabled */
+		.hw_ip_checksum = 0, /**< IP checksum offload enabled */
+		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
+		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
+		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
+	},
+	.txmode = {
+		.mq_mode = ETH_MQ_TX_NONE,
+	},
+	.lpbk_mode = 0,
+};
+
+static const struct rte_eth_rxconf rx_conf_default = {
+	.rx_thresh = {
+		.pthresh = RX_PTHRESH,
+		.hthresh = RX_HTHRESH,
+		.wthresh = RX_WTHRESH,
+	},
+	.rx_free_thresh = RX_FREE_THRESH,
+	.rx_drop_en = 0,
+};
+
+static struct rte_eth_txconf tx_conf_default = {
+	.tx_thresh = {
+		.pthresh = TX_PTHRESH,
+		.hthresh = TX_HTHRESH,
+		.wthresh = TX_WTHRESH,
+	},
+	.tx_free_thresh = TX_FREE_THRESH,
+	.tx_rs_thresh = TX_RSBIT_THRESH,
+	.txq_flags = TX_Q_FLAGS
+
+};
+
+static struct rte_mbuf *mbufs[2][BURST_SIZE * 100];
+static uint32_t src_addr = IPV4_ADDR(192, 168, 1, 98);
+static uint32_t dst_addr = IPV4_ADDR(192, 168, 1, 99);
+
+static struct timespec tv = {
+	.tv_sec = 0,
+	.tv_nsec = 50000		/* 50 us */
+};
+
+/*
+ * Initialises a given port using global settings and with the rx buffers
+ * coming from the mbuf_pool passed as parameter
+ */
+static inline int
+port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+{
+	struct rte_eth_conf port_conf = port_conf_default;
+	const uint16_t rxRings = 1, txRings = 1;
+	int retval;
+	uint16_t q;
+
+	if (port >= rte_eth_dev_count())
+		return -1;
+
+	retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf);
+	if (retval != 0)
+		return retval;
+
+	for (q = 0; q < rxRings; q++) {
+		retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
+				rte_eth_dev_socket_id(port), &rx_conf_default,
+				mbuf_pool);
+		if (retval < 0)
+			return retval;
+	}
+
+	for (q = 0; q < txRings; q++) {
+		retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
+				rte_eth_dev_socket_id(port), &tx_conf_default);
+		if (retval < 0)
+			return retval;
+	}
+
+	retval  = rte_eth_dev_start(port);
+	if (retval < 0)
+		return retval;
+
+	struct ether_addr addr;
+
+	rte_eth_macaddr_get(port, &addr);
+	printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
+			" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
+			(unsigned)port,
+			addr.addr_bytes[0], addr.addr_bytes[1],
+			addr.addr_bytes[2], addr.addr_bytes[3],
+			addr.addr_bytes[4], addr.addr_bytes[5]);
+
+	struct ether_hdr eth_hdr;
+
+	eth_hdr.s_addr = addr;
+	addr.addr_bytes[5] ^= 1;
+	eth_hdr.d_addr = addr;
+	eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+
+	int pkt_len;
+	struct udp_hdr udp_hdr;
+	struct ipv4_hdr ip_hdr;
+
+	pkt_len = initialize_udp_header(&udp_hdr, 0x0246, 0x0357, 174);
+	pkt_len = initialize_ipv4_header(&ip_hdr, src_addr, dst_addr, pkt_len);
+
+	int num_pkts;
+
+	num_pkts = generate_packet_burst(mbuf_pool, &mbufs[port][0],
+			&eth_hdr, &ip_hdr,
+			&udp_hdr, BURST_SIZE * 100);
+
+	if (num_pkts < BURST_SIZE * 100)
+		rte_exit(EXIT_FAILURE, "Cannot allocate packet bursts\n");
+
+	return 0;
+}
+
+/*
+ * Main thread that does the work, reading from INPUT_PORT
+ * and writing to OUTPUT_PORT
+ */
+static  __attribute__((noreturn)) void
+lcore_main(void)
+{
+	const uint8_t nb_ports = rte_eth_dev_count();
+	uint8_t port;
+	int burst_cycle = 0;
+	unsigned long pktsTxed = 0;
+	struct timeval tvStart, tvEnd, tvDiff, tvLastDrop, tvNow;
+	struct timespec tvrem;
+
+	printf("\nCore %u transmitting packets. [Ctrl+C to quit]\n",
+			rte_lcore_id());
+	gettimeofday(&tvStart, NULL);
+	tvLastDrop = tvStart;
+	for (;;) {
+		for (port = 0; port < nb_ports; port++) {
+			const uint16_t nb_tx = rte_eth_tx_burst(port, 0,
+					&mbufs[port]
+					[(burst_cycle % 100) * BURST_SIZE],
+					BURST_SIZE);
+			pktsTxed += nb_tx;
+			if (unlikely(nb_tx < BURST_SIZE)) {
+				gettimeofday(&tvNow, NULL);
+				timersub(&tvNow, &tvLastDrop, &tvDiff);
+				printf("Port %d dropped %d (Time since last "
+					"drop %g s)\n", port,
+					BURST_SIZE - nb_tx, tvDiff.tv_sec +
+					tvDiff.tv_usec/1000000.0);
+				tvLastDrop = tvNow;
+			}
+		}
+		burst_cycle++;
+		if (burst_cycle % 50000 == 0) {
+			gettimeofday(&tvEnd, NULL);
+			timersub(&tvEnd, &tvStart, &tvDiff);
+			printf("%g pps...",
+				pktsTxed / (tvDiff.tv_sec + tvDiff.tv_usec/1000000.0));
+			if (burst_cycle % 500000 == 0)
+				printf("\n");
+			fflush(stdout);
+			pktsTxed = 0;
+			tvStart = tvEnd;
+		}
+		tvrem = tv;
+		while (nanosleep(&tvrem, &tvrem) != 0)
+			;
+	}
+}
+
+/* Main function, does initialisation and calls the per-lcore functions */
+int
+MAIN(int argc, char *argv[])
+{
+	struct rte_mempool *mbuf_pool;
+	unsigned nb_ports;
+	uint8_t portid;
+
+	/* init EAL */
+	int ret = rte_eal_init(argc, argv);
+
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+	argc -= ret;
+	argv += ret;
+
+	nb_ports = rte_eth_dev_count();
+	if (nb_ports > 2)
+		rte_exit(EXIT_FAILURE, "Error: number of ports must be <=2\n");
+
+	mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
+				       MBUF_SIZE, MBUF_CACHE_SIZE,
+				       sizeof(struct rte_pktmbuf_pool_private),
+				       rte_pktmbuf_pool_init, NULL,
+				       rte_pktmbuf_init, NULL,
+				       rte_socket_id(), 0);
+	if (mbuf_pool == NULL)
+		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+
+	/* initialize all ports */
+	for (portid = 0; portid < nb_ports; portid++)
+		if (port_init(portid, mbuf_pool) != 0)
+			rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n",
+					portid);
+
+	if (rte_lcore_count() > 1)
+		printf("\nWARNING: Coremask too big - App uses only 1 lcore\n");
+
+	/* call lcore_main on master core only */
+	lcore_main();
+	return 0;
+}
diff --git a/examples/txburst/txburst.h b/examples/txburst/txburst.h
new file mode 100644
index 0000000..909dd3b
--- /dev/null
+++ b/examples/txburst/txburst.h
@@ -0,0 +1,40 @@
+/*********************************************************
+ * Copyright (C) 2014 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+
+#ifdef RTE_EXEC_ENV_BAREMETAL
+#define MAIN _main
+#else
+#define MAIN main
+#endif
+
+int MAIN(int argc, char *argv[]);
+
+#endif /* ifndef _MAIN_H_ */
-- 
1.7.1



More information about the dev mailing list