Skip to content

Commit 4ef1b28

Browse files
soheilhydavem330
authored andcommitted
tcp: mark skbs with SCM_TIMESTAMPING_OPT_STATS
SOF_TIMESTAMPING_OPT_STATS can be enabled and disabled while packets are collected on the error queue. So, checking SOF_TIMESTAMPING_OPT_STATS in sk->sk_tsflags is not enough to safely assume that the skb contains OPT_STATS data. Add a bit in sock_exterr_skb to indicate whether the skb contains opt_stats data. Fixes: 1c88580 ("tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING") Reported-by: JongHwan Kim <[email protected]> Signed-off-by: Soheil Hassas Yeganeh <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8605330 commit 4ef1b28

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

include/linux/errqueue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ struct sock_exterr_skb {
2020
struct sock_extended_err ee;
2121
u16 addr_offset;
2222
__be16 port;
23+
u8 opt_stats:1,
24+
unused:7;
2325
};
2426

2527
#endif

net/core/skbuff.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3793,16 +3793,20 @@ EXPORT_SYMBOL(skb_clone_sk);
37933793

37943794
static void __skb_complete_tx_timestamp(struct sk_buff *skb,
37953795
struct sock *sk,
3796-
int tstype)
3796+
int tstype,
3797+
bool opt_stats)
37973798
{
37983799
struct sock_exterr_skb *serr;
37993800
int err;
38003801

3802+
BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb));
3803+
38013804
serr = SKB_EXT_ERR(skb);
38023805
memset(serr, 0, sizeof(*serr));
38033806
serr->ee.ee_errno = ENOMSG;
38043807
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
38053808
serr->ee.ee_info = tstype;
3809+
serr->opt_stats = opt_stats;
38063810
if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
38073811
serr->ee.ee_data = skb_shinfo(skb)->tskey;
38083812
if (sk->sk_protocol == IPPROTO_TCP &&
@@ -3843,7 +3847,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb,
38433847
*/
38443848
if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) {
38453849
*skb_hwtstamps(skb) = *hwtstamps;
3846-
__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
3850+
__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false);
38473851
sock_put(sk);
38483852
}
38493853
}
@@ -3854,7 +3858,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
38543858
struct sock *sk, int tstype)
38553859
{
38563860
struct sk_buff *skb;
3857-
bool tsonly;
3861+
bool tsonly, opt_stats = false;
38583862

38593863
if (!sk)
38603864
return;
@@ -3867,9 +3871,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
38673871
#ifdef CONFIG_INET
38683872
if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
38693873
sk->sk_protocol == IPPROTO_TCP &&
3870-
sk->sk_type == SOCK_STREAM)
3874+
sk->sk_type == SOCK_STREAM) {
38713875
skb = tcp_get_timestamping_opt_stats(sk);
3872-
else
3876+
opt_stats = true;
3877+
} else
38733878
#endif
38743879
skb = alloc_skb(0, GFP_ATOMIC);
38753880
} else {
@@ -3888,7 +3893,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
38883893
else
38893894
skb->tstamp = ktime_get_real();
38903895

3891-
__skb_complete_tx_timestamp(skb, sk, tstype);
3896+
__skb_complete_tx_timestamp(skb, sk, tstype, opt_stats);
38923897
}
38933898
EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
38943899

net/socket.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
706706
SCM_TIMESTAMPING, sizeof(tss), &tss);
707707

708708
if (skb_is_err_queue(skb) && skb->len &&
709-
(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
709+
SKB_EXT_ERR(skb)->opt_stats)
710710
put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
711711
skb->len, skb->data);
712712
}

0 commit comments

Comments
 (0)