get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131758,
    "url": "https://patches.dpdk.org/api/patches/131758/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230921042349.104150-5-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": "<20230921042349.104150-5-stephen@networkplumber.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230921042349.104150-5-stephen@networkplumber.org",
    "date": "2023-09-21T04:23:49",
    "name": "[4/4] pcapng: move timestamp calculation into pdump",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "709927edfabc3083e81bc560d89f7f5f8279fdb6",
    "submitter": {
        "id": 27,
        "url": "https://patches.dpdk.org/api/people/27/?format=api",
        "name": "Stephen Hemminger",
        "email": "stephen@networkplumber.org"
    },
    "delegate": {
        "id": 24651,
        "url": "https://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20230921042349.104150-5-stephen@networkplumber.org/mbox/",
    "series": [
        {
            "id": 29581,
            "url": "https://patches.dpdk.org/api/series/29581/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29581",
            "date": "2023-09-21T04:23:45",
            "name": "pcapng fixes",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/29581/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/131758/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/131758/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 ECD51425DC;\n\tThu, 21 Sep 2023 06:24:28 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 820AB4067B;\n\tThu, 21 Sep 2023 06:24:09 +0200 (CEST)",
            "from mail-oi1-f180.google.com (mail-oi1-f180.google.com\n [209.85.167.180])\n by mails.dpdk.org (Postfix) with ESMTP id D0C20402E0\n for <dev@dpdk.org>; Thu, 21 Sep 2023 06:24:05 +0200 (CEST)",
            "by mail-oi1-f180.google.com with SMTP id\n 5614622812f47-3ade1011f8cso368537b6e.0\n for <dev@dpdk.org>; Wed, 20 Sep 2023 21:24:05 -0700 (PDT)",
            "from hermes.local (204-195-112-131.wavecable.com. [204.195.112.131])\n by smtp.gmail.com with ESMTPSA id\n u5-20020aa78485000000b00690d1269691sm311946pfn.22.2023.09.20.21.24.03\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 20 Sep 2023 21:24:04 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1695270245;\n x=1695875045; 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=v9D23f4qgr4f2T2Rqt+XYQxDpkW7uq0g6x8hWZbE/U4=;\n b=CDNbPrS4+KXx9RCONK8FY7qDcN1dYGG/fPqsViYW6GA35zvv8yVku6UMmWn1irtmGE\n C+if6nB3hxtku+4siknAY138nVUU/CddNjqOPd0yKpaCYaKZd+uwc1jz37QeRszB9x38\n ERBzhom8I2DjP4s3u4ShjPykxqv/a8Cyc3ZnwNnmIQyjmR+9IoqeO4CgFPaK0qp+UI4z\n 2FEt4TchXKXGOVwTKu32UL/yLHgNurHcueJAi7zUoRf69ADP6F02DrjqDnXAwI/hLg5r\n w5+BlEscZ8pxuOxXs4s4XWUZdQ1p6HO6TIA98Q60KRAYjML9MOI0xgQWR6v95tDxWF8u\n ATmw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1695270245; x=1695875045;\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=v9D23f4qgr4f2T2Rqt+XYQxDpkW7uq0g6x8hWZbE/U4=;\n b=Epg0JqvrFBR9Iat2qYWrAIb+38Kb7WCrnw4MTYmkWIRuZlwf7TFOQ/lwFsW7NlI/j8\n 3GPSZq+r3QBT80r1us0cJ1dhanAGKnlJkhZsQ15FxNWa+DIU1z2M+mX99Ief6xVK5uWX\n yREpGzodurE6trFgHGxhQIz9qaAqptfsPiiLXRE5LRUX+/nu8jp2uceqciaAyLrwD14V\n oo4Jis6pMKPsbEaXSmXziqtsaVOtwDM90PfuBJk1Vm+CwWV0tCURHry3qp3HPkAry98k\n 2KkOB3hfQScofyv3CgkFaWiXpb8nIhMvoWiYQywOe8pcbSfgWyyO+DzQbQXi3U2vXEUu\n m8mg==",
        "X-Gm-Message-State": "AOJu0Yxk+ps1igR7K/sDVk8/a3ADDtsTsI5f4To0ncqxeoYXOeWHILCJ\n GOrte078m5g9C/QZ1+HKb5/14OlKv0r78h8w2gc=",
        "X-Google-Smtp-Source": "\n AGHT+IHUvMo7kH1GvKMxHvk7tq4MfVlUDqvmk18WaclEGAhNRS+IBF5+HBsTvdj5rTXazSPfS7W8WQ==",
        "X-Received": "by 2002:a05:6870:9a24:b0:1d6:439d:d03e with SMTP id\n fo36-20020a0568709a2400b001d6439dd03emr4796780oab.18.1695270244838;\n Wed, 20 Sep 2023 21:24:04 -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>,\n Quentin Armitage <quentin@armitage.org.uk>",
        "Subject": "[PATCH 4/4] pcapng: move timestamp calculation into pdump",
        "Date": "Wed, 20 Sep 2023 21:23:49 -0700",
        "Message-Id": "<20230921042349.104150-5-stephen@networkplumber.org>",
        "X-Mailer": "git-send-email 2.39.2",
        "In-Reply-To": "<20230921042349.104150-1-stephen@networkplumber.org>",
        "References": "<20230921042349.104150-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 more easily done in pdump\nthan pcapng. The initialization is easier and makes the pcapng\nlibrary have no global state.\n\nIt also makes it easier to add HW timestamp support later.\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 lib/pcapng/rte_pcapng.c | 71 ++---------------------------------------\n lib/pcapng/rte_pcapng.h |  2 +-\n lib/pdump/rte_pdump.c   | 56 +++++++++++++++++++++++++++++---\n 3 files changed, 55 insertions(+), 74 deletions(-)",
    "diff": "diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c\nindex ddce7bc87141..f6b3bd0ca718 100644\n--- a/lib/pcapng/rte_pcapng.c\n+++ b/lib/pcapng/rte_pcapng.c\n@@ -25,7 +25,6 @@\n #include <rte_mbuf.h>\n #include <rte_os_shim.h>\n #include <rte_pcapng.h>\n-#include <rte_reciprocal.h>\n #include <rte_time.h>\n \n #include \"pcapng_proto.h\"\n@@ -43,15 +42,6 @@ struct rte_pcapng {\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,58 +92,6 @@ 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-{\n-\tstruct timespec ts;\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-\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-\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-}\n-\n /* length of option including padding */\n static uint16_t pcapng_optlen(uint16_t len)\n {\n@@ -518,7 +456,7 @@ 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, uint64_t timestamp,\n \t\tenum rte_pcapng_direction direction,\n \t\tconst char *comment)\n {\n@@ -527,14 +465,11 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,\n \tstruct pcapng_option *opt;\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@@ -639,8 +574,8 @@ 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+\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 \ndiff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h\nindex 1225ed5536ff..b9a9ee23ad1d 100644\n--- a/lib/pcapng/rte_pcapng.h\n+++ b/lib/pcapng/rte_pcapng.h\n@@ -122,7 +122,7 @@ enum rte_pcapng_direction {\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+ *   The timestamp in nanoseconds since 1/1/1970.\n  * @param direction\n  *   The direction of the packer: receive, transmit or unknown.\n  * @param comment\ndiff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c\nindex a70085bd0211..384abf5e27ad 100644\n--- a/lib/pdump/rte_pdump.c\n+++ b/lib/pdump/rte_pdump.c\n@@ -10,7 +10,9 @@\n #include <rte_log.h>\n #include <rte_memzone.h>\n #include <rte_errno.h>\n+#include <rte_reciprocal.h>\n #include <rte_string_fns.h>\n+#include <rte_time.h>\n #include <rte_pcapng.h>\n \n #include \"rte_pdump.h\"\n@@ -78,6 +80,33 @@ static struct {\n \tconst struct rte_memzone *mz;\n } *pdump_stats;\n \n+/* Time conversion values */\n+static struct {\n+\tuint64_t offset_ns;\t/* ns since 1/1/1970 when initialized */\n+\tuint64_t tsc_base;\t/* TSC when initialized */\n+\tuint64_t tsc_hz;\t/* copy of rte_tsc_hz() */\n+\tstruct rte_reciprocal_u64 tsc_hz_inverse; /* inverse of tsc_hz */\n+} pdump_time;\n+\n+/* Convert from TSC (CPU cycles) to nanoseconds */\n+static uint64_t pdump_timestamp(void)\n+{\n+\tuint64_t delta, secs, ns;\n+\n+\tdelta = rte_get_tsc_cycles() - pdump_time.tsc_base;\n+\n+\t/* Avoid numeric wraparound by computing seconds first */\n+\tsecs = rte_reciprocal_divide_u64(delta, &pdump_time.tsc_hz_inverse);\n+\n+\t/* Remove the seconds portion */\n+\tdelta -= secs * pdump_time.tsc_hz;\n+\tns = rte_reciprocal_divide_u64(delta * NS_PER_S,\n+\t\t\t\t       &pdump_time.tsc_hz_inverse);\n+\n+\treturn secs * NS_PER_S + ns + pdump_time.offset_ns;\n+}\n+\n+\n /* Create a clone of mbuf to be placed into ring. */\n static void\n pdump_copy(uint16_t port_id, uint16_t queue,\n@@ -90,7 +119,7 @@ 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+\tuint64_t timestamp = 0;\n \tstruct rte_ring *ring;\n \tstruct rte_mempool *mp;\n \tstruct rte_mbuf *p;\n@@ -99,7 +128,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@@ -119,12 +147,17 @@ pdump_copy(uint16_t port_id, uint16_t queue,\n \t\t * If using pcapng then want to wrap packets\n \t\t * otherwise a simple copy.\n \t\t */\n-\t\tif (cbs->ver == V2)\n+\t\tif (cbs->ver == V2) {\n+\t\t\t/* calculate timestamp on first packet */\n+\t\t\tif (timestamp == 0)\n+\t\t\t\ttimestamp = pdump_timestamp();\n+\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\telse\n+\t\t\t\t\t    timestamp, direction, NULL);\n+\t\t} else {\n \t\t\tp = rte_pktmbuf_copy(pkts[i], mp, 0, cbs->snaplen);\n+\t\t}\n \n \t\tif (unlikely(p == NULL))\n \t\t\t__atomic_fetch_add(&stats->nombuf, 1, __ATOMIC_RELAXED);\n@@ -421,8 +454,21 @@ int\n rte_pdump_init(void)\n {\n \tconst struct rte_memzone *mz;\n+\tstruct timespec ts;\n+\tuint64_t cycles;\n \tint ret;\n \n+\t/* Compute time base offsets */\n+\tcycles = rte_get_tsc_cycles();\n+\tclock_gettime(CLOCK_REALTIME, &ts);\n+\n+\t/* put initial TSC value in middle of clock_gettime() call */\n+\tpdump_time.tsc_base = (cycles + rte_get_tsc_cycles()) / 2;\n+\tpdump_time.offset_ns = rte_timespec_to_ns(&ts);\n+\n+\tpdump_time.tsc_hz = rte_get_tsc_hz();\n+\tpdump_time.tsc_hz_inverse = rte_reciprocal_value_u64(pdump_time.tsc_hz);\n+\n \tmz = rte_memzone_reserve(MZ_RTE_PDUMP_STATS, sizeof(*pdump_stats),\n \t\t\t\t rte_socket_id(), 0);\n \tif (mz == NULL) {\n",
    "prefixes": [
        "4/4"
    ]
}