Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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 <paul.chavent@onera.fr>
Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92dea7c0
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -3327,12 +3327,8 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
	if (!sk)
		return;

	skb = skb_clone(orig_skb, GFP_ATOMIC);
	if (!skb)
		return;

	if (hwtstamps) {
		*skb_hwtstamps(skb) =
		*skb_hwtstamps(orig_skb) =
			*hwtstamps;
	} 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)
		return;

	serr = SKB_EXT_ERR(skb);
	memset(serr, 0, sizeof(*serr));
	serr->ee.ee_errno = ENOMSG;
+33 −0
Original line number Diff line number Diff line
@@ -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))
		return;

	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;
		break;
	case TPACKET_V2:
		h.h2->tp_sec = ts.tv_sec;
		h.h2->tp_nsec = ts.tv_nsec;
		break;
	case TPACKET_V3:
	default:
		WARN(1, "TPACKET version not supported.\n");
		BUG();
	}

	/* one flush is safe, as both fields always lie on the same cacheline */
	flush_dcache_page(pgv_to_page(&h.h1->tp_sec));
	smp_wmb();
}

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);
		atomic_dec(&po->tx_ring.pending);
		__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) {