svn commit: r336934 - head/sys/netinet

Michael Tuexen tuexen at FreeBSD.org
Mon Jul 30 20:35:52 UTC 2018


Author: tuexen
Date: Mon Jul 30 20:35:50 2018
New Revision: 336934
URL: https://svnweb.freebsd.org/changeset/base/336934

Log:
  Fix some TCP fast open issues.
  
  The following issues are fixed:
  * Whenever a TCP server with TCP fast open enabled, calls accept(),
    recv(), send(), and close() before the TCP-ACK segment has been received,
    the TCP connection is just dropped and the reception of the TCP-ACK
    segment triggers the sending of a TCP-RST segment.
  * Whenever a TCP server with TCP fast open enabled, calls accept(), recv(),
    send(), send(), and close() before the TCP-ACK segment has been received,
    the first byte provided in the second send call is not transferred.
  * Whenever a TCP client with TCP fast open enabled calls sendto() followed
    by close() the TCP connection is just dropped.
  
  Reviewed by:		jtl@, kbowling@, rrs@
  Sponsored by:		Netflix, Inc.
  Differential Revision:	https://reviews.freebsd.org/D16485

Modified:
  head/sys/netinet/tcp_input.c
  head/sys/netinet/tcp_output.c
  head/sys/netinet/tcp_usrreq.c

Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c	Mon Jul 30 20:25:32 2018	(r336933)
+++ head/sys/netinet/tcp_input.c	Mon Jul 30 20:35:50 2018	(r336934)
@@ -2407,6 +2407,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, stru
 		 *      SYN-RECEIVED* -> FIN-WAIT-1
 		 */
 		tp->t_starttime = ticks;
+		if (IS_FASTOPEN(tp->t_flags) && tp->t_tfo_pending) {
+			tcp_fastopen_decrement_counter(tp->t_tfo_pending);
+			tp->t_tfo_pending = NULL;
+
+			/*
+			 * Account for the ACK of our SYN prior to
+			 * regular ACK processing below.
+			 */ 
+			tp->snd_una++;
+		}
 		if (tp->t_flags & TF_NEEDFIN) {
 			tcp_state_change(tp, TCPS_FIN_WAIT_1);
 			tp->t_flags &= ~TF_NEEDFIN;
@@ -2414,16 +2424,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, stru
 			tcp_state_change(tp, TCPS_ESTABLISHED);
 			TCP_PROBE5(accept__established, NULL, tp,
 			    m, tp, th);
-			if (IS_FASTOPEN(tp->t_flags) && tp->t_tfo_pending) {
-				tcp_fastopen_decrement_counter(tp->t_tfo_pending);
-				tp->t_tfo_pending = NULL;
-
-				/*
-				 * Account for the ACK of our SYN prior to
-				 * regular ACK processing below.
-				 */ 
-				tp->snd_una++;
-			}
 			/*
 			 * TFO connections call cc_conn_init() during SYN
 			 * processing.  Calling it again here for such

Modified: head/sys/netinet/tcp_output.c
==============================================================================
--- head/sys/netinet/tcp_output.c	Mon Jul 30 20:25:32 2018	(r336933)
+++ head/sys/netinet/tcp_output.c	Mon Jul 30 20:35:50 2018	(r336934)
@@ -228,13 +228,15 @@ tcp_output(struct tcpcb *tp)
 #endif
 
 	/*
-	 * For TFO connections in SYN_RECEIVED, only allow the initial
-	 * SYN|ACK and those sent by the retransmit timer.
+	 * For TFO connections in SYN_SENT or SYN_RECEIVED,
+	 * only allow the initial SYN or SYN|ACK and those sent
+	 * by the retransmit timer.
 	 */
 	if (IS_FASTOPEN(tp->t_flags) &&
-	    (tp->t_state == TCPS_SYN_RECEIVED) &&
-	    SEQ_GT(tp->snd_max, tp->snd_una) &&    /* initial SYN|ACK sent */
-	    (tp->snd_nxt != tp->snd_una))         /* not a retransmit */
+	    ((tp->t_state == TCPS_SYN_SENT) ||
+	     (tp->t_state == TCPS_SYN_RECEIVED)) &&
+	    SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN or SYN|ACK sent */
+	    (tp->snd_nxt != tp->snd_una))       /* not a retransmit */
 		return (0);
 
 	/*

Modified: head/sys/netinet/tcp_usrreq.c
==============================================================================
--- head/sys/netinet/tcp_usrreq.c	Mon Jul 30 20:25:32 2018	(r336933)
+++ head/sys/netinet/tcp_usrreq.c	Mon Jul 30 20:35:50 2018	(r336934)
@@ -2113,7 +2113,8 @@ tcp_disconnect(struct tcpcb *tp)
 	 * Neither tcp_close() nor tcp_drop() should return NULL, as the
 	 * socket is still open.
 	 */
-	if (tp->t_state < TCPS_ESTABLISHED) {
+	if (tp->t_state < TCPS_ESTABLISHED &&
+	    !(tp->t_state > TCPS_LISTEN && IS_FASTOPEN(tp->t_flags))) {
 		tp = tcp_close(tp);
 		KASSERT(tp != NULL,
 		    ("tcp_disconnect: tcp_close() returned NULL"));


More information about the svn-src-head mailing list