|
@@ -662,6 +662,27 @@ static bool skb_is_err_queue(const struct sk_buff *skb)
|
|
return skb->pkt_type == PACKET_OUTGOING;
|
|
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)
|
|
* 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;
|
|
empty = 0;
|
|
if (shhwtstamps &&
|
|
if (shhwtstamps &&
|
|
(sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
|
|
(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;
|
|
empty = 0;
|
|
|
|
+ if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
|
|
|
|
+ !skb_is_err_queue(skb))
|
|
|
|
+ put_ts_pktinfo(msg, skb);
|
|
|
|
+ }
|
|
if (!empty) {
|
|
if (!empty) {
|
|
put_cmsg(msg, SOL_SOCKET,
|
|
put_cmsg(msg, SOL_SOCKET,
|
|
SCM_TIMESTAMPING, sizeof(tss), &tss);
|
|
SCM_TIMESTAMPING, sizeof(tss), &tss);
|