DPDK patches and discussions
 help / color / mirror / Atom feed
From: Fan Zhang <roy.fan.zhang@intel.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v4 1/4] lib/librte_port: add PCAP file support to source port
Date: Fri, 11 Mar 2016 17:08:07 +0000	[thread overview]
Message-ID: <1457716090-26742-2-git-send-email-roy.fan.zhang@intel.com> (raw)
In-Reply-To: <1457716090-26742-1-git-send-email-roy.fan.zhang@intel.com>

Originally, source ports in librte_port is an input port used as packet
generator. Similar to Linux kernel /dev/zero character device, it
generates null packets. This patch adds optional PCAP file support to
source port: instead of sending NULL packets, the source port generates
packets copied from a PCAP file. To increase the performance, the packets
in the file are loaded to memory initially, and copied to mbufs in circular
manner. Users can enable or disable this feature by setting
CONFIG_RTE_PORT_PCAP compiler option "y" or "n".

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 config/common_base                     |   1 +
 lib/librte_port/Makefile               |  10 +-
 lib/librte_port/rte_port_source_sink.c | 251 ++++++++++++++++++++++++++++++++-
 lib/librte_port/rte_port_source_sink.h |  13 +-
 mk/rte.app.mk                          |   5 +
 5 files changed, 275 insertions(+), 5 deletions(-)

diff --git a/config/common_base b/config/common_base
index 192e198..52bd34f 100644
--- a/config/common_base
+++ b/config/common_base
@@ -466,6 +466,7 @@ CONFIG_RTE_LIBRTE_REORDER=y
 #
 CONFIG_RTE_LIBRTE_PORT=y
 CONFIG_RTE_PORT_STATS_COLLECT=n
+CONFIG_RTE_PORT_PCAP=n
 
 #
 # Compile librte_table
diff --git a/lib/librte_port/Makefile b/lib/librte_port/Makefile
index 410053e..0b31c04 100644
--- a/lib/librte_port/Makefile
+++ b/lib/librte_port/Makefile
@@ -1,6 +1,6 @@
 #   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
@@ -36,6 +36,14 @@ include $(RTE_SDK)/mk/rte.vars.mk
 #
 LIB = librte_port.a
 
+ifeq ($(CONFIG_RTE_NEXT_ABI),y)
+
+ifeq ($(CONFIG_RTE_PORT_PCAP),y)
+LDLIBS += -lpcap
+endif
+
+endif
+
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 
diff --git a/lib/librte_port/rte_port_source_sink.c b/lib/librte_port/rte_port_source_sink.c
index a06477e..3d4e8d9 100644
--- a/lib/librte_port/rte_port_source_sink.c
+++ b/lib/librte_port/rte_port_source_sink.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
@@ -37,6 +37,16 @@
 #include <rte_mempool.h>
 #include <rte_malloc.h>
 
+#ifdef RTE_NEXT_ABI
+
+#include <rte_memcpy.h>
+
+#ifdef RTE_PORT_PCAP
+#include <pcap.h>
+#endif
+
+#endif
+
 #include "rte_port_source_sink.h"
 
 /*
@@ -60,8 +70,174 @@ struct rte_port_source {
 	struct rte_port_in_stats stats;
 
 	struct rte_mempool *mempool;
+
+#ifdef RTE_NEXT_ABI
+	/* PCAP buffers and indexes */
+	uint8_t **pkts;
+	uint8_t *pkt_buff;
+	uint32_t *pkt_len;
+	uint32_t n_pkts;
+	uint32_t pkt_index;
+#endif
 };
 
+#ifdef RTE_NEXT_ABI
+
+#ifdef RTE_PORT_PCAP
+
+/**
+ * Load PCAP file, allocate and copy packets in the file to memory
+ *
+ * @param p
+ *   Parameters for source port
+ * @param port
+ *   Handle to source port
+ * @param socket_id
+ *   Socket id where the memory is created
+ * @return
+ *   0 on SUCCESS
+ *   error code otherwise
+ */
+static int
+pcap_source_load(struct rte_port_source_params *p,
+		struct rte_port_source *port,
+		int socket_id)
+{
+	uint32_t status = 0;
+	uint32_t n_pkts = 0;
+	uint32_t i;
+	uint32_t *pkt_len_aligns = NULL;
+	size_t total_buff_len = 0;
+	pcap_t *pcap_handle;
+	char pcap_errbuf[PCAP_ERRBUF_SIZE];
+	uint32_t max_len;
+	struct pcap_pkthdr pcap_hdr;
+	const uint8_t *pkt;
+	uint8_t *buff = NULL;
+	uint32_t pktmbuf_maxlen = (uint32_t)
+			(rte_pktmbuf_data_room_size(port->mempool) -
+			RTE_PKTMBUF_HEADROOM);
+
+	if (p->file_name == NULL)
+		return 0;
+
+	if (p->n_bytes_per_pkt == 0)
+		max_len = pktmbuf_maxlen;
+	else
+		max_len = RTE_MIN(p->n_bytes_per_pkt, pktmbuf_maxlen);
+
+	/* first time open, get packet number */
+	pcap_handle = pcap_open_offline(p->file_name, pcap_errbuf);
+	if (pcap_handle == NULL) {
+		status = -ENOENT;
+		goto error_exit;
+	}
+
+	while ((pkt = pcap_next(pcap_handle, &pcap_hdr)) != NULL)
+		n_pkts++;
+
+	pcap_close(pcap_handle);
+
+	port->pkt_len = rte_zmalloc_socket("PCAP",
+		(sizeof(*port->pkt_len) * n_pkts), 0, socket_id);
+	if (port->pkt_len == NULL) {
+		status = -ENOMEM;
+		goto error_exit;
+	}
+
+	pkt_len_aligns = rte_malloc("PCAP",
+		(sizeof(*pkt_len_aligns) * n_pkts), 0);
+	if (pkt_len_aligns == NULL) {
+		status = -ENOMEM;
+		goto error_exit;
+	}
+
+	port->pkts = rte_zmalloc_socket("PCAP",
+		(sizeof(*port->pkts) * n_pkts), 0, socket_id);
+	if (port->pkts == NULL) {
+		status = -ENOMEM;
+		goto error_exit;
+	}
+
+	/* open 2nd time, get pkt_len */
+	pcap_handle = pcap_open_offline(p->file_name, pcap_errbuf);
+	if (pcap_handle == NULL) {
+		status = -ENOENT;
+		goto error_exit;
+	}
+
+	for (i = 0; i < n_pkts; i++) {
+		pkt = pcap_next(pcap_handle, &pcap_hdr);
+		port->pkt_len[i] = RTE_MIN(max_len, pcap_hdr.len);
+		pkt_len_aligns[i] = RTE_CACHE_LINE_ROUNDUP(
+			port->pkt_len[i]);
+		total_buff_len += pkt_len_aligns[i];
+	}
+
+	pcap_close(pcap_handle);
+
+	/* allocate a big trunk of data for pcap file load */
+	buff = rte_zmalloc_socket("PCAP",
+		total_buff_len, 0, socket_id);
+	if (buff == NULL) {
+		status = -ENOMEM;
+		goto error_exit;
+	}
+
+	port->pkt_buff = buff;
+
+	/* open file one last time to copy the pkt content */
+	pcap_handle = pcap_open_offline(p->file_name, pcap_errbuf);
+	if (pcap_handle == NULL) {
+		status = -ENOENT;
+		goto error_exit;
+	}
+
+	for (i = 0; i < n_pkts; i++) {
+		pkt = pcap_next(pcap_handle, &pcap_hdr);
+		rte_memcpy(buff, pkt, port->pkt_len[i]);
+		port->pkts[i] = buff;
+		buff += pkt_len_aligns[i];
+	}
+
+	pcap_close(pcap_handle);
+
+	port->n_pkts = n_pkts;
+
+	rte_free(pkt_len_aligns);
+
+	return 0;
+
+error_exit:
+	if (pkt_len_aligns)
+		rte_free(pkt_len_aligns);
+	if (port->pkt_len)
+		rte_free(port->pkt_len);
+	if (port->pkts)
+		rte_free(port->pkts);
+	if (port->pkt_buff)
+		rte_free(port->pkt_buff);
+
+	return status;
+}
+
+#else
+static int
+pcap_source_load(__rte_unused struct rte_port_source_params *p,
+		struct rte_port_source *port,
+		__rte_unused int socket_id)
+{
+	port->pkt_buff = NULL;
+	port->pkt_len = NULL;
+	port->pkts = NULL;
+	port->pkt_index = 0;
+
+	return -ENOTSUP;
+}
+#endif /* RTE_PORT_PCAP */
+
+#endif
+
 static void *
 rte_port_source_create(void *params, int socket_id)
 {
@@ -86,17 +262,66 @@ rte_port_source_create(void *params, int socket_id)
 	/* Initialization */
 	port->mempool = (struct rte_mempool *) p->mempool;
 
+#ifdef RTE_NEXT_ABI
+
+	/* pcap file load and initialization */
+	int status = pcap_source_load(p, port, socket_id);
+
+	if (status == 0) {
+		if (port->pkt_buff != NULL) {
+			RTE_LOG(INFO, PORT, "Successfully load pcap file "
+				"'%s' with %u pkts\n",
+				p->file_name, port->n_pkts);
+		}
+	} else if (status != -ENOTSUP) {
+		/* ENOTSUP is not treated as error */
+		switch (status) {
+		case -ENOENT:
+			RTE_LOG(ERR, PORT, "%s: Failed to open pcap file "
+				"'%s' for reading\n",
+				__func__, p->file_name);
+			break;
+		case -ENOMEM:
+			RTE_LOG(ERR, PORT, "%s: Not enough memory\n",
+				__func__);
+			break;
+		default:
+			RTE_LOG(ERR, PORT, "%s: Failed to enable PCAP "
+				"support for unknown reason\n",
+				__func__);
+			break;
+		}
+
+		rte_free(port);
+		port = NULL;
+	}
+
+#endif
+
 	return port;
 }
 
 static int
 rte_port_source_free(void *port)
 {
+	struct rte_port_source *p =
+			(struct rte_port_source *)port;
+
 	/* Check input parameters */
-	if (port == NULL)
+	if (p == NULL)
 		return 0;
 
-	rte_free(port);
+#ifdef RTE_NEXT_ABI
+
+	if (p->pkt_len)
+		rte_free(p->pkt_len);
+	if (p->pkts)
+		rte_free(p->pkts);
+	if (p->pkt_buff)
+		rte_free(p->pkt_buff);
+#endif
+
+	rte_free(p);
 
 	return 0;
 }
@@ -115,6 +340,26 @@ rte_port_source_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts)
 		rte_pktmbuf_reset(pkts[i]);
 	}
 
+#ifdef RTE_NEXT_ABI
+
+	if (p->pkt_buff != NULL) {
+		for (i = 0; i < n_pkts; i++) {
+			uint8_t *pkt_data = rte_pktmbuf_mtod(pkts[i],
+				uint8_t *);
+
+			rte_memcpy(pkt_data, p->pkts[p->pkt_index],
+					p->pkt_len[p->pkt_index]);
+			pkts[i]->data_len = p->pkt_len[p->pkt_index];
+			pkts[i]->pkt_len = pkts[i]->data_len;
+
+			p->pkt_index++;
+			if (p->pkt_index >= p->n_pkts)
+				p->pkt_index = 0;
+		}
+	}
+
+#endif
+
 	RTE_PORT_SOURCE_STATS_PKTS_IN_ADD(p, n_pkts);
 
 	return n_pkts;
diff --git a/lib/librte_port/rte_port_source_sink.h b/lib/librte_port/rte_port_source_sink.h
index 0f9be79..522d10d 100644
--- a/lib/librte_port/rte_port_source_sink.h
+++ b/lib/librte_port/rte_port_source_sink.h
@@ -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
@@ -53,6 +53,17 @@ extern "C" {
 struct rte_port_source_params {
 	/** Pre-initialized buffer pool */
 	struct rte_mempool *mempool;
+#ifdef RTE_NEXT_ABI
+
+	/** The full path of the pcap file to read packets from */
+	char *file_name;
+	/** The number of bytes to be read from each packet in the
+	 *  pcap file. If this value is 0, the whole packet is read;
+	 *  if it is bigger than packet size, the generated packets
+	 *  will contain the whole packet */
+	uint32_t n_bytes_per_pkt;
+
+#endif
 };
 
 /** source port operations */
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 30a91ad..a5a7b1c 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -95,6 +95,11 @@ endif
 # The static libraries do not know their dependencies.
 # So linking with static library requires explicit dependencies.
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
+
+ifeq ($(CONFIG_RTE_NEXT_ABI),y)
+_LDLIBS-$(CONFIG_RTE_PORT_PCAP)             += -lpcap
+endif
+
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP)       += -lpcap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD)      += -lz
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -libverbs
-- 
2.5.0

  reply	other threads:[~2016-03-11 17:08 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-17 11:11 [dpdk-dev] [PATCH v2 0/4] Add PCAP support to source and sink port Fan Zhang
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 1/4] lib/librte_port: add PCAP file support to source port Fan Zhang
2016-03-07 11:17   ` Thomas Monjalon
2016-03-08  8:36     ` Dumitrescu, Cristian
2016-03-08  9:06       ` Panu Matilainen
2016-03-08 10:14       ` Thomas Monjalon
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 2/4] example/ip_pipeline: add PCAP file support Fan Zhang
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 3/4] lib/librte_port: add packet dumping to PCAP file support in sink port Fan Zhang
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 4/4] examples/ip_pipeline: add packets dumping to PCAP file support Fan Zhang
2016-03-09 16:07 ` [dpdk-dev] [PATCH v3 0/4] Add PCAP support to source and sink port Fan Zhang
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 1/4] lib/librte_port: add PCAP file support to source port Fan Zhang
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 2/4] example/ip_pipeline: add PCAP file support Fan Zhang
2016-03-11 11:10     ` Thomas Monjalon
2016-03-25 12:00       ` Zhang, Roy Fan
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 3/4] lib/librte_port: add packet dumping to PCAP file support in sink port Fan Zhang
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 4/4] examples/ip_pipeline: add packets dumping to PCAP file support Fan Zhang
2016-03-11 17:08   ` [dpdk-dev] [PATCH v4 0/4] Add PCAP support to source and sink port Fan Zhang
2016-03-11 17:08     ` Fan Zhang [this message]
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 2/4] example/ip_pipeline: add PCAP file support Fan Zhang
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 3/4] lib/librte_port: add packet dumping to PCAP file support in sink port Fan Zhang
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 4/4] examples/ip_pipeline: add packets dumping to PCAP file support Fan Zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1457716090-26742-2-git-send-email-roy.fan.zhang@intel.com \
    --to=roy.fan.zhang@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).