From: Marek Kasiewicz <[email protected]>

Add rte_pcapng_copy_ts() which accepts a timestamp parameter in
nanoseconds since the Unix epoch. When non-zero, the supplied value is
used directly. This allows applications to provide hardware PTP
timestamps from the NIC, enabling accurate packet capture with
PTP-domain timing rather than host-local TSC values.

The existing rte_pcapng_copy() function is preserved as a static
inline wrapper that passes zero, keeping the original TSC-based
behaviour for callers that do not have a hardware timestamp.

To support both timestamp sources, the per-mbuf timestamp now carries
a sentinel bit: when rte_pcapng_copy_ts() is called with ts == 0 it
stores the current TSC with bit 63 set. rte_pcapng_write_packets()
detects the sentinel, clears it and converts TSC -> epoch ns using
the per-file clock before writing. A timestamp supplied by the caller
has bit 63 clear and is written unchanged. The sentinel space is safe
because the TSC counter does not reach bit 63 for centuries and
epoch-ns values stay below bit 63 until the year 2554.

Signed-off-by: Marek Kasiewicz <[email protected]>
Signed-off-by: Dawid Wesierski <[email protected]>
---
 .mailmap                |  2 ++
 lib/pcapng/rte_pcapng.c | 42 +++++++++++++++++++++++++++-------------
 lib/pcapng/rte_pcapng.h | 43 +++++++++++++++++++++++++++++++++++++++--
 3 files changed, 72 insertions(+), 15 deletions(-)

diff --git a/.mailmap b/.mailmap
index 4001e5fb0e..a7d97a631e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -366,6 +366,7 @@ David Zeng <[email protected]>
 Davide Caratti <[email protected]>
 Dawid Gorecki <[email protected]>
 Dawid Jurczak <[email protected]>
+Dawid Wesierski <[email protected]> Wesierski, Dawid 
<[email protected]>
 Dawid Zielinski <[email protected]>
 Dawid Łukwiński <[email protected]>
 Daxue Gao <[email protected]>
@@ -1014,6 +1015,7 @@ Marcin Wilk <[email protected]>
 Marcin Wojtas <[email protected]>
 Marcin Zapolski <[email protected]>
 Marco Varlese <[email protected]>
+Marek Kasiewicz <[email protected]>
 Marek Mical <[email protected]>
 Marek Zalfresso-jundzillo <[email protected]>
 Maria Lingemark <[email protected]>
diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index b5d1026891..29090a2ae4 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -546,14 +546,14 @@ pcapng_vlan_insert(struct rte_mbuf *m, uint16_t 
ether_type, uint16_t tci)
  */
 
 /* Make a copy of original mbuf with pcapng header and options */
-RTE_EXPORT_SYMBOL(rte_pcapng_copy)
+RTE_EXPORT_SYMBOL(rte_pcapng_copy_ts)
 struct rte_mbuf *
-rte_pcapng_copy(uint16_t port_id, uint32_t queue,
+rte_pcapng_copy_ts(uint16_t port_id, uint32_t queue,
                const struct rte_mbuf *md,
                struct rte_mempool *mp,
                uint32_t length,
                enum rte_pcapng_direction direction,
-               const char *comment)
+               const char *comment, uint64_t ts)
 {
        struct pcapng_enhance_packet_block *epb;
        uint32_t orig_len, pkt_len, padding, flags;
@@ -690,8 +690,20 @@ rte_pcapng_copy(uint16_t port_id, uint32_t queue,
        /* Interface index is filled in later during write */
        mc->port = port_id;
 
-       /* Put timestamp in cycles here - adjust in packet write */
-       timestamp = rte_get_tsc_cycles();
+       /*
+        * Timestamp handling:
+        *  - If the caller supplied an explicit timestamp (ts != 0), it is
+        *    already in nanoseconds since the Unix epoch, so store it as-is.
+        *  - If the caller did not (ts == 0), store the current TSC and set
+        *    the high bit as a sentinel so rte_pcapng_write_packets() knows
+        *    it must convert TSC -> epoch ns at write time. The TSC counter
+        *    will not reach bit 63 for centuries, and epoch-ns values stay
+        *    below bit 63 until the year 2554, so the bit is safe to use.
+        */
+       if (ts != 0)
+               timestamp = ts;
+       else
+               timestamp = rte_get_tsc_cycles() | (UINT64_C(1) << 63);
        epb->timestamp_hi = timestamp >> 32;
        epb->timestamp_lo = (uint32_t)timestamp;
        epb->capture_length = pkt_len;
@@ -720,7 +732,7 @@ rte_pcapng_write_packets(rte_pcapng_t *self,
        for (i = 0; i < nb_pkts; i++) {
                struct rte_mbuf *m = pkts[i];
                struct pcapng_enhance_packet_block *epb;
-               uint64_t cycles, timestamp;
+               uint64_t timestamp;
 
                /* sanity check that is really a pcapng mbuf */
                epb = rte_pktmbuf_mtod(m, struct pcapng_enhance_packet_block *);
@@ -738,14 +750,18 @@ rte_pcapng_write_packets(rte_pcapng_t *self,
                }
 
                /*
-                * When data is captured by pcapng_copy the current TSC is 
stored.
-                * Adjust the value recorded in file to PCAP epoch units.
+                * If rte_pcapng_copy[_ts]() stored a TSC value (high bit set
+                * as sentinel), convert it to nanoseconds since the Unix epoch
+                * using the per-file clock. Otherwise the timestamp is already
+                * in epoch ns and is written unchanged.
                 */
-               cycles = (uint64_t)epb->timestamp_hi << 32;
-               cycles += epb->timestamp_lo;
-               timestamp = tsc_to_ns_epoch(&self->clock, cycles);
-               epb->timestamp_hi = timestamp >> 32;
-               epb->timestamp_lo = (uint32_t)timestamp;
+               timestamp = ((uint64_t)epb->timestamp_hi << 32) | 
epb->timestamp_lo;
+               if (timestamp & (UINT64_C(1) << 63)) {
+                       timestamp &= ~(UINT64_C(1) << 63);
+                       timestamp = tsc_to_ns_epoch(&self->clock, timestamp);
+                       epb->timestamp_hi = timestamp >> 32;
+                       epb->timestamp_lo = (uint32_t)timestamp;
+               }
 
                /*
                 * Handle case of highly fragmented and large burst size
diff --git a/lib/pcapng/rte_pcapng.h b/lib/pcapng/rte_pcapng.h
index d8d328f710..975e7996f0 100644
--- a/lib/pcapng/rte_pcapng.h
+++ b/lib/pcapng/rte_pcapng.h
@@ -109,7 +109,7 @@ enum rte_pcapng_direction {
 };
 
 /**
- * Format an mbuf for writing to file.
+ * Format an mbuf with time stamp for writing to file.
  *
  * @param port_id
  *   The Ethernet port on which packet was received
@@ -129,16 +129,55 @@ enum rte_pcapng_direction {
  * @param comment
  *   Optional per packet comment.
  *   Truncated to UINT16_MAX characters.
+ * @param ts
+ *   Packet timestamp in nanoseconds since the Unix epoch. If zero, the
+ *   current TSC is captured and converted to epoch ns by
+ *   rte_pcapng_write_packets() when the packet is written.
  *
  * @return
  *   - The pointer to the new mbuf formatted for pcapng_write
  *   - NULL on error such as invalid port or out of memory.
  */
 struct rte_mbuf *
+rte_pcapng_copy_ts(uint16_t port_id, uint32_t queue,
+               const struct rte_mbuf *m, struct rte_mempool *mp,
+               uint32_t length,
+               enum rte_pcapng_direction direction, const char *comment, 
uint64_t ts);
+
+/**
+ * Format an mbuf for writing to file.
+ *
+ * @param port_id
+ *   The Ethernet port on which packet was received
+ *   or is going to be transmitted.
+ * @param queue
+ *   The queue on the Ethernet port where packet was received
+ *   or is going to be transmitted.
+ * @param mp
+ *   The mempool from which the "clone" mbufs are allocated.
+ * @param m
+ *   The mbuf to copy
+ * @param length
+ *   The upper limit on bytes to copy.  Passing UINT32_MAX
+ *   means all data (after offset).
+ * @param direction
+ *   The direction of the packer: receive, transmit or unknown.
+ * @param comment
+ *   Packet comment.
+ *
+ * @return
+ *   - The pointer to the new mbuf formatted for pcapng_write
+ *   - NULL if allocation fails.
+ */
+static inline struct rte_mbuf *
 rte_pcapng_copy(uint16_t port_id, uint32_t queue,
                const struct rte_mbuf *m, struct rte_mempool *mp,
                uint32_t length,
-               enum rte_pcapng_direction direction, const char *comment);
+               enum rte_pcapng_direction direction, const char *comment)
+{
+       return rte_pcapng_copy_ts(port_id, queue, m, mp, length, direction,
+                                 comment, 0);
+}
 
 
 /**
-- 
2.47.3

---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial 
Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | 
Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z 
dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach 
handlowych.

Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i 
moze zawierac informacje poufne. W razie przypadkowego otrzymania tej 
wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; 
jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole 
use of the intended recipient(s). If you are not the intended recipient, please 
contact the sender and delete all copies; any review or distribution by others 
is strictly prohibited.

Reply via email to