net: add new control message for incoming HW-timestamped packets
Add SOF_TIMESTAMPING_OPT_PKTINFO option to request a new control message for incoming packets with hardware timestamps. It contains the index of the real interface which received the packet and the length of the packet at layer 2. The index is useful with bonding, bridges and other interfaces, where IP_PKTINFO doesn't allow applications to determine which PHC made the timestamp. With the L2 length (and link speed) it is possible to transpose preamble timestamps to trailer timestamps, which are used in the NTP protocol. While this information could be provided by two new socket options independently from timestamping, it doesn't look like they would be very useful. With this option any performance impact is limited to hardware timestamping. Use dev_get_by_napi_id() to get the device and its index. On kernels with disabled CONFIG_NET_RX_BUSY_POLL or drivers not using NAPI, a zero index will be returned in the control message. CC: Richard Cochran <richardcochran@gmail.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
90b602f803
commit
aad9c8c470
27
net/socket.c
27
net/socket.c
@ -662,6 +662,27 @@ static bool skb_is_err_queue(const struct sk_buff *skb)
|
||||
return skb->pkt_type == PACKET_OUTGOING;
|
||||
}
|
||||
|
||||
static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
|
||||
{
|
||||
struct scm_ts_pktinfo ts_pktinfo;
|
||||
struct net_device *orig_dev;
|
||||
|
||||
if (!skb_mac_header_was_set(skb))
|
||||
return;
|
||||
|
||||
memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
|
||||
|
||||
rcu_read_lock();
|
||||
orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
|
||||
if (orig_dev)
|
||||
ts_pktinfo.if_index = orig_dev->ifindex;
|
||||
rcu_read_unlock();
|
||||
|
||||
ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
|
||||
sizeof(ts_pktinfo), &ts_pktinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
|
||||
*/
|
||||
@ -699,8 +720,12 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
||||
empty = 0;
|
||||
if (shhwtstamps &&
|
||||
(sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
|
||||
ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
|
||||
ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
|
||||
empty = 0;
|
||||
if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
|
||||
!skb_is_err_queue(skb))
|
||||
put_ts_pktinfo(msg, skb);
|
||||
}
|
||||
if (!empty) {
|
||||
put_cmsg(msg, SOL_SOCKET,
|
||||
SCM_TIMESTAMPING, sizeof(tss), &tss);
|
||||
|
Reference in New Issue
Block a user