All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>
Subject: [dpdk-dev] [RFC 7/8] pcapng: add new library for writing pcapng files
Date: Mon,  7 Oct 2019 09:52:31 -0700	[thread overview]
Message-ID: <20191007165232.14535-8-stephen@networkplumber.org> (raw)
In-Reply-To: <20191007165232.14535-1-stephen@networkplumber.org>

Simple library for formatting pcapng files used by wireshark
and other programs.

See PCAP next generation file format specification
https://github.com/pcapng/pcapng

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 config/common_base                       |   6 +
 lib/Makefile                             |   2 +
 lib/librte_pcapng/Makefile               |  22 ++
 lib/librte_pcapng/meson.build            |  10 +
 lib/librte_pcapng/pcapng_proto.h         | 112 ++++++
 lib/librte_pcapng/rte_pcapng.c           | 449 +++++++++++++++++++++++
 lib/librte_pcapng/rte_pcapng.h           | 132 +++++++
 lib/librte_pcapng/rte_pcapng_version.map |  12 +
 lib/meson.build                          |   2 +-
 mk/rte.app.mk                            |   1 +
 10 files changed, 747 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_pcapng/Makefile
 create mode 100644 lib/librte_pcapng/meson.build
 create mode 100644 lib/librte_pcapng/pcapng_proto.h
 create mode 100644 lib/librte_pcapng/rte_pcapng.c
 create mode 100644 lib/librte_pcapng/rte_pcapng.h
 create mode 100644 lib/librte_pcapng/rte_pcapng_version.map

diff --git a/config/common_base b/config/common_base
index 8ef75c2039a2..0ccfcfae377d 100644
--- a/config/common_base
+++ b/config/common_base
@@ -998,6 +998,12 @@ CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
 #
 CONFIG_RTE_LIBRTE_PDUMP=y
 
+#
+# Compile the pcapng library
+#
+CONFIG_RTE_LIBRTE_PCAPNG=y
+
+#
 #
 # Compile vhost user library
 #
diff --git a/lib/Makefile b/lib/Makefile
index 41c463d92139..47786030fade 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -102,6 +102,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DEPDIRS-librte_reorder := librte_eal librte_mempool librte_mbuf
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DEPDIRS-librte_pdump := librte_eal librte_mempool librte_mbuf librte_ethdev
+DIRS-$(CONFIG_RTE_LIBRTE_PCAPNG) += librte_pcapng
+DEPDIRS-librte_pcapng := librte_eal librte_mbuf librte_ethdev librte_net
 DIRS-$(CONFIG_RTE_LIBRTE_GSO) += librte_gso
 DEPDIRS-librte_gso := librte_eal librte_mbuf librte_ethdev librte_net
 DEPDIRS-librte_gso += librte_mempool
diff --git a/lib/librte_pcapng/Makefile b/lib/librte_pcapng/Makefile
new file mode 100644
index 000000000000..eaf3e85e3ad2
--- /dev/null
+++ b/lib/librte_pcapng/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Microsoft Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_pcapng.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
+EXPORT_MAP := rte_pcapng_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_PCAPNG) := rte_pcapng.c
+
+# install includes
+SYMLINK-$(CONFIG_RTE_LIBRTE_MBUF)-include := rte_pcapng.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pcapng/meson.build b/lib/librte_pcapng/meson.build
new file mode 100644
index 000000000000..7904b4759b00
--- /dev/null
+++ b/lib/librte_pcapng/meson.build
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Microsoft Corporation
+
+version = 1
+sources = files('rte_pcapng.c')
+headers = files('rte_pcapng.h')
+
+allow_experimental_apis = true
+
+deps += ['ethdev']
diff --git a/lib/librte_pcapng/pcapng_proto.h b/lib/librte_pcapng/pcapng_proto.h
new file mode 100644
index 000000000000..8f35bc31d979
--- /dev/null
+++ b/lib/librte_pcapng/pcapng_proto.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Microsoft Corporation
+ *
+ * Pcapng protocol data structures
+ *  from Draft RFC
+ */
+
+enum pcapng_block_types {
+	PCAPNG_INTERFACE_BLOCK		= 1,
+	PCAPNG_PACKET_BLOCK,		/* Obsolete */
+	PCAPNG_SIMPLE_PACKET_BLOCK,
+	PCAPNG_NAME_RESOLUTION_BLOCK,
+	PCAPNG_INTERFACE_STATS_BLOCK,
+	PCAPNG_ENHANCED_PACKET_BLOCK,
+
+	PCAPNG_SECTION_BLOCK		= 0x0A0D0D0A,
+};
+
+struct pcapng_option {
+	uint16_t code;
+	uint16_t length;
+	uint8_t data[];
+};
+
+#define PCAPNG_BYTE_ORDER_MAGIC 0x1A2B3C4D
+#define PCAPNG_MAJOR_VERS 1
+#define PCAPNG_MINOR_VERS 0
+
+enum pcapng_opt {
+	PCAPNG_OPT_END	= 0,
+	PCAPNG_OPT_COMMENT = 1,
+};
+
+struct pcapng_section_header {
+	uint32_t block_type;
+	uint32_t block_length;
+	uint32_t byte_order_magic;
+	uint16_t major_version;
+	uint16_t minor_version;
+	uint64_t section_length;
+};
+
+enum pcapng_section_opt {
+	PCAPNG_SHB_HARDWARE = 2,
+	PCAPNG_SHB_OS	    = 3,
+	PCAPNG_SHB_USERAPPL = 4,
+};
+
+struct pcapng_interface_block {
+	uint32_t block_type;	/* 1 */
+	uint32_t block_length;
+	uint16_t link_type;
+	uint16_t reserved;
+	uint32_t snap_len;
+};
+
+enum pcapng_interface_options {
+	PCAPNG_IFB_NAME	 = 2,
+	PCAPNG_IFB_DESCRIPTION,
+	PCAPNG_IFB_IPV4ADDR,
+	PCAPNG_IFB_IPV6ADDR,
+	PCAPNG_IFB_MACADDR,
+	PCAPNG_IFB_EUIADDR,
+	PCAPNG_IFB_SPEED,
+	PCAPNG_IFB_TSRESOL,
+	PCAPNG_IFB_TZONE,
+	PCAPNG_IFB_FILTER,
+	PCAPNG_IFB_OS,
+	PCAPNG_IFB_FCSLEN,
+	PCAPNG_IFB_TSOFFSET,
+	PCAPNG_IFB_HARDWARE,
+};
+
+struct pcapng_enhance_packet_block {
+	uint32_t block_type;	/* 6 */
+	uint32_t block_length;
+	uint32_t interface_id;
+	uint32_t timestamp_hi;
+	uint32_t timestamp_lo;
+	uint32_t capture_length;
+	uint32_t original_length;
+};
+
+enum pcapng_epb_options {
+	PCAPNG_EPB_FLAGS = 2,
+	PCAPNG_EPB_HASH,
+	PCAPNG_EPB_DROPS
+};
+
+struct pcapng_simple_packet {
+	uint32_t block_type;	/* 3 */
+	uint32_t block_length;
+	uint32_t packet_length;
+};
+
+struct pcapng_statistics {
+	uint32_t block_type;	/* 5 */
+	uint32_t block_length;
+	uint32_t interface_id;
+	uint32_t timestamp_hi;
+	uint32_t timestamp_lo;
+};
+
+enum pcapng_isb_options {
+	PCAPNG_ISB_STARTTIME = 2,
+	PCAPNG_ISB_ENDTIME,
+	PCAPNG_ISB_IFRECV,
+	PCAPNG_ISB_IFDROP,
+	PCAPNG_ISB_FILTERACCEPT,
+	PCAPNG_ISB_OSDROP,
+	PCAPNG_ISB_USRDELIV
+};
diff --git a/lib/librte_pcapng/rte_pcapng.c b/lib/librte_pcapng/rte_pcapng.c
new file mode 100644
index 000000000000..2beb3c24f882
--- /dev/null
+++ b/lib/librte_pcapng/rte_pcapng.c
@@ -0,0 +1,449 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Microsoft Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/utsname.h>
+#include <net/if.h>
+
+#include <rte_config.h>
+#include <rte_ethdev.h>
+#include <rte_mbuf.h>
+#include <rte_cycles.h>
+#include <rte_version.h>
+#include <rte_pcapng.h>
+#include <rte_malloc.h>
+
+#include "pcapng_proto.h"
+
+/* conversion from DPDK speed to PCAPNG */
+#define PCAPNG_MBPS_SPEED 1000000ull
+
+#define PCAPNG_MAX_COMMENT 256
+
+#define NS_PER_US	1000ul
+#define US_PER_SEC	1000ul
+#define NS_PER_SEC	(NS_PER_US * US_PER_SEC)
+
+/* Private state for the library */
+struct rte_pcapng {
+	int  outfd;		/* output file */
+
+	uint64_t tsc_t0;	/* TSC cycles when opened */
+	uint32_t tsc_per_us;	/* TSC cycles per microsecond */
+	uint64_t tsc_offset;	/* nanosecond since 1970 */
+
+	uint32_t next_index;
+	uint32_t port_index[RTE_MAX_ETHPORTS];
+};
+
+/* length of option including padding */
+static size_t pcapng_optlen(uint16_t len)
+{
+	return RTE_ALIGN(sizeof(struct pcapng_option) + len,
+			 sizeof(uint32_t));
+}
+
+/* build TLV option and return location of next */
+static struct pcapng_option *
+pcapng_add_option(struct pcapng_option *popt, uint16_t code,
+		  const void *data, uint16_t len)
+{
+	popt->code = code;
+	popt->length = len;
+	memcpy(popt->data, data, len);
+
+	return (struct pcapng_option *)((uint8_t *)popt + pcapng_optlen(len));
+}
+
+/*
+ * Convert from DPDK timestamp (tsc cycles)
+ * to what Pcapng uses (nanosecond since 1 Jan 1970 UTC)
+ */
+static inline uint64_t tsc_to_timestamp(const rte_pcapng_t *self,
+					uint64_t tsc)
+{
+	uint64_t ticks = tsc - self->tsc_t0;
+
+	return (ticks * NS_PER_US) / self->tsc_per_us + self->tsc_offset;
+}
+
+/*
+ * Write required initial section header describing the capture
+ */
+static int
+write_section_block(rte_pcapng_t *self,
+		    const char *os, const char *hw,
+		    const char *app, const char *comment)
+{
+	struct pcapng_section_header *hdr;
+	struct pcapng_option *opt;
+	void *buf;
+	size_t len;
+	ssize_t cc;
+
+	len = sizeof(*hdr);
+	if (hw)
+		len += pcapng_optlen(strlen(hw));
+	if (os)
+		len += pcapng_optlen(strlen(os));
+	if (app)
+		len += pcapng_optlen(strlen(app));
+	if (comment)
+		len += pcapng_optlen(strlen(comment));
+
+	len += pcapng_optlen(0);
+	len += sizeof(uint32_t);
+
+	buf = calloc(1, len);
+	if (!buf)
+		return -1;
+
+	hdr = (struct pcapng_section_header *)buf;
+	*hdr = (struct pcapng_section_header) {
+		.block_type = PCAPNG_SECTION_BLOCK,
+		.block_length = len,
+		.byte_order_magic = PCAPNG_BYTE_ORDER_MAGIC,
+		.major_version = PCAPNG_MAJOR_VERS,
+		.minor_version = PCAPNG_MINOR_VERS,
+		.section_length = UINT64_MAX,
+	};
+	hdr->block_length = len;
+
+	opt = (struct pcapng_option *)(hdr + 1);
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,
+					comment, strlen(comment));
+	if (hw)
+		opt = pcapng_add_option(opt, PCAPNG_SHB_HARDWARE,
+					hw, strlen(hw));
+	if (os)
+		opt = pcapng_add_option(opt, PCAPNG_SHB_OS,
+					os, strlen(os));
+	if (app)
+		opt = pcapng_add_option(opt, PCAPNG_SHB_USERAPPL,
+					app, strlen(app));
+
+	opt = pcapng_add_option(opt, PCAPNG_OPT_END, NULL, 0);
+	/* clone block_length after option */
+	memcpy(opt, &hdr->block_length, sizeof(uint32_t));
+
+	cc = write(self->outfd, buf, len);
+	free(buf);
+
+	return cc;
+}
+
+static int
+capture_header(rte_pcapng_t *self,
+	       const char *os, const char *hw,
+	       const char *app, const char *comment)
+{
+	char osbuf[256];
+
+	if (app == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (os == NULL) {
+		struct utsname uts;
+
+		uname(&uts);
+		snprintf(osbuf, sizeof(osbuf),
+			 "%s %s", uts.sysname, uts.release);
+		os = osbuf;
+	}
+
+	if (hw == NULL)
+		hw = rte_version();
+
+	if (write_section_block(self, os, hw, app, comment) > 0)
+		return 0;
+	else
+		return -1;
+}
+
+static ssize_t
+write_interface_block(rte_pcapng_t *self, const char *if_name,
+		      uint64_t if_speed, const uint8_t *mac_addr,
+		      const char *if_hw, const char *comment)
+{
+	struct pcapng_interface_block *hdr;
+	struct pcapng_option *opt;
+	const uint8_t tsresol = 9;	/* nanosecond resolution */
+	size_t len = sizeof(*hdr);
+	ssize_t cc;
+	void *buf;
+
+	len += pcapng_optlen(sizeof(tsresol));
+	if (if_name)
+		len += pcapng_optlen(strlen(if_name));
+	if (mac_addr)
+		len += pcapng_optlen(6);
+	if (if_speed)
+		len += pcapng_optlen(sizeof(uint64_t));
+	if (if_hw)
+		len += pcapng_optlen(strlen(if_hw));
+	if (comment)
+		len += pcapng_optlen(strlen(comment));
+
+	len += pcapng_optlen(0);
+	len += sizeof(uint32_t);
+	buf = calloc(1, len);
+	if (!buf)
+		return -ENOMEM;
+
+	hdr = (struct pcapng_interface_block *)buf;
+	hdr->block_type = PCAPNG_INTERFACE_BLOCK;
+	hdr->link_type = 1;	/* Ethernet */
+	hdr->block_length = len;
+
+	opt = (struct pcapng_option *)(hdr + 1);
+	if (if_name)
+		opt = pcapng_add_option(opt, PCAPNG_IFB_NAME,
+					 if_name, strlen(if_name));
+	if (mac_addr)
+		opt = pcapng_add_option(opt, PCAPNG_IFB_MACADDR,
+					mac_addr, RTE_ETHER_ADDR_LEN);
+	if (if_speed)
+		opt = pcapng_add_option(opt, PCAPNG_IFB_SPEED,
+					 &if_speed, sizeof(uint64_t));
+	opt = pcapng_add_option(opt, PCAPNG_IFB_TSRESOL,
+				&tsresol, sizeof(tsresol));
+	if (if_hw)
+		opt = pcapng_add_option(opt, PCAPNG_IFB_HARDWARE,
+					 if_hw, strlen(if_hw));
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,
+					comment, strlen(comment));
+
+	opt = pcapng_add_option(opt, PCAPNG_OPT_END, NULL, 0);
+
+	memcpy(opt, &hdr->block_length, sizeof(uint32_t));
+	cc = write(self->outfd, buf, len);
+	free(buf);
+
+	return cc;
+}
+
+int
+rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port,
+			 const char *comment, uint32_t flags)
+{
+	struct rte_eth_dev_info dev_info;
+	struct rte_ether_addr macaddr;
+	const struct rte_device *dev;
+	struct rte_eth_link link;
+	char ifname[IF_NAMESIZE];
+	char ifhw[256];
+	uint64_t speed = 0;
+	int cc;
+
+	if (flags != 0) {
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	rte_eth_dev_info_get(port, &dev_info);
+
+	/* make something like an interface name */
+	if (if_indextoname(dev_info.if_index, ifname) == NULL)
+		snprintf(ifname, IF_NAMESIZE, "dpdk:%u", port);
+
+	/* make a useful device hardware string */
+	dev = dev_info.device;
+	if (dev)
+		snprintf(ifhw, sizeof(ifhw),
+			 "%s-%s", dev->bus->name, dev->name);
+
+	/* DPDK reports in units of Mbps */
+	rte_eth_link_get(port, &link);
+	if (link.link_status == ETH_LINK_UP)
+		speed = link.link_speed * PCAPNG_MBPS_SPEED;
+
+	rte_eth_macaddr_get(port, &macaddr);
+
+	cc = write_interface_block(self, ifname, speed,
+				   macaddr.addr_bytes,
+				   dev ? ifhw : NULL,
+				   comment);
+	if (cc < 0) {
+		rte_errno = errno;
+		return -1;
+	}
+
+	self->port_index[port] = self->next_index++;
+	return 0;
+}
+
+/* Create new pcapng writer handle */
+rte_pcapng_t *
+rte_pcapng_fdopen(int fd,
+		  const char *osname, const char *hardware,
+		  const char *appname, const char *comment,
+		  uint32_t flags)
+{
+	rte_pcapng_t *self;
+	struct timeval tv;
+
+	if (flags != 0) {
+		rte_errno = EINVAL;
+		return NULL;
+	}
+
+	self = rte_zmalloc("pcapng", sizeof(*self), 0);
+	if (!self) {
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
+	self->outfd = fd;
+
+	/* compute clock offsets */
+	self->tsc_t0 = rte_rdtsc();
+	self->tsc_per_us = rte_get_tsc_hz() / US_PER_SEC;
+	gettimeofday(&tv, NULL);
+	self->tsc_offset = (tv.tv_sec * US_PER_SEC + tv.tv_usec) * NS_PER_US;
+
+	if (capture_header(self, osname, hardware,
+			   appname, comment) < 0)
+		goto error;
+
+	return self;
+
+error:
+	close(self->outfd);
+	rte_errno = errno;
+	rte_free(self);
+	return NULL;
+}
+
+void
+rte_pcapng_close(rte_pcapng_t *self)
+{
+	close(self->outfd);
+	rte_free(self);
+}
+
+int
+rte_pcapng_dump_packet(rte_pcapng_t *self, uint16_t port,
+		       const struct rte_mbuf *m,
+		       enum rte_pcapng_direction dir,
+		       const char *comment)
+{
+	struct pcapng_enhance_packet_block hdr;
+	uint32_t snap_len, padded_len, pad_bytes;
+	uint64_t ts = tsc_to_timestamp(self, m->timestamp);
+	static uint64_t zero_pad;
+	struct pcapng_option *opt;
+	uint32_t flags = dir;
+	uint32_t options[512];
+	uint16_t i;
+	struct iovec iov[m->nb_segs + 4];
+	size_t len, optlen;
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+#endif
+	/* only handle single segment mbuf */
+	snap_len = rte_pktmbuf_data_len(m);
+	padded_len = RTE_ALIGN(snap_len, sizeof(uint32_t));
+	pad_bytes = padded_len - snap_len;
+
+	len = sizeof(hdr) + padded_len + sizeof(uint32_t);
+	opt = (struct pcapng_option *)options;
+
+	opt = pcapng_add_option(opt, PCAPNG_EPB_FLAGS,
+				&flags, sizeof(flags));
+
+	if (comment)
+		opt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,
+					strnlen(comment, PCAPNG_MAX_COMMENT));
+
+	optlen = (char *)opt - (char *)options;
+	len += optlen;
+
+	hdr.block_type = PCAPNG_ENHANCED_PACKET_BLOCK;
+	hdr.block_length = len;
+
+	hdr.interface_id = self->port_index[port];
+	hdr.timestamp_hi = ts >> 32;
+	hdr.timestamp_lo = (uint32_t)ts;
+	hdr.capture_length = snap_len;
+	hdr.original_length = rte_pktmbuf_pkt_len(m);
+
+	iov[0].iov_base = &hdr;
+	iov[0].iov_len = sizeof(hdr);
+
+	for (i = 1; m; ++i, m = m->next) {
+		iov[i].iov_base = rte_pktmbuf_mtod(m, void *);
+		iov[i].iov_len = rte_pktmbuf_data_len(m);
+	}
+
+	if (pad_bytes > 0) {
+		iov[i].iov_base = &zero_pad;
+		iov[i].iov_len = pad_bytes;
+		++i;
+	}
+
+	iov[i].iov_base = options;
+	iov[i].iov_len = optlen;
+	++i;
+
+	iov[i].iov_base = &hdr.block_length;
+	iov[i].iov_len = sizeof(uint32_t);
+	++i;
+
+	if (unlikely(writev(self->outfd, iov, i) < 0)) {
+		rte_errno = errno;
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+rte_pcapng_dump_tx(rte_pcapng_t *out, uint16_t port,
+		   struct rte_mbuf *pkts[], uint32_t nb_pkts)
+{
+	uint32_t i;
+	int r = 0;
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *m = pkts[i];
+
+		r = rte_pcapng_dump_packet(out, port, m,
+					   RTE_PCAPNG_DIR_OUTBOUND, NULL);
+		if (unlikely(r < 0))
+			break;
+	}
+
+	return r;
+}
+
+int
+rte_pcapng_dump_rx(rte_pcapng_t *out,
+		   struct rte_mbuf *pkts[], uint32_t nb_pkts)
+{
+	uint32_t i;
+	int r = 0;
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *m = pkts[i];
+
+		r = rte_pcapng_dump_packet(out, m->port, m,
+					   RTE_PCAPNG_DIR_INBOUND, NULL);
+		if (unlikely(r < 0))
+			break;
+	}
+	return r;
+}
diff --git a/lib/librte_pcapng/rte_pcapng.h b/lib/librte_pcapng/rte_pcapng.h
new file mode 100644
index 000000000000..23763c6882c8
--- /dev/null
+++ b/lib/librte_pcapng/rte_pcapng.h
@@ -0,0 +1,132 @@
+/*
+ * Simple library to write files in Pcap-ng format.
+ * Copyright(c) 2019 Microsoft Corporation
+ * All rights reserved.
+ */
+
+
+/* Handle used for functions in this library. */
+typedef struct rte_pcapng rte_pcapng_t;
+
+/**
+ * Open new packet capture file
+ *
+ * @param fd
+ *   file descriptor
+ * @param osname
+ *   Operating system name.
+ *   If NULL will be filled in based on result of utsname.
+ * @param hardware
+ *   Hardware information.
+ *   If NULL will be filled in with DPDK version.
+ * @param appname
+ *   Applicaton name.
+ * @param comment
+ *   Comment for the file (optional can be NULL)
+ * @param flags
+ *   Options for capture (reserved must be 0)
+ * @return
+ *   handle to library, or NULL in case of error (and rte_errno is set).
+ */
+__rte_experimental
+rte_pcapng_t *
+rte_pcapng_fdopen(int fd,
+		  const char *osname, const char *hardware,
+		  const char *appname, const char *comment,
+		  uint32_t flags);
+
+
+enum rte_pcapng_direction {
+	RTE_PCAPNG_DIR_UNKNOWN = 0,
+	RTE_PCAPNG_DIR_INBOUND = 1,
+	RTE_PCAPNG_DIR_OUTBOUND = 2,
+};
+
+/**
+ * Add interface to capture file
+ * This must be done after opening and before dumping any packets.
+ * Call once for each port being followed.
+ *
+ * @param out
+ *  The handle to the packet capture file
+ * @param port
+ *  The Ethernet port being captured.
+ * @param comment
+ *   Comment for the file (optional can be NULL)
+ * @param flags
+ *   Options for capture (reserved must be 0)
+ * @return
+ *  0 on success, -1 on failure (and rte_errno is set).
+ */
+__rte_experimental
+int
+rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port,
+			 const char *comment, uint32_t flags);
+
+/**
+ * Record packet in capture file
+ *
+ * @param out
+ *  The handle to the packet capture file
+ * @param port
+ *  The Ethernet port on which the packet is being sent.
+ * @param m
+ *  The packet to record
+ * @param dir
+ *  Direction in/out or unknown
+ * @param comment
+ *  Comment to add to record
+ * @return
+ *  0 on success, -1 on failure
+ */
+__rte_experimental
+int
+rte_pcapng_dump_packet(rte_pcapng_t *self, uint16_t port,
+		       const struct rte_mbuf *m,
+		       enum rte_pcapng_direction dir,
+		       const char *comment);
+/**
+ * Dump packets to be transmitted.
+ *
+ * @param out
+ *  The handle to the packet capture file
+ * @param port_id
+ *  The Ethernet port on which the packet is being sent.
+ * @param pkts
+ *  The packets to be recorded.
+ * @param nb_pkts
+ *  The number of packets in the burst pointed to by "pkts".
+ * @return
+ *  0 on success, -1 on failure (and rte_errno is set).
+ */
+__rte_experimental
+int
+rte_pcapng_dump_tx(rte_pcapng_t *out, uint16_t port,
+		   struct rte_mbuf *pkts[], uint32_t nb_pkts);
+
+/**
+ * Dump a packets received.
+ *
+ * @param out
+ *  The handle to the packet capture file
+ * @param pkts
+ *  The packets to be recorded.
+ * @param nb_pkts
+ *  The number of packets in the burst pointed to by "pkts".
+ * @return
+ *  0 on success, -1 on failure (and rte_errno is set).
+ */
+__rte_experimental
+int
+rte_pcapng_dump_rx(rte_pcapng_t *out,
+		   struct rte_mbuf *pkts[], uint32_t nb_pkts);
+
+/**
+ * Close capture file
+ *
+ * @param self
+ *  handle to library
+ */
+__rte_experimental
+void
+rte_pcapng_close(rte_pcapng_t *self);
diff --git a/lib/librte_pcapng/rte_pcapng_version.map b/lib/librte_pcapng/rte_pcapng_version.map
new file mode 100644
index 000000000000..eb8ae2b50984
--- /dev/null
+++ b/lib/librte_pcapng/rte_pcapng_version.map
@@ -0,0 +1,12 @@
+EXPERIMENTAL {
+	global:
+
+	rte_pcapng_fdopen;
+	rte_pcapng_add_interface;
+	rte_pcapng_dump_packet;
+	rte_pcapng_dump_tx;
+	rte_pcapng_dump_rx;
+	rte_pcapng_close;
+
+	local: *;
+};
diff --git a/lib/meson.build b/lib/meson.build
index e5ff83893489..cb07e38d8b58 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -21,7 +21,7 @@ libraries = [
 	'distributor', 'efd', 'eventdev',
 	'gro', 'gso', 'ip_frag', 'jobstats',
 	'kni', 'latencystats', 'lpm', 'member',
-	'power', 'pdump', 'rawdev',
+	'power', 'pdump', 'rawdev', 'pcapng',
 	'rcu', 'reorder', 'sched', 'security', 'stack', 'vhost',
 	# ipsec lib depends on net, crypto and security
 	'ipsec',
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index ba5c39e01957..b50b74ed6c99 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -42,6 +42,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT)           += -lrte_port
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT)           += --no-whole-archive
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PDUMP)          += -lrte_pdump
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PCAPNG)         += -lrte_pcapng
 _LDLIBS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR)    += -lrte_distributor
 _LDLIBS-$(CONFIG_RTE_LIBRTE_IP_FRAG)        += -lrte_ip_frag
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METER)          += -lrte_meter
-- 
2.20.1


  parent reply	other threads:[~2019-10-07 16:53 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-07 16:52 [dpdk-dev] [RFC 0/8] Packet Capture enhancements Stephen Hemminger
2019-10-07 16:52 ` [dpdk-dev] [RFC 1/8] pdump: use new pktmbuf copy function Stephen Hemminger
2019-10-07 16:52 ` [dpdk-dev] [RFC 2/8] pdump: use dynamic logtype Stephen Hemminger
2019-10-07 16:52 ` [dpdk-dev] [RFC 3/8] pdump: tag copied mbuf with port Stephen Hemminger
2019-10-07 16:52 ` [dpdk-dev] [RFC 4/8] pdump: stamp packets with current timestamp Stephen Hemminger
2019-10-07 16:52 ` [dpdk-dev] [RFC 5/8] pdump: add classic BPF filtering Stephen Hemminger
2019-10-07 17:07   ` Jerin Jacob
2019-10-07 17:33     ` Stephen Hemminger
2019-10-07 19:33       ` Jerin Jacob
2019-10-07 21:45         ` Stephen Hemminger
2019-10-08  3:47           ` Jerin Jacob
2019-10-08  4:01             ` Stephen Hemminger
2019-10-08  4:15               ` Jerin Jacob
2019-10-08  4:22                 ` Stephen Hemminger
2019-10-08 21:08                   ` Morten Brørup
2019-10-09  8:21                     ` Ananyev, Konstantin
2019-10-09 14:59                       ` Stephen Hemminger
2019-10-07 16:52 ` [dpdk-dev] [RFC 6/8] pdump: add packet header truncation Stephen Hemminger
2019-10-07 16:52 ` Stephen Hemminger [this message]
2019-10-07 16:52 ` [dpdk-dev] [RFC 8/8] app/capture: add packet capture using pcapng Stephen Hemminger

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=20191007165232.14535-8-stephen@networkplumber.org \
    --to=stephen@networkplumber.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.