@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -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],
+ ð_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;
+}
new file mode 100644
@@ -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_ */