Skip to content

Commit 59a0ad4

Browse files
committed
Merge branch 'tcp-take-better-care-of-tw_substate-and-tw_rcv_nxt'
Eric Dumazet says: ==================== tcp: take better care of tw_substate and tw_rcv_nxt While reviewing Jason Xing recent commit (0d9e5df "tcp: avoid reusing FIN_WAIT2 when trying to find port in connect() process") I saw we could remove the volatile qualifier for tw_substate field, and I also added missing data-race annotations around tcptw->tw_rcv_nxt. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 0fa5e94 + c0a1149 commit 59a0ad4

File tree

5 files changed

+26
-22
lines changed

5 files changed

+26
-22
lines changed

include/net/inet_timewait_sock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ struct inet_timewait_sock {
5858
#define tw_dr __tw_common.skc_tw_dr
5959

6060
__u32 tw_mark;
61-
volatile unsigned char tw_substate;
61+
unsigned char tw_substate;
6262
unsigned char tw_rcv_wscale;
6363

6464
/* Socket demultiplex comparisons on incoming packets. */

net/ipv4/inet_diag.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ static int inet_twsk_diag_fill(struct sock *sk,
442442
inet_diag_msg_common_fill(r, sk);
443443
r->idiag_retrans = 0;
444444

445-
r->idiag_state = tw->tw_substate;
445+
r->idiag_state = READ_ONCE(tw->tw_substate);
446446
r->idiag_timer = 3;
447447
tmo = tw->tw_timer.expires - jiffies;
448448
r->idiag_expires = jiffies_delta_to_msecs(tmo);
@@ -1209,7 +1209,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
12091209
if (num < s_num)
12101210
goto next_normal;
12111211
state = (sk->sk_state == TCP_TIME_WAIT) ?
1212-
inet_twsk(sk)->tw_substate : sk->sk_state;
1212+
READ_ONCE(inet_twsk(sk)->tw_substate) : sk->sk_state;
12131213
if (!(idiag_states & (1 << state)))
12141214
goto next_normal;
12151215
if (r->sdiag_family != AF_UNSPEC &&

net/ipv4/tcp_ipv4.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
120120
struct tcp_sock *tp = tcp_sk(sk);
121121
int ts_recent_stamp;
122122

123-
if (tw->tw_substate == TCP_FIN_WAIT2)
123+
if (READ_ONCE(tw->tw_substate) == TCP_FIN_WAIT2)
124124
reuse = 0;
125125

126126
if (reuse == 2) {
@@ -1073,7 +1073,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
10731073
}
10741074

10751075
tcp_v4_send_ack(sk, skb,
1076-
tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
1076+
tcptw->tw_snd_nxt, READ_ONCE(tcptw->tw_rcv_nxt),
10771077
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
10781078
tcp_tw_tsval(tcptw),
10791079
READ_ONCE(tcptw->tw_ts_recent),
@@ -2948,7 +2948,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw,
29482948

29492949
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
29502950
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
2951-
i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
2951+
i, src, srcp, dest, destp, READ_ONCE(tw->tw_substate), 0, 0,
29522952
3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
29532953
refcount_read(&tw->tw_refcnt), tw);
29542954
}

net/ipv4/tcp_minisocks.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,17 @@ tcp_timewait_check_oow_rate_limit(struct inet_timewait_sock *tw,
5252
return TCP_TW_SUCCESS;
5353
}
5454

55-
static void twsk_rcv_nxt_update(struct tcp_timewait_sock *tcptw, u32 seq)
55+
static void twsk_rcv_nxt_update(struct tcp_timewait_sock *tcptw, u32 seq,
56+
u32 rcv_nxt)
5657
{
5758
#ifdef CONFIG_TCP_AO
5859
struct tcp_ao_info *ao;
5960

6061
ao = rcu_dereference(tcptw->ao_info);
61-
if (unlikely(ao && seq < tcptw->tw_rcv_nxt))
62+
if (unlikely(ao && seq < rcv_nxt))
6263
WRITE_ONCE(ao->rcv_sne, ao->rcv_sne + 1);
6364
#endif
64-
tcptw->tw_rcv_nxt = seq;
65+
WRITE_ONCE(tcptw->tw_rcv_nxt, seq);
6566
}
6667

6768
/*
@@ -98,8 +99,9 @@ enum tcp_tw_status
9899
tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
99100
const struct tcphdr *th, u32 *tw_isn)
100101
{
101-
struct tcp_options_received tmp_opt;
102102
struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
103+
u32 rcv_nxt = READ_ONCE(tcptw->tw_rcv_nxt);
104+
struct tcp_options_received tmp_opt;
103105
bool paws_reject = false;
104106
int ts_recent_stamp;
105107

@@ -117,26 +119,26 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
117119
}
118120
}
119121

120-
if (tw->tw_substate == TCP_FIN_WAIT2) {
122+
if (READ_ONCE(tw->tw_substate) == TCP_FIN_WAIT2) {
121123
/* Just repeat all the checks of tcp_rcv_state_process() */
122124

123125
/* Out of window, send ACK */
124126
if (paws_reject ||
125127
!tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
126-
tcptw->tw_rcv_nxt,
127-
tcptw->tw_rcv_nxt + tcptw->tw_rcv_wnd))
128+
rcv_nxt,
129+
rcv_nxt + tcptw->tw_rcv_wnd))
128130
return tcp_timewait_check_oow_rate_limit(
129131
tw, skb, LINUX_MIB_TCPACKSKIPPEDFINWAIT2);
130132

131133
if (th->rst)
132134
goto kill;
133135

134-
if (th->syn && !before(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt))
136+
if (th->syn && !before(TCP_SKB_CB(skb)->seq, rcv_nxt))
135137
return TCP_TW_RST;
136138

137139
/* Dup ACK? */
138140
if (!th->ack ||
139-
!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) ||
141+
!after(TCP_SKB_CB(skb)->end_seq, rcv_nxt) ||
140142
TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) {
141143
inet_twsk_put(tw);
142144
return TCP_TW_SUCCESS;
@@ -146,12 +148,13 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
146148
* reset.
147149
*/
148150
if (!th->fin ||
149-
TCP_SKB_CB(skb)->end_seq != tcptw->tw_rcv_nxt + 1)
151+
TCP_SKB_CB(skb)->end_seq != rcv_nxt + 1)
150152
return TCP_TW_RST;
151153

152154
/* FIN arrived, enter true time-wait state. */
153-
tw->tw_substate = TCP_TIME_WAIT;
154-
twsk_rcv_nxt_update(tcptw, TCP_SKB_CB(skb)->end_seq);
155+
WRITE_ONCE(tw->tw_substate, TCP_TIME_WAIT);
156+
twsk_rcv_nxt_update(tcptw, TCP_SKB_CB(skb)->end_seq,
157+
rcv_nxt);
155158

156159
if (tmp_opt.saw_tstamp) {
157160
WRITE_ONCE(tcptw->tw_ts_recent_stamp,
@@ -182,7 +185,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
182185
*/
183186

184187
if (!paws_reject &&
185-
(TCP_SKB_CB(skb)->seq == tcptw->tw_rcv_nxt &&
188+
(TCP_SKB_CB(skb)->seq == rcv_nxt &&
186189
(TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq || th->rst))) {
187190
/* In window segment, it may be only reset or bare ack. */
188191

@@ -229,7 +232,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
229232
*/
230233

231234
if (th->syn && !th->rst && !th->ack && !paws_reject &&
232-
(after(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt) ||
235+
(after(TCP_SKB_CB(skb)->seq, rcv_nxt) ||
233236
(tmp_opt.saw_tstamp &&
234237
(s32)(READ_ONCE(tcptw->tw_ts_recent) - tmp_opt.rcv_tsval) < 0))) {
235238
u32 isn = tcptw->tw_snd_nxt + 65535 + 2;

net/ipv6/tcp_ipv6.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
11931193
#endif
11941194
}
11951195

1196-
tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
1196+
tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt,
1197+
READ_ONCE(tcptw->tw_rcv_nxt),
11971198
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
11981199
tcp_tw_tsval(tcptw),
11991200
READ_ONCE(tcptw->tw_ts_recent), tw->tw_bound_dev_if,
@@ -2258,7 +2259,7 @@ static void get_timewait6_sock(struct seq_file *seq,
22582259
src->s6_addr32[2], src->s6_addr32[3], srcp,
22592260
dest->s6_addr32[0], dest->s6_addr32[1],
22602261
dest->s6_addr32[2], dest->s6_addr32[3], destp,
2261-
tw->tw_substate, 0, 0,
2262+
READ_ONCE(tw->tw_substate), 0, 0,
22622263
3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
22632264
refcount_read(&tw->tw_refcnt), tw);
22642265
}

0 commit comments

Comments
 (0)