Skip to content

Commit 89278c9

Browse files
yuchungchengdavem330
authored andcommitted
tcp: simplify fast open cookie processing
Consolidate various cookie checking and generation code to simplify the fast open processing. The main goal is to reduce code duplication in tcp_v4_conn_request() for IPv6 support. Removes two experimental sysctl flags TFO_SERVER_ALWAYS and TFO_SERVER_COOKIE_NOT_CHKD used primarily for developmental debugging purposes. Signed-off-by: Yuchung Cheng <[email protected]> Signed-off-by: Daniel Lee <[email protected]> Signed-off-by: Jerry Chu <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Acked-by: Neal Cardwell <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5b7ed08 commit 89278c9

File tree

5 files changed

+33
-64
lines changed

5 files changed

+33
-64
lines changed

include/linux/tcp.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,6 @@ static inline bool tcp_passive_fastopen(const struct sock *sk)
366366
tcp_sk(sk)->fastopen_rsk != NULL);
367367
}
368368

369-
static inline bool fastopen_cookie_present(struct tcp_fastopen_cookie *foc)
370-
{
371-
return foc->len != -1;
372-
}
373-
374369
extern void tcp_sock_destruct(struct sock *sk);
375370

376371
static inline int fastopen_init_queue(struct sock *sk, int backlog)

include/net/tcp.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,6 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
220220
#define TFO_SERVER_ENABLE 2
221221
#define TFO_CLIENT_NO_COOKIE 4 /* Data in SYN w/o cookie option */
222222

223-
/* Process SYN data but skip cookie validation */
224-
#define TFO_SERVER_COOKIE_NOT_CHKED 0x100
225223
/* Accept SYN data w/o any cookie option */
226224
#define TFO_SERVER_COOKIE_NOT_REQD 0x200
227225

@@ -230,10 +228,6 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
230228
*/
231229
#define TFO_SERVER_WO_SOCKOPT1 0x400
232230
#define TFO_SERVER_WO_SOCKOPT2 0x800
233-
/* Always create TFO child sockets on a TFO listener even when
234-
* cookie/data not present. (For testing purpose!)
235-
*/
236-
#define TFO_SERVER_ALWAYS 0x1000
237231

238232
extern struct inet_timewait_death_row tcp_death_row;
239233

@@ -1335,8 +1329,7 @@ int tcp_fastopen_create_child(struct sock *sk,
13351329
struct request_sock *req);
13361330
bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb,
13371331
struct request_sock *req,
1338-
struct tcp_fastopen_cookie *foc,
1339-
struct tcp_fastopen_cookie *valid_foc);
1332+
struct tcp_fastopen_cookie *foc);
13401333
void tcp_fastopen_init_key_once(bool publish);
13411334
#define TCP_FASTOPEN_KEY_LENGTH 16
13421335

net/ipv4/tcp_fastopen.c

Lines changed: 28 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -228,59 +228,44 @@ static bool tcp_fastopen_queue_check(struct sock *sk)
228228
return true;
229229
}
230230

231+
/* Returns true if we should perform Fast Open on the SYN. The cookie (foc)
232+
* may be updated and return the client in the SYN-ACK later. E.g., Fast Open
233+
* cookie request (foc->len == 0).
234+
*/
231235
bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb,
232236
struct request_sock *req,
233-
struct tcp_fastopen_cookie *foc,
234-
struct tcp_fastopen_cookie *valid_foc)
237+
struct tcp_fastopen_cookie *foc)
235238
{
236-
bool skip_cookie = false;
237-
238-
if (likely(!fastopen_cookie_present(foc))) {
239-
/* See include/net/tcp.h for the meaning of these knobs */
240-
if ((sysctl_tcp_fastopen & TFO_SERVER_ALWAYS) ||
241-
((sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD) &&
242-
(TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1)))
243-
skip_cookie = true; /* no cookie to validate */
244-
else
245-
return false;
246-
}
247-
/* A FO option is present; bump the counter. */
248-
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVE);
239+
struct tcp_fastopen_cookie valid_foc = { .len = -1 };
240+
bool syn_data = TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1;
249241

250-
if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) == 0 ||
251-
!tcp_fastopen_queue_check(sk))
242+
if (!((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) &&
243+
(syn_data || foc->len >= 0) &&
244+
tcp_fastopen_queue_check(sk))) {
245+
foc->len = -1;
252246
return false;
253-
254-
if (skip_cookie) {
255-
tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
256-
return true;
257247
}
258248

259-
if (foc->len == TCP_FASTOPEN_COOKIE_SIZE) {
260-
if ((sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_CHKED) == 0) {
261-
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
262-
ip_hdr(skb)->daddr, valid_foc);
263-
if ((valid_foc->len != TCP_FASTOPEN_COOKIE_SIZE) ||
264-
memcmp(&foc->val[0], &valid_foc->val[0],
265-
TCP_FASTOPEN_COOKIE_SIZE) != 0)
266-
return false;
267-
valid_foc->len = -1;
268-
}
269-
/* Acknowledge the data received from the peer. */
249+
if (syn_data && (sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD))
250+
goto fastopen;
251+
252+
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
253+
ip_hdr(skb)->daddr, &valid_foc);
254+
255+
if (foc->len == TCP_FASTOPEN_COOKIE_SIZE &&
256+
foc->len == valid_foc.len &&
257+
!memcmp(foc->val, valid_foc.val, foc->len)) {
258+
fastopen:
270259
tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
260+
foc->len = -1;
261+
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVE);
271262
return true;
272-
} else if (foc->len == 0) { /* Client requesting a cookie */
273-
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
274-
ip_hdr(skb)->daddr, valid_foc);
275-
NET_INC_STATS_BH(sock_net(sk),
276-
LINUX_MIB_TCPFASTOPENCOOKIEREQD);
277-
} else {
278-
/* Client sent a cookie with wrong size. Treat it
279-
* the same as invalid and return a valid one.
280-
*/
281-
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
282-
ip_hdr(skb)->daddr, valid_foc);
283263
}
264+
265+
NET_INC_STATS_BH(sock_net(sk), foc->len ?
266+
LINUX_MIB_TCPFASTOPENPASSIVEFAIL :
267+
LINUX_MIB_TCPFASTOPENCOOKIEREQD);
268+
*foc = valid_foc;
284269
return false;
285270
}
286271
EXPORT_SYMBOL(tcp_fastopen_check);

net/ipv4/tcp_ipv4.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
12731273
bool want_cookie = false;
12741274
struct flowi4 fl4;
12751275
struct tcp_fastopen_cookie foc = { .len = -1 };
1276-
struct tcp_fastopen_cookie valid_foc = { .len = -1 };
12771276
struct sk_buff *skb_synack;
12781277
int do_fastopen;
12791278

@@ -1381,7 +1380,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
13811380
if (dst == NULL)
13821381
goto drop_and_free;
13831382
}
1384-
do_fastopen = tcp_fastopen_check(sk, skb, req, &foc, &valid_foc);
1383+
do_fastopen = !want_cookie &&
1384+
tcp_fastopen_check(sk, skb, req, &foc);
13851385

13861386
/* We don't call tcp_v4_send_synack() directly because we need
13871387
* to make sure a child socket can be created successfully before
@@ -1394,8 +1394,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
13941394
* latter to remove its dependency on the current implementation
13951395
* of tcp_v4_send_synack()->tcp_select_initial_window().
13961396
*/
1397-
skb_synack = tcp_make_synack(sk, dst, req,
1398-
fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL);
1397+
skb_synack = tcp_make_synack(sk, dst, req, &foc);
13991398

14001399
if (skb_synack) {
14011400
__tcp_v4_send_check(skb_synack, ireq->ir_loc_addr, ireq->ir_rmt_addr);
@@ -1415,9 +1414,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
14151414
tcp_rsk(req)->listener = NULL;
14161415
/* Add the request_sock to the SYN table */
14171416
inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
1418-
if (fastopen_cookie_present(&foc) && foc.len != 0)
1419-
NET_INC_STATS_BH(sock_net(sk),
1420-
LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
14211417
} else if (tcp_fastopen_create_child(sk, skb, skb_synack, req))
14221418
goto drop_and_release;
14231419

net/ipv4/tcp_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
627627
if (unlikely(!ireq->tstamp_ok))
628628
remaining -= TCPOLEN_SACKPERM_ALIGNED;
629629
}
630-
if (foc != NULL) {
630+
if (foc != NULL && foc->len >= 0) {
631631
u32 need = TCPOLEN_EXP_FASTOPEN_BASE + foc->len;
632632
need = (need + 3) & ~3U; /* Align to 32 bits */
633633
if (remaining >= need) {

0 commit comments

Comments
 (0)