@@ -2600,12 +2600,13 @@ static inline void sock_write_timestamp(struct sock *sk, ktime_t kt)
}
void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
- struct sk_buff *skb);
+ struct sk_buff *skb, bool errqueue);
void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb);
static inline void
-sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
+sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb,
+ bool errqueue)
{
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
u32 tsflags = READ_ONCE(sk->sk_tsflags);
@@ -2617,11 +2618,11 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
* - hardware time stamps available and wanted
*/
if (sock_flag(sk, SOCK_RCVTSTAMP) ||
- (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
- (kt && tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
+ ((tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || errqueue) &&
+ (kt && tsflags & SOF_TIMESTAMPING_SOFTWARE)) ||
(hwtstamps->hwtstamp &&
(tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
- __sock_recv_timestamp(msg, sk, skb);
+ __sock_recv_timestamp(msg, sk, skb, errqueue);
else
sock_write_timestamp(sk, kt);
@@ -1586,11 +1586,11 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
break;
case HCI_CHANNEL_USER:
case HCI_CHANNEL_MONITOR:
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
break;
default:
if (hci_mgmt_chan_find(hci_pi(sk)->channel))
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
break;
}
@@ -3677,7 +3677,7 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
if (err)
goto out_free_skb;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, true);
serr = SKB_EXT_ERR(skb);
put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
@@ -547,7 +547,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
kfree_skb(skb);
return err;
}
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, true);
serr = SKB_EXT_ERR(skb);
@@ -880,7 +880,7 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
if (err)
goto done;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
/* Copy the address and add cmsg data. */
if (family == AF_INET) {
@@ -479,7 +479,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
kfree_skb(skb);
return err;
}
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, true);
serr = SKB_EXT_ERR(skb);
@@ -568,7 +568,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
if (err)
goto out_free_skb;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
memcpy(&mtu_info, IP6CBMTU(skb), sizeof(mtu_info));
@@ -567,7 +567,7 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg,
if (err)
goto done;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
/* Copy the address. */
if (sin) {
@@ -712,7 +712,7 @@ static int l2tp_ip6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
if (err)
goto done;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
/* Copy the address. */
if (lsa) {
@@ -869,7 +869,7 @@ static int llcp_sock_recvmsg(struct socket *sock, struct msghdr *msg,
return -EFAULT;
}
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
if (sk->sk_type == SOCK_DGRAM && msg->msg_name) {
struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb);
@@ -200,7 +200,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
sp->hdr.serial, seq);
if (msg)
- sock_recv_timestamp(msg, sock->sk, skb);
+ sock_recv_timestamp(msg, sock->sk, skb, false);
if (rx_pkt_offset == 0) {
ret2 = rxrpc_verify_data(call, skb);
@@ -893,7 +893,7 @@ static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
* called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
*/
void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
- struct sk_buff *skb)
+ struct sk_buff *skb, bool errqueue)
{
int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
@@ -946,7 +946,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
memset(&tss, 0, sizeof(tss));
tsflags = READ_ONCE(sk->sk_tsflags);
- if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
+ if ((tsflags & SOF_TIMESTAMPING_SOFTWARE &&
+ (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || errqueue)) &&
ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
empty = 0;
if (shhwtstamps &&
@@ -1024,7 +1025,7 @@ static void sock_recv_mark(struct msghdr *msg, struct sock *sk,
void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb)
{
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb, false);
sock_recv_drops(msg, sk, skb);
sock_recv_mark(msg, sk, skb);
}
@@ -2481,7 +2481,7 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
goto out_free;
if (sock_flag(sk, SOCK_RCVTSTAMP))
- __sock_recv_timestamp(msg, sk, skb);
+ __sock_recv_timestamp(msg, sk, skb, false);
memset(&scm, 0, sizeof(scm));