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
next prev 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 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).