Commit 2e31396f authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller
Browse files

packet: tx timestamping on tpacket ring

When transmit timestamping is enabled at the socket level, record a
timestamp on packets written to a PACKET_TX_RING. Tx timestamps are
always looped to the application over the socket error queue. Software
timestamps are also written back into the packet frame header in the
packet ring.
Reported-by: default avatarPaul Chavent <>
Signed-off-by: default avatarWillem de Bruijn <>
Signed-off-by: default avatarDavid S. Miller <>
parent 92dea7c0
......@@ -3327,12 +3327,8 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
if (!sk)
skb = skb_clone(orig_skb, GFP_ATOMIC);
if (!skb)
if (hwtstamps) {
*skb_hwtstamps(skb) =
*skb_hwtstamps(orig_skb) =
} else {
......@@ -3340,9 +3336,13 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
* so keep the shared tx_flags and only
* store software time stamp
skb->tstamp = ktime_get_real();
orig_skb->tstamp = ktime_get_real();
skb = skb_clone(orig_skb, GFP_ATOMIC);
if (!skb)
serr = SKB_EXT_ERR(skb);
memset(serr, 0, sizeof(*serr));
serr->ee.ee_errno = ENOMSG;
......@@ -339,6 +339,37 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
static void __packet_set_timestamp(struct packet_sock *po, void *frame,
ktime_t tstamp)
union tpacket_uhdr h;
struct timespec ts;
if (!ktime_to_timespec_cond(tstamp, &ts) ||
!sock_flag(&po->sk, SOCK_TIMESTAMPING_SOFTWARE))
h.raw = frame;
switch (po->tp_version) {
case TPACKET_V1:
h.h1->tp_sec = ts.tv_sec;
h.h1->tp_usec = ts.tv_nsec / NSEC_PER_USEC;
case TPACKET_V2:
h.h2->tp_sec = ts.tv_sec;
h.h2->tp_nsec = ts.tv_nsec;
case TPACKET_V3:
WARN(1, "TPACKET version not supported.\n");
/* one flush is safe, as both fields always lie on the same cacheline */
static void *packet_lookup_frame(struct packet_sock *po,
struct packet_ring_buffer *rb,
unsigned int position,
......@@ -1877,6 +1908,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
ph = skb_shinfo(skb)->destructor_arg;
BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
__packet_set_timestamp(po, ph, skb->tstamp);
__packet_set_status(po, ph, TP_STATUS_AVAILABLE);
......@@ -1900,6 +1932,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
skb->dev = dev;
skb->priority = po->sk.sk_priority;
skb->mark = po->sk.sk_mark;
sock_tx_timestamp(&po->sk, &skb_shinfo(skb)->tx_flags);
skb_shinfo(skb)->destructor_arg = ph.raw;
switch (po->tp_version) {
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment