get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132352,
    "url": "https://patches.dpdk.org/api/patches/132352/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20231005230648.68244-4-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": "<20231005230648.68244-4-stephen@networkplumber.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231005230648.68244-4-stephen@networkplumber.org",
    "date": "2023-10-05T23:06:47",
    "name": "[v2,3/4] pcapng: modify timestamp calculation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "504fd1dcd5c0a1f2692b8d2f5d36311d96409594",
    "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/20231005230648.68244-4-stephen@networkplumber.org/mbox/",
    "series": [
        {
            "id": 29747,
            "url": "https://patches.dpdk.org/api/series/29747/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29747",
            "date": "2023-10-05T23:06:44",
            "name": "dumpcap and pcapng fixes",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/29747/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/132352/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/132352/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 94CD8426C7;\n\tFri,  6 Oct 2023 01:07:21 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 061D640685;\n\tFri,  6 Oct 2023 01:07:05 +0200 (CEST)",
            "from mail-pf1-f180.google.com (mail-pf1-f180.google.com\n [209.85.210.180])\n by mails.dpdk.org (Postfix) with ESMTP id 175AB402E1\n for <dev@dpdk.org>; Fri,  6 Oct 2023 01:07:03 +0200 (CEST)",
            "by mail-pf1-f180.google.com with SMTP id\n d2e1a72fcca58-69101d33315so1334839b3a.3\n for <dev@dpdk.org>; Thu, 05 Oct 2023 16:07:03 -0700 (PDT)",
            "from hermes.local (204-195-126-68.wavecable.com. [204.195.126.68])\n by smtp.gmail.com with ESMTPSA id\n d13-20020aa7814d000000b00690cd981652sm112665pfn.61.2023.10.05.16.07.01\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 05 Oct 2023 16:07:01 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1696547222;\n x=1697152022; darn=dpdk.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=G96UWs1s1zVTU1r2+fNK0uU6DoagTbT+MgDPBX/yKww=;\n b=IDfZN9iesYrEiRbWMdcGSm11LB1liHPAEBZe8QXBqempbXKC5A/ZtKY5cgX97NZPBt\n xqwaBrK1s1ukcJO2CZplsLqfMBGnr15WemZ5e0RfAMLkd4WiVASOXg+rwT8i65qQ2ph2\n +UOqu8CDRfbzRdnQXgz4EMe4NqcpHrjD73LglpdAk/yhhxVRGRp6c1oFYYnJOJpYAS8k\n PQC0FgVTRCdLc0OAvHL04qxl5Mjruf/PrpYGYEhOKq7ol5YCQl8Sm5YoDYEsXL5TpSbT\n 6UQ+CkGns8EV4ADk99+sJ/SbepB6YiqDf6J2hOsyAM/OhSFOL3jzce/r3ImFfm5potpK\n OB4g==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1696547222; x=1697152022;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=G96UWs1s1zVTU1r2+fNK0uU6DoagTbT+MgDPBX/yKww=;\n b=wPFhz+IbNXBqhQAJq1Eon15PEN+zc2cBQLHgGiDyXhzmhOQoBo1bnZHqRqbNO2z6iK\n 2jeA4gtfT/jGn8WH+F6Ip7+mvQApe0w8Ws84KQ4jdUvMggcil5lB/KrRciNujnyAMY/2\n GeXPBU9FSwIlBNglNIrSkVb409y5PWpsgRmPa7eBV+l9Sg7AD9fbT7L6z6CC0GNtu4Wy\n tcgkYairyQww0simYkHwcqF7Plm+idYvY3SQ3OupwADujFRfNCW77NR0nIbUKFUqGrNo\n kpcEgBy0IoRz+Ig2hBXP79VBMeRImA46c2afZVzWJM5gnmWSmD7jOJHfcKaTdwLw7OsR\n mYAA==",
        "X-Gm-Message-State": "AOJu0Yzbf7m6H2jOtnG5U5yj+Ej30ZrmOkehW8JfweLKySZNHq2B+nos\n dDpWlN+ekYkOtCfY4n5bfxdJATAgW6SV9GZArlI=",
        "X-Google-Smtp-Source": "\n AGHT+IF1cz8fAHMioqFR/BePlJbugcdNyAkPVOeiW+9wudxG5kcDpbEiQvqbFVlUyCEV8IGgbkZwJA==",
        "X-Received": "by 2002:a05:6a00:2489:b0:690:1720:aa92 with SMTP id\n c9-20020a056a00248900b006901720aa92mr6897109pfv.10.1696547221914;\n Thu, 05 Oct 2023 16:07:01 -0700 (PDT)",
        "From": "Stephen Hemminger <stephen@networkplumber.org>",
        "To": "dev@dpdk.org",
        "Cc": "Stephen Hemminger <stephen@networkplumber.org>,\n Reshma Pattan <reshma.pattan@intel.com>, Jerin Jacob <jerinj@marvell.com>,\n Kiran Kumar K <kirankumark@marvell.com>,\n Nithin Dabilpuram <ndabilpuram@marvell.com>,\n Zhirun Yan <zhirun.yan@intel.com>,\n Quentin Armitage <quentin@armitage.org.uk>",
        "Subject": "[PATCH v2 3/4] pcapng: modify timestamp calculation",
        "Date": "Thu,  5 Oct 2023 16:06:47 -0700",
        "Message-Id": "<20231005230648.68244-4-stephen@networkplumber.org>",
        "X-Mailer": "git-send-email 2.39.2",
        "In-Reply-To": "<20231005230648.68244-1-stephen@networkplumber.org>",
        "References": "<20230921042349.104150-1-stephen@networkplumber.org>\n <20231005230648.68244-1-stephen@networkplumber.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "The computation of timestamp is best done in the part of\npcapng library that is in secondary process.\nThe secondary process is already doing a bunch of system\ncalls which makes it not performance sensitive.\n\nSimplify the computation of nanoseconds from TSC to a two\nstep process which avoids numeric overflow issues. The previous\ncode was not thread safe as well.\n\nFixes: c882eb544842 (\"pcapng: fix timestamp wrapping in output files\")\nSigned-off-by: Stephen Hemminger <stephen@networkplumber.org>\n---\n app/dumpcap/main.c      |  25 +++------\n app/test/test_pcapng.c  |   4 +-\n lib/graph/graph_pcap.c  |   2 +-\n lib/pcapng/rte_pcapng.c | 119 +++++++++++++++-------------------------\n lib/pcapng/rte_pcapng.h |  19 ++-----\n lib/pdump/rte_pdump.c   |   4 +-\n 6 files changed, 61 insertions(+), 112 deletions(-)",
    "diff": "diff --git a/app/dumpcap/main.c b/app/dumpcap/main.c\nindex 37754fd06f4f..764dac6c37c0 100644\n--- a/app/dumpcap/main.c\n+++ b/app/dumpcap/main.c\n@@ -66,13 +66,13 @@ static bool print_stats;\n \n /* capture limit options */\n static struct {\n-\tuint64_t  duration;\t/* nanoseconds */\n+\ttime_t  duration;\t/* seconds */\n \tunsigned long packets;  /* number of packets in file */\n \tsize_t size;\t\t/* file size (bytes) */\n } stop;\n \n /* Running state */\n-static uint64_t start_time, end_time;\n+static time_t start_time;\n static uint64_t packets_received;\n static size_t file_size;\n \n@@ -197,7 +197,7 @@ static void auto_stop(char *opt)\n \t\tif (*value == '\\0' || *endp != '\\0' || interval <= 0)\n \t\t\trte_exit(EXIT_FAILURE,\n \t\t\t\t \"Invalid duration \\\"%s\\\"\\n\", value);\n-\t\tstop.duration = NSEC_PER_SEC * interval;\n+\t\tstop.duration = interval;\n \t} else if (strcmp(opt, \"filesize\") == 0) {\n \t\tstop.size = get_uint(value, \"filesize\", 0) * 1024;\n \t} else if (strcmp(opt, \"packets\") == 0) {\n@@ -511,15 +511,6 @@ static void statistics_loop(void)\n \t}\n }\n \n-/* Return the time since 1/1/1970 in nanoseconds */\n-static uint64_t create_timestamp(void)\n-{\n-\tstruct timespec now;\n-\n-\tclock_gettime(CLOCK_MONOTONIC, &now);\n-\treturn rte_timespec_to_ns(&now);\n-}\n-\n static void\n cleanup_pdump_resources(void)\n {\n@@ -589,9 +580,8 @@ report_packet_stats(dumpcap_out_t out)\n \t\tifdrop = pdump_stats.nombuf + pdump_stats.ringfull;\n \n \t\tif (use_pcapng)\n-\t\t\trte_pcapng_write_stats(out.pcapng, intf->port, NULL,\n-\t\t\t\t\t       start_time, end_time,\n-\t\t\t\t\t       ifrecv, ifdrop);\n+\t\t\trte_pcapng_write_stats(out.pcapng, intf->port,\n+\t\t\t\t\t       ifrecv, ifdrop, NULL);\n \n \t\tif (ifrecv == 0)\n \t\t\tpercent = 0;\n@@ -983,7 +973,7 @@ int main(int argc, char **argv)\n \tmp = create_mempool();\n \tout = create_output();\n \n-\tstart_time = create_timestamp();\n+\tstart_time = time(NULL);\n \tenable_pdump(r, mp);\n \n \tif (!quiet) {\n@@ -1005,11 +995,10 @@ int main(int argc, char **argv)\n \t\t\tbreak;\n \n \t\tif (stop.duration != 0 &&\n-\t\t    create_timestamp() - start_time > stop.duration)\n+\t\t    time(NULL) - start_time > stop.duration)\n \t\t\tbreak;\n \t}\n \n-\tend_time = create_timestamp();\n \tdisable_primary_monitor();\n \n \tif (rte_eal_primary_proc_alive(NULL))\ndiff --git a/app/test/test_pcapng.c b/app/test/test_pcapng.c\nindex b8429a02f160..55aa2cf93666 100644\n--- a/app/test/test_pcapng.c\n+++ b/app/test/test_pcapng.c\n@@ -173,8 +173,8 @@ test_write_stats(void)\n \tssize_t len;\n \n \t/* write a statistics block */\n-\tlen = rte_pcapng_write_stats(pcapng, port_id,\n-\t\t\t\t     NULL, 0, 0,\n+\tlen = rte_pcapng_write_stats(pcapng, port_id, NULL,\n+\t\t\t\t     0, 0, 0,\n \t\t\t\t     NUM_PACKETS, 0);\n \tif (len <= 0) {\n \t\tfprintf(stderr, \"Write of statistics failed\\n\");\ndiff --git a/lib/graph/graph_pcap.c b/lib/graph/graph_pcap.c\nindex db722c375fa7..89525f1220ca 100644\n--- a/lib/graph/graph_pcap.c\n+++ b/lib/graph/graph_pcap.c\n@@ -214,7 +214,7 @@ graph_pcap_dispatch(struct rte_graph *graph,\n \t\tmbuf = (struct rte_mbuf *)objs[i];\n \n \t\tmc = rte_pcapng_copy(mbuf->port, 0, mbuf, pkt_mp, mbuf->pkt_len,\n-\t\t\t\t     rte_get_tsc_cycles(), 0, buffer);\n+\t\t\t\t     0, buffer);\n \t\tif (mc == NULL)\n \t\t\tbreak;\n \ndiff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c\nindex 3c91fc77644a..13fd2b97fb80 100644\n--- a/lib/pcapng/rte_pcapng.c\n+++ b/lib/pcapng/rte_pcapng.c\n@@ -36,22 +36,14 @@\n /* Format of the capture file handle */\n struct rte_pcapng {\n \tint  outfd;\t\t/* output file */\n-\n \tunsigned int ports;\t/* number of interfaces added */\n+\tuint64_t offset_ns;\t/* ns since 1/1/1970 when initialized */\n+\tuint64_t tsc_base;\t/* TSC when started */\n \n \t/* DPDK port id to interface index in file */\n \tuint32_t port_index[RTE_MAX_ETHPORTS];\n };\n \n-/* For converting TSC cycles to PCAPNG ns format */\n-static struct pcapng_time {\n-\tuint64_t ns;\n-\tuint64_t cycles;\n-\tuint64_t tsc_hz;\n-\tstruct rte_reciprocal_u64 tsc_hz_inverse;\n-} pcapng_time;\n-\n-\n #ifdef RTE_EXEC_ENV_WINDOWS\n /*\n  * Windows does not have writev() call.\n@@ -102,56 +94,21 @@ static ssize_t writev(int fd, const struct iovec *iov, int iovcnt)\n #define if_indextoname(ifindex, ifname) NULL\n #endif\n \n-static inline void\n-pcapng_init(void)\n+/* Convert from TSC (CPU cycles) to nanoseconds */\n+static uint64_t\n+pcapng_timestamp(const rte_pcapng_t *self, uint64_t cycles)\n {\n-\tstruct timespec ts;\n+\tuint64_t delta, rem, secs, ns;\n+\tconst uint64_t hz = rte_get_tsc_hz();\n \n-\tpcapng_time.cycles = rte_get_tsc_cycles();\n-\tclock_gettime(CLOCK_REALTIME, &ts);\n-\tpcapng_time.cycles = (pcapng_time.cycles + rte_get_tsc_cycles()) / 2;\n-\tpcapng_time.ns = rte_timespec_to_ns(&ts);\n-\n-\tpcapng_time.tsc_hz = rte_get_tsc_hz();\n-\tpcapng_time.tsc_hz_inverse = rte_reciprocal_value_u64(pcapng_time.tsc_hz);\n-}\n+\tdelta = cycles - self->tsc_base;\n \n-/* PCAPNG timestamps are in nanoseconds */\n-static uint64_t pcapng_tsc_to_ns(uint64_t cycles)\n-{\n-\tuint64_t delta, secs;\n-\n-\tif (!pcapng_time.tsc_hz)\n-\t\tpcapng_init();\n-\n-\t/* In essence the calculation is:\n-\t *   delta = (cycles - pcapng_time.cycles) * NSEC_PRE_SEC / rte_get_tsc_hz()\n-\t * but this overflows within 4 to 8 seconds depending on TSC frequency.\n-\t * Instead, if delta >= pcapng_time.tsc_hz:\n-\t *   Increase pcapng_time.ns and pcapng_time.cycles by the number of\n-\t *   whole seconds in delta and reduce delta accordingly.\n-\t * delta will therefore always lie in the interval [0, pcapng_time.tsc_hz),\n-\t * which will not overflow when multiplied by NSEC_PER_SEC provided the\n-\t * TSC frequency < approx 18.4GHz.\n-\t *\n-\t * Currently all TSCs operate below 5GHz.\n-\t */\n-\tdelta = cycles - pcapng_time.cycles;\n-\tif (unlikely(delta >= pcapng_time.tsc_hz)) {\n-\t\tif (likely(delta < pcapng_time.tsc_hz * 2)) {\n-\t\t\tdelta -= pcapng_time.tsc_hz;\n-\t\t\tpcapng_time.cycles += pcapng_time.tsc_hz;\n-\t\t\tpcapng_time.ns += NSEC_PER_SEC;\n-\t\t} else {\n-\t\t\tsecs = rte_reciprocal_divide_u64(delta, &pcapng_time.tsc_hz_inverse);\n-\t\t\tdelta -= secs * pcapng_time.tsc_hz;\n-\t\t\tpcapng_time.cycles += secs * pcapng_time.tsc_hz;\n-\t\t\tpcapng_time.ns += secs * NSEC_PER_SEC;\n-\t\t}\n-\t}\n+\t/* Avoid numeric wraparound by computing seconds first */\n+\tsecs = delta / hz;\n+\trem = delta % hz;\n+\tns = (rem * NS_PER_S) / hz;\n \n-\treturn pcapng_time.ns + rte_reciprocal_divide_u64(delta * NSEC_PER_SEC,\n-\t\t\t\t\t\t\t  &pcapng_time.tsc_hz_inverse);\n+\treturn secs * NS_PER_S + ns + self->offset_ns;\n }\n \n /* length of option including padding */\n@@ -368,15 +325,15 @@ rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port,\n  */\n ssize_t\n rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,\n-\t\t       const char *comment,\n-\t\t       uint64_t start_time, uint64_t end_time,\n-\t\t       uint64_t ifrecv, uint64_t ifdrop)\n+\t\t       uint64_t ifrecv, uint64_t ifdrop,\n+\t\t       const char *comment)\n {\n \tstruct pcapng_statistics *hdr;\n \tstruct pcapng_option *opt;\n+\tuint64_t start_time = self->offset_ns;\n+\tuint64_t sample_time;\n \tuint32_t optlen, len;\n \tuint8_t *buf;\n-\tuint64_t ns;\n \n \tRTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);\n \n@@ -386,10 +343,10 @@ rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,\n \t\toptlen += pcapng_optlen(sizeof(ifrecv));\n \tif (ifdrop != UINT64_MAX)\n \t\toptlen += pcapng_optlen(sizeof(ifdrop));\n+\n \tif (start_time != 0)\n \t\toptlen += pcapng_optlen(sizeof(start_time));\n-\tif (end_time != 0)\n-\t\toptlen += pcapng_optlen(sizeof(end_time));\n+\n \tif (comment)\n \t\toptlen += pcapng_optlen(strlen(comment));\n \tif (optlen != 0)\n@@ -409,9 +366,6 @@ rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,\n \tif (start_time != 0)\n \t\topt = pcapng_add_option(opt, PCAPNG_ISB_STARTTIME,\n \t\t\t\t\t &start_time, sizeof(start_time));\n-\tif (end_time != 0)\n-\t\topt = pcapng_add_option(opt, PCAPNG_ISB_ENDTIME,\n-\t\t\t\t\t &end_time, sizeof(end_time));\n \tif (ifrecv != UINT64_MAX)\n \t\topt = pcapng_add_option(opt, PCAPNG_ISB_IFRECV,\n \t\t\t\t&ifrecv, sizeof(ifrecv));\n@@ -425,9 +379,9 @@ rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,\n \thdr->block_length = len;\n \thdr->interface_id = self->port_index[port_id];\n \n-\tns = pcapng_tsc_to_ns(rte_get_tsc_cycles());\n-\thdr->timestamp_hi = ns >> 32;\n-\thdr->timestamp_lo = (uint32_t)ns;\n+\tsample_time = pcapng_timestamp(self, rte_get_tsc_cycles());\n+\thdr->timestamp_hi = sample_time >> 32;\n+\thdr->timestamp_lo = (uint32_t)sample_time;\n \n \t/* clone block_length after option */\n \tmemcpy(opt, &len, sizeof(uint32_t));\n@@ -520,23 +474,21 @@ struct rte_mbuf *\n rte_pcapng_copy(uint16_t port_id, uint32_t queue,\n \t\tconst struct rte_mbuf *md,\n \t\tstruct rte_mempool *mp,\n-\t\tuint32_t length, uint64_t cycles,\n+\t\tuint32_t length,\n \t\tenum rte_pcapng_direction direction,\n \t\tconst char *comment)\n {\n \tstruct pcapng_enhance_packet_block *epb;\n \tuint32_t orig_len, data_len, padding, flags;\n \tstruct pcapng_option *opt;\n+\tuint64_t timestamp;\n \tuint16_t optlen;\n \tstruct rte_mbuf *mc;\n-\tuint64_t ns;\n \tbool rss_hash;\n \n #ifdef RTE_LIBRTE_ETHDEV_DEBUG\n \tRTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);\n #endif\n-\tns = pcapng_tsc_to_ns(cycles);\n-\n \torig_len = rte_pktmbuf_pkt_len(md);\n \n \t/* Take snapshot of the data */\n@@ -641,8 +593,10 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,\n \t/* Interface index is filled in later during write */\n \tmc->port = port_id;\n \n-\tepb->timestamp_hi = ns >> 32;\n-\tepb->timestamp_lo = (uint32_t)ns;\n+\t/* Put timestamp in cycles here - adjust in packet write */\n+\ttimestamp = rte_get_tsc_cycles();\n+\tepb->timestamp_hi = timestamp >> 32;\n+\tepb->timestamp_lo = (uint32_t)timestamp;\n \tepb->capture_length = data_len;\n \tepb->original_length = orig_len;\n \n@@ -668,6 +622,7 @@ rte_pcapng_write_packets(rte_pcapng_t *self,\n \tfor (i = 0; i < nb_pkts; i++) {\n \t\tstruct rte_mbuf *m = pkts[i];\n \t\tstruct pcapng_enhance_packet_block *epb;\n+\t\tuint64_t cycles, timestamp;\n \n \t\t/* sanity check that is really a pcapng mbuf */\n \t\tepb = rte_pktmbuf_mtod(m, struct pcapng_enhance_packet_block *);\n@@ -684,6 +639,13 @@ rte_pcapng_write_packets(rte_pcapng_t *self,\n \t\t\treturn -1;\n \t\t}\n \n+\t\t/* adjust timestamp recorded in packet */\n+\t\tcycles = (uint64_t)epb->timestamp_hi << 32;\n+\t\tcycles += epb->timestamp_lo;\n+\t\ttimestamp = pcapng_timestamp(self, cycles);\n+\t\tepb->timestamp_hi = timestamp >> 32;\n+\t\tepb->timestamp_lo = (uint32_t)timestamp;\n+\n \t\t/*\n \t\t * Handle case of highly fragmented and large burst size\n \t\t * Note: this assumes that max segments per mbuf < IOV_MAX\n@@ -725,6 +687,8 @@ rte_pcapng_fdopen(int fd,\n {\n \tunsigned int i;\n \trte_pcapng_t *self;\n+\tstruct timespec ts;\n+\tuint64_t cycles;\n \n \tself = malloc(sizeof(*self));\n \tif (!self) {\n@@ -734,6 +698,13 @@ rte_pcapng_fdopen(int fd,\n \n \tself->outfd = fd;\n \tself->ports = 0;\n+\n+\t/* record start time in ns since 1/1/1970 */\n+\tcycles = rte_get_tsc_cycles();\n+\tclock_gettime(CLOCK_REALTIME, &ts);\n+\tself->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;\n+\tself->offset_ns = rte_timespec_to_ns(&ts);\n+\n \tfor (i = 0; i < RTE_MAX_ETHPORTS; i++)\n \t\tself->port_index[i] = UINT32_MAX;\n \ndiff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h\nindex d93cc9f73ad5..c40795c721de 100644\n--- a/lib/pcapng/rte_pcapng.h\n+++ b/lib/pcapng/rte_pcapng.h\n@@ -121,8 +121,6 @@ enum rte_pcapng_direction {\n  * @param length\n  *   The upper limit on bytes to copy.  Passing UINT32_MAX\n  *   means all data (after offset).\n- * @param timestamp\n- *   The timestamp in TSC cycles.\n  * @param direction\n  *   The direction of the packer: receive, transmit or unknown.\n  * @param comment\n@@ -136,7 +134,7 @@ __rte_experimental\n struct rte_mbuf *\n rte_pcapng_copy(uint16_t port_id, uint32_t queue,\n \t\tconst struct rte_mbuf *m, struct rte_mempool *mp,\n-\t\tuint32_t length, uint64_t timestamp,\n+\t\tuint32_t length,\n \t\tenum rte_pcapng_direction direction, const char *comment);\n \n \n@@ -188,29 +186,22 @@ rte_pcapng_write_packets(rte_pcapng_t *self,\n  *  The handle to the packet capture file\n  * @param port\n  *  The Ethernet port to report stats on.\n- * @param comment\n- *   Optional comment to add to statistics.\n- * @param start_time\n- *  The time when packet capture was started in nanoseconds.\n- *  Optional: can be zero if not known.\n- * @param end_time\n- *  The time when packet capture was stopped in nanoseconds.\n- *  Optional: can be zero if not finished;\n  * @param ifrecv\n  *  The number of packets received by capture.\n  *  Optional: use UINT64_MAX if not known.\n  * @param ifdrop\n  *  The number of packets missed by the capture process.\n  *  Optional: use UINT64_MAX if not known.\n+ * @param comment\n+ *  Optional comment to add to statistics.\n  * @return\n  *  number of bytes written to file, -1 on failure to write file\n  */\n __rte_experimental\n ssize_t\n rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port,\n-\t\t       const char *comment,\n-\t\t       uint64_t start_time, uint64_t end_time,\n-\t\t       uint64_t ifrecv, uint64_t ifdrop);\n+\t\t       uint64_t ifrecv, uint64_t ifdrop,\n+\t\t       const char *comment);\n \n #ifdef __cplusplus\n }\ndiff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c\nindex a70085bd0211..903f92839b8e 100644\n--- a/lib/pdump/rte_pdump.c\n+++ b/lib/pdump/rte_pdump.c\n@@ -90,7 +90,6 @@ pdump_copy(uint16_t port_id, uint16_t queue,\n \tint ring_enq;\n \tuint16_t d_pkts = 0;\n \tstruct rte_mbuf *dup_bufs[nb_pkts];\n-\tuint64_t ts;\n \tstruct rte_ring *ring;\n \tstruct rte_mempool *mp;\n \tstruct rte_mbuf *p;\n@@ -99,7 +98,6 @@ pdump_copy(uint16_t port_id, uint16_t queue,\n \tif (cbs->filter)\n \t\trte_bpf_exec_burst(cbs->filter, (void **)pkts, rcs, nb_pkts);\n \n-\tts = rte_get_tsc_cycles();\n \tring = cbs->ring;\n \tmp = cbs->mp;\n \tfor (i = 0; i < nb_pkts; i++) {\n@@ -122,7 +120,7 @@ pdump_copy(uint16_t port_id, uint16_t queue,\n \t\tif (cbs->ver == V2)\n \t\t\tp = rte_pcapng_copy(port_id, queue,\n \t\t\t\t\t    pkts[i], mp, cbs->snaplen,\n-\t\t\t\t\t    ts, direction, NULL);\n+\t\t\t\t\t    direction, NULL);\n \t\telse\n \t\t\tp = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);\n \n",
    "prefixes": [
        "v2",
        "3/4"
    ]
}