aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/af_inet.c
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2012-07-19 02:43:07 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-19 14:02:03 -0400
commit783237e8daf13481ee234997cbbbb823872ac388 (patch)
treecf6e9adf54eedbc155d4fc43bcf6ec87aaac820e /net/ipv4/af_inet.c
parent1fe4c481ba637660793217769695c146a037bd54 (diff)
net-tcp: Fast Open client - sending SYN-data
This patch implements sending SYN-data in tcp_connect(). The data is from tcp_sendmsg() with flag MSG_FASTOPEN (implemented in a later patch). The length of the cookie in tcp_fastopen_req, init'd to 0, controls the type of the SYN. If the cookie is not cached (len==0), the host sends data-less SYN with Fast Open cookie request option to solicit a cookie from the remote. If cookie is not available (len > 0), the host sends a SYN-data with Fast Open cookie option. If cookie length is negative, the SYN will not include any Fast Open option (for fall back operations). To deal with middleboxes that may drop SYN with data or experimental TCP option, the SYN-data is only sent once. SYN retransmits do not include data or Fast Open options. The connection will fall back to regular TCP handshake. Signed-off-by: Yuchung Cheng <ycheng@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r--net/ipv4/af_inet.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 07a02f6e9696..edc414625be2 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -556,11 +556,12 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
556} 556}
557EXPORT_SYMBOL(inet_dgram_connect); 557EXPORT_SYMBOL(inet_dgram_connect);
558 558
559static long inet_wait_for_connect(struct sock *sk, long timeo) 559static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)
560{ 560{
561 DEFINE_WAIT(wait); 561 DEFINE_WAIT(wait);
562 562
563 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 563 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
564 sk->sk_write_pending += writebias;
564 565
565 /* Basic assumption: if someone sets sk->sk_err, he _must_ 566 /* Basic assumption: if someone sets sk->sk_err, he _must_
566 * change state of the socket from TCP_SYN_*. 567 * change state of the socket from TCP_SYN_*.
@@ -576,6 +577,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo)
576 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 577 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
577 } 578 }
578 finish_wait(sk_sleep(sk), &wait); 579 finish_wait(sk_sleep(sk), &wait);
580 sk->sk_write_pending -= writebias;
579 return timeo; 581 return timeo;
580} 582}
581 583
@@ -634,8 +636,12 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
634 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); 636 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
635 637
636 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { 638 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
639 int writebias = (sk->sk_protocol == IPPROTO_TCP) &&
640 tcp_sk(sk)->fastopen_req &&
641 tcp_sk(sk)->fastopen_req->data ? 1 : 0;
642
637 /* Error code is set above */ 643 /* Error code is set above */
638 if (!timeo || !inet_wait_for_connect(sk, timeo)) 644 if (!timeo || !inet_wait_for_connect(sk, timeo, writebias))
639 goto out; 645 goto out;
640 646
641 err = sock_intr_errno(timeo); 647 err = sock_intr_errno(timeo);