get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/60651/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 60651,
    "url": "https://patches.dpdk.org/api/patches/60651/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20191007165232.14535-8-stephen@networkplumber.org/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20191007165232.14535-8-stephen@networkplumber.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20191007165232.14535-8-stephen@networkplumber.org",
    "date": "2019-10-07T16:52:31",
    "name": "[RFC,7/8] pcapng: add new library for writing pcapng files",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "3f5560e027161c85c0c050a81b07768a112d5e5c",
    "submitter": {
        "id": 27,
        "url": "https://patches.dpdk.org/api/people/27/?format=api",
        "name": "Stephen Hemminger",
        "email": "stephen@networkplumber.org"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20191007165232.14535-8-stephen@networkplumber.org/mbox/",
    "series": [
        {
            "id": 6728,
            "url": "https://patches.dpdk.org/api/series/6728/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=6728",
            "date": "2019-10-07T16:52:24",
            "name": "Packet Capture enhancements",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/6728/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/60651/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/60651/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id B61FE1D37D;\n\tMon,  7 Oct 2019 18:52:58 +0200 (CEST)",
            "from mail-pf1-f196.google.com (mail-pf1-f196.google.com\n\t[209.85.210.196]) by dpdk.org (Postfix) with ESMTP id 204641D159\n\tfor <dev@dpdk.org>; Mon,  7 Oct 2019 18:52:50 +0200 (CEST)",
            "by mail-pf1-f196.google.com with SMTP id b128so9054134pfa.1\n\tfor <dev@dpdk.org>; Mon, 07 Oct 2019 09:52:50 -0700 (PDT)",
            "from hermes.lan (204-195-22-127.wavecable.com. [204.195.22.127])\n\tby smtp.gmail.com with ESMTPSA id\n\tw5sm15920979pfn.96.2019.10.07.09.52.47\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 07 Oct 2019 09:52:47 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=networkplumber-org.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=QGhlsAZUTXIfdCmzS6vHhtVgwqGoDe7ZxIOrTe28vBw=;\n\tb=bOr8Bufxlyb/nQ86ugFwuofk2ADUFjfyReS0pbHp9qk7MfPR3sfQrqUJAwnAqrX0OB\n\tanQUQDOVBsPG0uqsmaiWDT80mtpUU2yVn9E7IPO0Bc6FsCHPpgrn0pJ++iXo045USpcf\n\tjgfzWm9+9ZOgwjeGkwq67dpiRGVl1Q0Cbcu/2KKx2BZ6gcRBmAtjqfzNq7TN9WTZ9lYb\n\tRSAsfKc4Kz/YNRzTn9UIj1C9Hm4ohSmNx8nzUh6dldeP9djAxOwUmwWzmVrHLz9yjUMS\n\tk1Ld7VHXontsnifXWkty1kpqVdAVvKx8q3TFHiioMOOsxW9ugFFEBIXpi0PtQgAGduFq\n\th4Ow==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=QGhlsAZUTXIfdCmzS6vHhtVgwqGoDe7ZxIOrTe28vBw=;\n\tb=rszpDMg5q6sjQdoBk0SYhBVahSt8XCLqMemUctABm3JJroz0oIwySMFwZcIUonJQGC\n\tdFXOcWDydW6bhBQoev5bBvxYYcd1n4H9wPZB8F3PwIR9/kCZDH9hZojtB5IFv67NXPkM\n\t9JppuPW4rWr9aRr1XLIp+ZFlqgD5BQ24oOM0ijOdLE4Z1lbFprjOBRoEWa19x3/swE6G\n\txARKTSxVIQyLXGfP9Y54DteUFyBTCRJPP40mHPpgpwrPOSLiTQTYFKUCPuN2gS3jwWto\n\tAf/reHjjKxgQ5zzZHJ8BR4hu/aaQruB/CpiFOYxwZfc3vCnzQCryl0Q5VYrRj7GpX/lg\n\tu6yg==",
        "X-Gm-Message-State": "APjAAAWrDrdf10CRa6qc/FUfGYQLTdpIJ6ht+MT5hY1qQ/emFP2+9jc2\n\tCEagFtVtg47zGtxCEAO2Jua1zYdvqXor8Q==",
        "X-Google-Smtp-Source": "APXvYqx6K6/BijNJUlptzNeH4KS07G3GtQbxW0NuBEzr/cS588LElgC89T+mvQZUQsUPkm7pyEBnHQ==",
        "X-Received": "by 2002:a62:cd41:: with SMTP id o62mr1937432pfg.94.1570467168642;\n\tMon, 07 Oct 2019 09:52:48 -0700 (PDT)",
        "From": "Stephen Hemminger <stephen@networkplumber.org>",
        "To": "dev@dpdk.org",
        "Cc": "Stephen Hemminger <stephen@networkplumber.org>",
        "Date": "Mon,  7 Oct 2019 09:52:31 -0700",
        "Message-Id": "<20191007165232.14535-8-stephen@networkplumber.org>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20191007165232.14535-1-stephen@networkplumber.org>",
        "References": "<20191007165232.14535-1-stephen@networkplumber.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [RFC 7/8] pcapng: add new library for writing pcapng\n\tfiles",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Simple library for formatting pcapng files used by wireshark\nand other programs.\n\nSee PCAP next generation file format specification\nhttps://github.com/pcapng/pcapng\n\nSigned-off-by: Stephen Hemminger <stephen@networkplumber.org>\n---\n config/common_base                       |   6 +\n lib/Makefile                             |   2 +\n lib/librte_pcapng/Makefile               |  22 ++\n lib/librte_pcapng/meson.build            |  10 +\n lib/librte_pcapng/pcapng_proto.h         | 112 ++++++\n lib/librte_pcapng/rte_pcapng.c           | 449 +++++++++++++++++++++++\n lib/librte_pcapng/rte_pcapng.h           | 132 +++++++\n lib/librte_pcapng/rte_pcapng_version.map |  12 +\n lib/meson.build                          |   2 +-\n mk/rte.app.mk                            |   1 +\n 10 files changed, 747 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_pcapng/Makefile\n create mode 100644 lib/librte_pcapng/meson.build\n create mode 100644 lib/librte_pcapng/pcapng_proto.h\n create mode 100644 lib/librte_pcapng/rte_pcapng.c\n create mode 100644 lib/librte_pcapng/rte_pcapng.h\n create mode 100644 lib/librte_pcapng/rte_pcapng_version.map",
    "diff": "diff --git a/config/common_base b/config/common_base\nindex 8ef75c2039a2..0ccfcfae377d 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -998,6 +998,12 @@ CONFIG_RTE_KNI_PREEMPT_DEFAULT=y\n #\n CONFIG_RTE_LIBRTE_PDUMP=y\n \n+#\n+# Compile the pcapng library\n+#\n+CONFIG_RTE_LIBRTE_PCAPNG=y\n+\n+#\n #\n # Compile vhost user library\n #\ndiff --git a/lib/Makefile b/lib/Makefile\nindex 41c463d92139..47786030fade 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -102,6 +102,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder\n DEPDIRS-librte_reorder := librte_eal librte_mempool librte_mbuf\n DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump\n DEPDIRS-librte_pdump := librte_eal librte_mempool librte_mbuf librte_ethdev\n+DIRS-$(CONFIG_RTE_LIBRTE_PCAPNG) += librte_pcapng\n+DEPDIRS-librte_pcapng := librte_eal librte_mbuf librte_ethdev librte_net\n DIRS-$(CONFIG_RTE_LIBRTE_GSO) += librte_gso\n DEPDIRS-librte_gso := librte_eal librte_mbuf librte_ethdev librte_net\n DEPDIRS-librte_gso += librte_mempool\ndiff --git a/lib/librte_pcapng/Makefile b/lib/librte_pcapng/Makefile\nnew file mode 100644\nindex 000000000000..eaf3e85e3ad2\n--- /dev/null\n+++ b/lib/librte_pcapng/Makefile\n@@ -0,0 +1,22 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Microsoft Corporation\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+# library name\n+LIB = librte_pcapng.a\n+\n+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+\n+EXPORT_MAP := rte_pcapng_version.map\n+\n+LIBABIVER := 1\n+\n+# all source are stored in SRCS-y\n+SRCS-$(CONFIG_RTE_LIBRTE_PCAPNG) := rte_pcapng.c\n+\n+# install includes\n+SYMLINK-$(CONFIG_RTE_LIBRTE_MBUF)-include := rte_pcapng.h\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_pcapng/meson.build b/lib/librte_pcapng/meson.build\nnew file mode 100644\nindex 000000000000..7904b4759b00\n--- /dev/null\n+++ b/lib/librte_pcapng/meson.build\n@@ -0,0 +1,10 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Microsoft Corporation\n+\n+version = 1\n+sources = files('rte_pcapng.c')\n+headers = files('rte_pcapng.h')\n+\n+allow_experimental_apis = true\n+\n+deps += ['ethdev']\ndiff --git a/lib/librte_pcapng/pcapng_proto.h b/lib/librte_pcapng/pcapng_proto.h\nnew file mode 100644\nindex 000000000000..8f35bc31d979\n--- /dev/null\n+++ b/lib/librte_pcapng/pcapng_proto.h\n@@ -0,0 +1,112 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Microsoft Corporation\n+ *\n+ * Pcapng protocol data structures\n+ *  from Draft RFC\n+ */\n+\n+enum pcapng_block_types {\n+\tPCAPNG_INTERFACE_BLOCK\t\t= 1,\n+\tPCAPNG_PACKET_BLOCK,\t\t/* Obsolete */\n+\tPCAPNG_SIMPLE_PACKET_BLOCK,\n+\tPCAPNG_NAME_RESOLUTION_BLOCK,\n+\tPCAPNG_INTERFACE_STATS_BLOCK,\n+\tPCAPNG_ENHANCED_PACKET_BLOCK,\n+\n+\tPCAPNG_SECTION_BLOCK\t\t= 0x0A0D0D0A,\n+};\n+\n+struct pcapng_option {\n+\tuint16_t code;\n+\tuint16_t length;\n+\tuint8_t data[];\n+};\n+\n+#define PCAPNG_BYTE_ORDER_MAGIC 0x1A2B3C4D\n+#define PCAPNG_MAJOR_VERS 1\n+#define PCAPNG_MINOR_VERS 0\n+\n+enum pcapng_opt {\n+\tPCAPNG_OPT_END\t= 0,\n+\tPCAPNG_OPT_COMMENT = 1,\n+};\n+\n+struct pcapng_section_header {\n+\tuint32_t block_type;\n+\tuint32_t block_length;\n+\tuint32_t byte_order_magic;\n+\tuint16_t major_version;\n+\tuint16_t minor_version;\n+\tuint64_t section_length;\n+};\n+\n+enum pcapng_section_opt {\n+\tPCAPNG_SHB_HARDWARE = 2,\n+\tPCAPNG_SHB_OS\t    = 3,\n+\tPCAPNG_SHB_USERAPPL = 4,\n+};\n+\n+struct pcapng_interface_block {\n+\tuint32_t block_type;\t/* 1 */\n+\tuint32_t block_length;\n+\tuint16_t link_type;\n+\tuint16_t reserved;\n+\tuint32_t snap_len;\n+};\n+\n+enum pcapng_interface_options {\n+\tPCAPNG_IFB_NAME\t = 2,\n+\tPCAPNG_IFB_DESCRIPTION,\n+\tPCAPNG_IFB_IPV4ADDR,\n+\tPCAPNG_IFB_IPV6ADDR,\n+\tPCAPNG_IFB_MACADDR,\n+\tPCAPNG_IFB_EUIADDR,\n+\tPCAPNG_IFB_SPEED,\n+\tPCAPNG_IFB_TSRESOL,\n+\tPCAPNG_IFB_TZONE,\n+\tPCAPNG_IFB_FILTER,\n+\tPCAPNG_IFB_OS,\n+\tPCAPNG_IFB_FCSLEN,\n+\tPCAPNG_IFB_TSOFFSET,\n+\tPCAPNG_IFB_HARDWARE,\n+};\n+\n+struct pcapng_enhance_packet_block {\n+\tuint32_t block_type;\t/* 6 */\n+\tuint32_t block_length;\n+\tuint32_t interface_id;\n+\tuint32_t timestamp_hi;\n+\tuint32_t timestamp_lo;\n+\tuint32_t capture_length;\n+\tuint32_t original_length;\n+};\n+\n+enum pcapng_epb_options {\n+\tPCAPNG_EPB_FLAGS = 2,\n+\tPCAPNG_EPB_HASH,\n+\tPCAPNG_EPB_DROPS\n+};\n+\n+struct pcapng_simple_packet {\n+\tuint32_t block_type;\t/* 3 */\n+\tuint32_t block_length;\n+\tuint32_t packet_length;\n+};\n+\n+struct pcapng_statistics {\n+\tuint32_t block_type;\t/* 5 */\n+\tuint32_t block_length;\n+\tuint32_t interface_id;\n+\tuint32_t timestamp_hi;\n+\tuint32_t timestamp_lo;\n+};\n+\n+enum pcapng_isb_options {\n+\tPCAPNG_ISB_STARTTIME = 2,\n+\tPCAPNG_ISB_ENDTIME,\n+\tPCAPNG_ISB_IFRECV,\n+\tPCAPNG_ISB_IFDROP,\n+\tPCAPNG_ISB_FILTERACCEPT,\n+\tPCAPNG_ISB_OSDROP,\n+\tPCAPNG_ISB_USRDELIV\n+};\ndiff --git a/lib/librte_pcapng/rte_pcapng.c b/lib/librte_pcapng/rte_pcapng.c\nnew file mode 100644\nindex 000000000000..2beb3c24f882\n--- /dev/null\n+++ b/lib/librte_pcapng/rte_pcapng.c\n@@ -0,0 +1,449 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Microsoft Corporation\n+ */\n+\n+#include <stdio.h>\n+#include <stdint.h>\n+#include <stdbool.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <unistd.h>\n+#include <errno.h>\n+#include <sys/time.h>\n+#include <sys/uio.h>\n+#include <sys/utsname.h>\n+#include <net/if.h>\n+\n+#include <rte_config.h>\n+#include <rte_ethdev.h>\n+#include <rte_mbuf.h>\n+#include <rte_cycles.h>\n+#include <rte_version.h>\n+#include <rte_pcapng.h>\n+#include <rte_malloc.h>\n+\n+#include \"pcapng_proto.h\"\n+\n+/* conversion from DPDK speed to PCAPNG */\n+#define PCAPNG_MBPS_SPEED 1000000ull\n+\n+#define PCAPNG_MAX_COMMENT 256\n+\n+#define NS_PER_US\t1000ul\n+#define US_PER_SEC\t1000ul\n+#define NS_PER_SEC\t(NS_PER_US * US_PER_SEC)\n+\n+/* Private state for the library */\n+struct rte_pcapng {\n+\tint  outfd;\t\t/* output file */\n+\n+\tuint64_t tsc_t0;\t/* TSC cycles when opened */\n+\tuint32_t tsc_per_us;\t/* TSC cycles per microsecond */\n+\tuint64_t tsc_offset;\t/* nanosecond since 1970 */\n+\n+\tuint32_t next_index;\n+\tuint32_t port_index[RTE_MAX_ETHPORTS];\n+};\n+\n+/* length of option including padding */\n+static size_t pcapng_optlen(uint16_t len)\n+{\n+\treturn RTE_ALIGN(sizeof(struct pcapng_option) + len,\n+\t\t\t sizeof(uint32_t));\n+}\n+\n+/* build TLV option and return location of next */\n+static struct pcapng_option *\n+pcapng_add_option(struct pcapng_option *popt, uint16_t code,\n+\t\t  const void *data, uint16_t len)\n+{\n+\tpopt->code = code;\n+\tpopt->length = len;\n+\tmemcpy(popt->data, data, len);\n+\n+\treturn (struct pcapng_option *)((uint8_t *)popt + pcapng_optlen(len));\n+}\n+\n+/*\n+ * Convert from DPDK timestamp (tsc cycles)\n+ * to what Pcapng uses (nanosecond since 1 Jan 1970 UTC)\n+ */\n+static inline uint64_t tsc_to_timestamp(const rte_pcapng_t *self,\n+\t\t\t\t\tuint64_t tsc)\n+{\n+\tuint64_t ticks = tsc - self->tsc_t0;\n+\n+\treturn (ticks * NS_PER_US) / self->tsc_per_us + self->tsc_offset;\n+}\n+\n+/*\n+ * Write required initial section header describing the capture\n+ */\n+static int\n+write_section_block(rte_pcapng_t *self,\n+\t\t    const char *os, const char *hw,\n+\t\t    const char *app, const char *comment)\n+{\n+\tstruct pcapng_section_header *hdr;\n+\tstruct pcapng_option *opt;\n+\tvoid *buf;\n+\tsize_t len;\n+\tssize_t cc;\n+\n+\tlen = sizeof(*hdr);\n+\tif (hw)\n+\t\tlen += pcapng_optlen(strlen(hw));\n+\tif (os)\n+\t\tlen += pcapng_optlen(strlen(os));\n+\tif (app)\n+\t\tlen += pcapng_optlen(strlen(app));\n+\tif (comment)\n+\t\tlen += pcapng_optlen(strlen(comment));\n+\n+\tlen += pcapng_optlen(0);\n+\tlen += sizeof(uint32_t);\n+\n+\tbuf = calloc(1, len);\n+\tif (!buf)\n+\t\treturn -1;\n+\n+\thdr = (struct pcapng_section_header *)buf;\n+\t*hdr = (struct pcapng_section_header) {\n+\t\t.block_type = PCAPNG_SECTION_BLOCK,\n+\t\t.block_length = len,\n+\t\t.byte_order_magic = PCAPNG_BYTE_ORDER_MAGIC,\n+\t\t.major_version = PCAPNG_MAJOR_VERS,\n+\t\t.minor_version = PCAPNG_MINOR_VERS,\n+\t\t.section_length = UINT64_MAX,\n+\t};\n+\thdr->block_length = len;\n+\n+\topt = (struct pcapng_option *)(hdr + 1);\n+\tif (comment)\n+\t\topt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,\n+\t\t\t\t\tcomment, strlen(comment));\n+\tif (hw)\n+\t\topt = pcapng_add_option(opt, PCAPNG_SHB_HARDWARE,\n+\t\t\t\t\thw, strlen(hw));\n+\tif (os)\n+\t\topt = pcapng_add_option(opt, PCAPNG_SHB_OS,\n+\t\t\t\t\tos, strlen(os));\n+\tif (app)\n+\t\topt = pcapng_add_option(opt, PCAPNG_SHB_USERAPPL,\n+\t\t\t\t\tapp, strlen(app));\n+\n+\topt = pcapng_add_option(opt, PCAPNG_OPT_END, NULL, 0);\n+\t/* clone block_length after option */\n+\tmemcpy(opt, &hdr->block_length, sizeof(uint32_t));\n+\n+\tcc = write(self->outfd, buf, len);\n+\tfree(buf);\n+\n+\treturn cc;\n+}\n+\n+static int\n+capture_header(rte_pcapng_t *self,\n+\t       const char *os, const char *hw,\n+\t       const char *app, const char *comment)\n+{\n+\tchar osbuf[256];\n+\n+\tif (app == NULL) {\n+\t\terrno = EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\tif (os == NULL) {\n+\t\tstruct utsname uts;\n+\n+\t\tuname(&uts);\n+\t\tsnprintf(osbuf, sizeof(osbuf),\n+\t\t\t \"%s %s\", uts.sysname, uts.release);\n+\t\tos = osbuf;\n+\t}\n+\n+\tif (hw == NULL)\n+\t\thw = rte_version();\n+\n+\tif (write_section_block(self, os, hw, app, comment) > 0)\n+\t\treturn 0;\n+\telse\n+\t\treturn -1;\n+}\n+\n+static ssize_t\n+write_interface_block(rte_pcapng_t *self, const char *if_name,\n+\t\t      uint64_t if_speed, const uint8_t *mac_addr,\n+\t\t      const char *if_hw, const char *comment)\n+{\n+\tstruct pcapng_interface_block *hdr;\n+\tstruct pcapng_option *opt;\n+\tconst uint8_t tsresol = 9;\t/* nanosecond resolution */\n+\tsize_t len = sizeof(*hdr);\n+\tssize_t cc;\n+\tvoid *buf;\n+\n+\tlen += pcapng_optlen(sizeof(tsresol));\n+\tif (if_name)\n+\t\tlen += pcapng_optlen(strlen(if_name));\n+\tif (mac_addr)\n+\t\tlen += pcapng_optlen(6);\n+\tif (if_speed)\n+\t\tlen += pcapng_optlen(sizeof(uint64_t));\n+\tif (if_hw)\n+\t\tlen += pcapng_optlen(strlen(if_hw));\n+\tif (comment)\n+\t\tlen += pcapng_optlen(strlen(comment));\n+\n+\tlen += pcapng_optlen(0);\n+\tlen += sizeof(uint32_t);\n+\tbuf = calloc(1, len);\n+\tif (!buf)\n+\t\treturn -ENOMEM;\n+\n+\thdr = (struct pcapng_interface_block *)buf;\n+\thdr->block_type = PCAPNG_INTERFACE_BLOCK;\n+\thdr->link_type = 1;\t/* Ethernet */\n+\thdr->block_length = len;\n+\n+\topt = (struct pcapng_option *)(hdr + 1);\n+\tif (if_name)\n+\t\topt = pcapng_add_option(opt, PCAPNG_IFB_NAME,\n+\t\t\t\t\t if_name, strlen(if_name));\n+\tif (mac_addr)\n+\t\topt = pcapng_add_option(opt, PCAPNG_IFB_MACADDR,\n+\t\t\t\t\tmac_addr, RTE_ETHER_ADDR_LEN);\n+\tif (if_speed)\n+\t\topt = pcapng_add_option(opt, PCAPNG_IFB_SPEED,\n+\t\t\t\t\t &if_speed, sizeof(uint64_t));\n+\topt = pcapng_add_option(opt, PCAPNG_IFB_TSRESOL,\n+\t\t\t\t&tsresol, sizeof(tsresol));\n+\tif (if_hw)\n+\t\topt = pcapng_add_option(opt, PCAPNG_IFB_HARDWARE,\n+\t\t\t\t\t if_hw, strlen(if_hw));\n+\tif (comment)\n+\t\topt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT,\n+\t\t\t\t\tcomment, strlen(comment));\n+\n+\topt = pcapng_add_option(opt, PCAPNG_OPT_END, NULL, 0);\n+\n+\tmemcpy(opt, &hdr->block_length, sizeof(uint32_t));\n+\tcc = write(self->outfd, buf, len);\n+\tfree(buf);\n+\n+\treturn cc;\n+}\n+\n+int\n+rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port,\n+\t\t\t const char *comment, uint32_t flags)\n+{\n+\tstruct rte_eth_dev_info dev_info;\n+\tstruct rte_ether_addr macaddr;\n+\tconst struct rte_device *dev;\n+\tstruct rte_eth_link link;\n+\tchar ifname[IF_NAMESIZE];\n+\tchar ifhw[256];\n+\tuint64_t speed = 0;\n+\tint cc;\n+\n+\tif (flags != 0) {\n+\t\trte_errno = EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\trte_eth_dev_info_get(port, &dev_info);\n+\n+\t/* make something like an interface name */\n+\tif (if_indextoname(dev_info.if_index, ifname) == NULL)\n+\t\tsnprintf(ifname, IF_NAMESIZE, \"dpdk:%u\", port);\n+\n+\t/* make a useful device hardware string */\n+\tdev = dev_info.device;\n+\tif (dev)\n+\t\tsnprintf(ifhw, sizeof(ifhw),\n+\t\t\t \"%s-%s\", dev->bus->name, dev->name);\n+\n+\t/* DPDK reports in units of Mbps */\n+\trte_eth_link_get(port, &link);\n+\tif (link.link_status == ETH_LINK_UP)\n+\t\tspeed = link.link_speed * PCAPNG_MBPS_SPEED;\n+\n+\trte_eth_macaddr_get(port, &macaddr);\n+\n+\tcc = write_interface_block(self, ifname, speed,\n+\t\t\t\t   macaddr.addr_bytes,\n+\t\t\t\t   dev ? ifhw : NULL,\n+\t\t\t\t   comment);\n+\tif (cc < 0) {\n+\t\trte_errno = errno;\n+\t\treturn -1;\n+\t}\n+\n+\tself->port_index[port] = self->next_index++;\n+\treturn 0;\n+}\n+\n+/* Create new pcapng writer handle */\n+rte_pcapng_t *\n+rte_pcapng_fdopen(int fd,\n+\t\t  const char *osname, const char *hardware,\n+\t\t  const char *appname, const char *comment,\n+\t\t  uint32_t flags)\n+{\n+\trte_pcapng_t *self;\n+\tstruct timeval tv;\n+\n+\tif (flags != 0) {\n+\t\trte_errno = EINVAL;\n+\t\treturn NULL;\n+\t}\n+\n+\tself = rte_zmalloc(\"pcapng\", sizeof(*self), 0);\n+\tif (!self) {\n+\t\trte_errno = ENOMEM;\n+\t\treturn NULL;\n+\t}\n+\n+\tself->outfd = fd;\n+\n+\t/* compute clock offsets */\n+\tself->tsc_t0 = rte_rdtsc();\n+\tself->tsc_per_us = rte_get_tsc_hz() / US_PER_SEC;\n+\tgettimeofday(&tv, NULL);\n+\tself->tsc_offset = (tv.tv_sec * US_PER_SEC + tv.tv_usec) * NS_PER_US;\n+\n+\tif (capture_header(self, osname, hardware,\n+\t\t\t   appname, comment) < 0)\n+\t\tgoto error;\n+\n+\treturn self;\n+\n+error:\n+\tclose(self->outfd);\n+\trte_errno = errno;\n+\trte_free(self);\n+\treturn NULL;\n+}\n+\n+void\n+rte_pcapng_close(rte_pcapng_t *self)\n+{\n+\tclose(self->outfd);\n+\trte_free(self);\n+}\n+\n+int\n+rte_pcapng_dump_packet(rte_pcapng_t *self, uint16_t port,\n+\t\t       const struct rte_mbuf *m,\n+\t\t       enum rte_pcapng_direction dir,\n+\t\t       const char *comment)\n+{\n+\tstruct pcapng_enhance_packet_block hdr;\n+\tuint32_t snap_len, padded_len, pad_bytes;\n+\tuint64_t ts = tsc_to_timestamp(self, m->timestamp);\n+\tstatic uint64_t zero_pad;\n+\tstruct pcapng_option *opt;\n+\tuint32_t flags = dir;\n+\tuint32_t options[512];\n+\tuint16_t i;\n+\tstruct iovec iov[m->nb_segs + 4];\n+\tsize_t len, optlen;\n+\n+#ifdef RTE_LIBRTE_ETHDEV_DEBUG\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);\n+#endif\n+\t/* only handle single segment mbuf */\n+\tsnap_len = rte_pktmbuf_data_len(m);\n+\tpadded_len = RTE_ALIGN(snap_len, sizeof(uint32_t));\n+\tpad_bytes = padded_len - snap_len;\n+\n+\tlen = sizeof(hdr) + padded_len + sizeof(uint32_t);\n+\topt = (struct pcapng_option *)options;\n+\n+\topt = pcapng_add_option(opt, PCAPNG_EPB_FLAGS,\n+\t\t\t\t&flags, sizeof(flags));\n+\n+\tif (comment)\n+\t\topt = pcapng_add_option(opt, PCAPNG_OPT_COMMENT, comment,\n+\t\t\t\t\tstrnlen(comment, PCAPNG_MAX_COMMENT));\n+\n+\toptlen = (char *)opt - (char *)options;\n+\tlen += optlen;\n+\n+\thdr.block_type = PCAPNG_ENHANCED_PACKET_BLOCK;\n+\thdr.block_length = len;\n+\n+\thdr.interface_id = self->port_index[port];\n+\thdr.timestamp_hi = ts >> 32;\n+\thdr.timestamp_lo = (uint32_t)ts;\n+\thdr.capture_length = snap_len;\n+\thdr.original_length = rte_pktmbuf_pkt_len(m);\n+\n+\tiov[0].iov_base = &hdr;\n+\tiov[0].iov_len = sizeof(hdr);\n+\n+\tfor (i = 1; m; ++i, m = m->next) {\n+\t\tiov[i].iov_base = rte_pktmbuf_mtod(m, void *);\n+\t\tiov[i].iov_len = rte_pktmbuf_data_len(m);\n+\t}\n+\n+\tif (pad_bytes > 0) {\n+\t\tiov[i].iov_base = &zero_pad;\n+\t\tiov[i].iov_len = pad_bytes;\n+\t\t++i;\n+\t}\n+\n+\tiov[i].iov_base = options;\n+\tiov[i].iov_len = optlen;\n+\t++i;\n+\n+\tiov[i].iov_base = &hdr.block_length;\n+\tiov[i].iov_len = sizeof(uint32_t);\n+\t++i;\n+\n+\tif (unlikely(writev(self->outfd, iov, i) < 0)) {\n+\t\trte_errno = errno;\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_pcapng_dump_tx(rte_pcapng_t *out, uint16_t port,\n+\t\t   struct rte_mbuf *pkts[], uint32_t nb_pkts)\n+{\n+\tuint32_t i;\n+\tint r = 0;\n+\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tstruct rte_mbuf *m = pkts[i];\n+\n+\t\tr = rte_pcapng_dump_packet(out, port, m,\n+\t\t\t\t\t   RTE_PCAPNG_DIR_OUTBOUND, NULL);\n+\t\tif (unlikely(r < 0))\n+\t\t\tbreak;\n+\t}\n+\n+\treturn r;\n+}\n+\n+int\n+rte_pcapng_dump_rx(rte_pcapng_t *out,\n+\t\t   struct rte_mbuf *pkts[], uint32_t nb_pkts)\n+{\n+\tuint32_t i;\n+\tint r = 0;\n+\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tstruct rte_mbuf *m = pkts[i];\n+\n+\t\tr = rte_pcapng_dump_packet(out, m->port, m,\n+\t\t\t\t\t   RTE_PCAPNG_DIR_INBOUND, NULL);\n+\t\tif (unlikely(r < 0))\n+\t\t\tbreak;\n+\t}\n+\treturn r;\n+}\ndiff --git a/lib/librte_pcapng/rte_pcapng.h b/lib/librte_pcapng/rte_pcapng.h\nnew file mode 100644\nindex 000000000000..23763c6882c8\n--- /dev/null\n+++ b/lib/librte_pcapng/rte_pcapng.h\n@@ -0,0 +1,132 @@\n+/*\n+ * Simple library to write files in Pcap-ng format.\n+ * Copyright(c) 2019 Microsoft Corporation\n+ * All rights reserved.\n+ */\n+\n+\n+/* Handle used for functions in this library. */\n+typedef struct rte_pcapng rte_pcapng_t;\n+\n+/**\n+ * Open new packet capture file\n+ *\n+ * @param fd\n+ *   file descriptor\n+ * @param osname\n+ *   Operating system name.\n+ *   If NULL will be filled in based on result of utsname.\n+ * @param hardware\n+ *   Hardware information.\n+ *   If NULL will be filled in with DPDK version.\n+ * @param appname\n+ *   Applicaton name.\n+ * @param comment\n+ *   Comment for the file (optional can be NULL)\n+ * @param flags\n+ *   Options for capture (reserved must be 0)\n+ * @return\n+ *   handle to library, or NULL in case of error (and rte_errno is set).\n+ */\n+__rte_experimental\n+rte_pcapng_t *\n+rte_pcapng_fdopen(int fd,\n+\t\t  const char *osname, const char *hardware,\n+\t\t  const char *appname, const char *comment,\n+\t\t  uint32_t flags);\n+\n+\n+enum rte_pcapng_direction {\n+\tRTE_PCAPNG_DIR_UNKNOWN = 0,\n+\tRTE_PCAPNG_DIR_INBOUND = 1,\n+\tRTE_PCAPNG_DIR_OUTBOUND = 2,\n+};\n+\n+/**\n+ * Add interface to capture file\n+ * This must be done after opening and before dumping any packets.\n+ * Call once for each port being followed.\n+ *\n+ * @param out\n+ *  The handle to the packet capture file\n+ * @param port\n+ *  The Ethernet port being captured.\n+ * @param comment\n+ *   Comment for the file (optional can be NULL)\n+ * @param flags\n+ *   Options for capture (reserved must be 0)\n+ * @return\n+ *  0 on success, -1 on failure (and rte_errno is set).\n+ */\n+__rte_experimental\n+int\n+rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port,\n+\t\t\t const char *comment, uint32_t flags);\n+\n+/**\n+ * Record packet in capture file\n+ *\n+ * @param out\n+ *  The handle to the packet capture file\n+ * @param port\n+ *  The Ethernet port on which the packet is being sent.\n+ * @param m\n+ *  The packet to record\n+ * @param dir\n+ *  Direction in/out or unknown\n+ * @param comment\n+ *  Comment to add to record\n+ * @return\n+ *  0 on success, -1 on failure\n+ */\n+__rte_experimental\n+int\n+rte_pcapng_dump_packet(rte_pcapng_t *self, uint16_t port,\n+\t\t       const struct rte_mbuf *m,\n+\t\t       enum rte_pcapng_direction dir,\n+\t\t       const char *comment);\n+/**\n+ * Dump packets to be transmitted.\n+ *\n+ * @param out\n+ *  The handle to the packet capture file\n+ * @param port_id\n+ *  The Ethernet port on which the packet is being sent.\n+ * @param pkts\n+ *  The packets to be recorded.\n+ * @param nb_pkts\n+ *  The number of packets in the burst pointed to by \"pkts\".\n+ * @return\n+ *  0 on success, -1 on failure (and rte_errno is set).\n+ */\n+__rte_experimental\n+int\n+rte_pcapng_dump_tx(rte_pcapng_t *out, uint16_t port,\n+\t\t   struct rte_mbuf *pkts[], uint32_t nb_pkts);\n+\n+/**\n+ * Dump a packets received.\n+ *\n+ * @param out\n+ *  The handle to the packet capture file\n+ * @param pkts\n+ *  The packets to be recorded.\n+ * @param nb_pkts\n+ *  The number of packets in the burst pointed to by \"pkts\".\n+ * @return\n+ *  0 on success, -1 on failure (and rte_errno is set).\n+ */\n+__rte_experimental\n+int\n+rte_pcapng_dump_rx(rte_pcapng_t *out,\n+\t\t   struct rte_mbuf *pkts[], uint32_t nb_pkts);\n+\n+/**\n+ * Close capture file\n+ *\n+ * @param self\n+ *  handle to library\n+ */\n+__rte_experimental\n+void\n+rte_pcapng_close(rte_pcapng_t *self);\ndiff --git a/lib/librte_pcapng/rte_pcapng_version.map b/lib/librte_pcapng/rte_pcapng_version.map\nnew file mode 100644\nindex 000000000000..eb8ae2b50984\n--- /dev/null\n+++ b/lib/librte_pcapng/rte_pcapng_version.map\n@@ -0,0 +1,12 @@\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_pcapng_fdopen;\n+\trte_pcapng_add_interface;\n+\trte_pcapng_dump_packet;\n+\trte_pcapng_dump_tx;\n+\trte_pcapng_dump_rx;\n+\trte_pcapng_close;\n+\n+\tlocal: *;\n+};\ndiff --git a/lib/meson.build b/lib/meson.build\nindex e5ff83893489..cb07e38d8b58 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -21,7 +21,7 @@ libraries = [\n \t'distributor', 'efd', 'eventdev',\n \t'gro', 'gso', 'ip_frag', 'jobstats',\n \t'kni', 'latencystats', 'lpm', 'member',\n-\t'power', 'pdump', 'rawdev',\n+\t'power', 'pdump', 'rawdev', 'pcapng',\n \t'rcu', 'reorder', 'sched', 'security', 'stack', 'vhost',\n \t# ipsec lib depends on net, crypto and security\n \t'ipsec',\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex ba5c39e01957..b50b74ed6c99 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -42,6 +42,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT)           += -lrte_port\n _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT)           += --no-whole-archive\n \n _LDLIBS-$(CONFIG_RTE_LIBRTE_PDUMP)          += -lrte_pdump\n+_LDLIBS-$(CONFIG_RTE_LIBRTE_PCAPNG)         += -lrte_pcapng\n _LDLIBS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR)    += -lrte_distributor\n _LDLIBS-$(CONFIG_RTE_LIBRTE_IP_FRAG)        += -lrte_ip_frag\n _LDLIBS-$(CONFIG_RTE_LIBRTE_METER)          += -lrte_meter\n",
    "prefixes": [
        "RFC",
        "7/8"
    ]
}