aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2012-07-19 02:43:08 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-19 14:02:03 -0400
commit8e4178c1c7b52f7c99f5fd22ef7af6b2bff409e3 (patch)
tree101ec972d397346ea603ee2a08b8320f1ed690eb
parent783237e8daf13481ee234997cbbbb823872ac388 (diff)
net-tcp: Fast Open client - receiving SYN-ACK
On receiving the SYN-ACK after SYN-data, the client needs to a) update the cached MSS and cookie (if included in SYN-ACK) b) retransmit the data not yet acknowledged by the SYN-ACK in the final ACK of the 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>
-rw-r--r--net/ipv4/tcp_input.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a06bb8959e7e..38b6a811edfc 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5646,6 +5646,34 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
5646 } 5646 }
5647} 5647}
5648 5648
5649static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
5650 struct tcp_fastopen_cookie *cookie)
5651{
5652 struct tcp_sock *tp = tcp_sk(sk);
5653 struct sk_buff *data = tcp_write_queue_head(sk);
5654 u16 mss = tp->rx_opt.mss_clamp;
5655
5656 if (mss == tp->rx_opt.user_mss) {
5657 struct tcp_options_received opt;
5658 const u8 *hash_location;
5659
5660 /* Get original SYNACK MSS value if user MSS sets mss_clamp */
5661 tcp_clear_options(&opt);
5662 opt.user_mss = opt.mss_clamp = 0;
5663 tcp_parse_options(synack, &opt, &hash_location, 0, NULL);
5664 mss = opt.mss_clamp;
5665 }
5666
5667 tcp_fastopen_cache_set(sk, mss, cookie);
5668
5669 if (data) { /* Retransmit unacked data in SYN */
5670 tcp_retransmit_skb(sk, data);
5671 tcp_rearm_rto(sk);
5672 return true;
5673 }
5674 return false;
5675}
5676
5649static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, 5677static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5650 const struct tcphdr *th, unsigned int len) 5678 const struct tcphdr *th, unsigned int len)
5651{ 5679{
@@ -5653,9 +5681,10 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5653 struct inet_connection_sock *icsk = inet_csk(sk); 5681 struct inet_connection_sock *icsk = inet_csk(sk);
5654 struct tcp_sock *tp = tcp_sk(sk); 5682 struct tcp_sock *tp = tcp_sk(sk);
5655 struct tcp_cookie_values *cvp = tp->cookie_values; 5683 struct tcp_cookie_values *cvp = tp->cookie_values;
5684 struct tcp_fastopen_cookie foc = { .len = -1 };
5656 int saved_clamp = tp->rx_opt.mss_clamp; 5685 int saved_clamp = tp->rx_opt.mss_clamp;
5657 5686
5658 tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, NULL); 5687 tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, &foc);
5659 5688
5660 if (th->ack) { 5689 if (th->ack) {
5661 /* rfc793: 5690 /* rfc793:
@@ -5665,11 +5694,9 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5665 * If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send 5694 * If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send
5666 * a reset (unless the RST bit is set, if so drop 5695 * a reset (unless the RST bit is set, if so drop
5667 * the segment and return)" 5696 * the segment and return)"
5668 *
5669 * We do not send data with SYN, so that RFC-correct
5670 * test reduces to:
5671 */ 5697 */
5672 if (TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt) 5698 if (!after(TCP_SKB_CB(skb)->ack_seq, tp->snd_una) ||
5699 after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt))
5673 goto reset_and_undo; 5700 goto reset_and_undo;
5674 5701
5675 if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && 5702 if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
@@ -5781,6 +5808,9 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5781 5808
5782 tcp_finish_connect(sk, skb); 5809 tcp_finish_connect(sk, skb);
5783 5810
5811 if (tp->syn_fastopen && tcp_rcv_fastopen_synack(sk, skb, &foc))
5812 return -1;
5813
5784 if (sk->sk_write_pending || 5814 if (sk->sk_write_pending ||
5785 icsk->icsk_accept_queue.rskq_defer_accept || 5815 icsk->icsk_accept_queue.rskq_defer_accept ||
5786 icsk->icsk_ack.pingpong) { 5816 icsk->icsk_ack.pingpong) {