Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Mar 2018 17:27:00 +0000 (UTC)
From:      Sean Bruno <sbruno@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r331249 - stable/11/sys/netinet
Message-ID:  <201803201727.w2KHR0rQ045501@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sbruno
Date: Tue Mar 20 17:27:00 2018
New Revision: 331249
URL: https://svnweb.freebsd.org/changeset/base/331249

Log:
  MFC r330675
  
  Update tcp_lro with tested bugfixes from Netflix and LLNW:
  
      rrs - Lets make the LRO code look for true dup-acks and window update acks
            fly on through and combine.
      rrs - Make the LRO engine a bit more aware of ack-only seq space. Lets not
            have it incorrectly wipe out newer acks for older acks when we have
            out-of-order acks (common in wifi environments).
      jeggleston - LRO eating window updates
  
  Based on all of the above I think we are RFC compliant doing it this way:
  
  https://tools.ietf.org/html/rfc1122
  
  section 4.2.2.16
  
  "Note that TCP has a heuristic to select the latest window update despite
  possible datagram reordering; as a result, it may ignore a window update with
  a smaller window than previously offered if neither the sequence number nor the
  acknowledgment number is increased."
  
  Submitted by:	Kevin Bowling <kevin.bowling@kev009.com>
  Sponsored by:	NetFlix and Limelight Networks

Modified:
  stable/11/sys/netinet/tcp_lro.c
  stable/11/sys/netinet/tcp_seq.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/tcp_lro.c
==============================================================================
--- stable/11/sys/netinet/tcp_lro.c	Tue Mar 20 17:05:23 2018	(r331248)
+++ stable/11/sys/netinet/tcp_lro.c	Tue Mar 20 17:27:00 2018	(r331249)
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/tcp.h>
+#include <netinet/tcp_seq.h>
 #include <netinet/tcp_lro.h>
 #include <netinet/tcp_var.h>
 
@@ -734,7 +735,9 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32
 
 		/* Try to append the new segment. */
 		if (__predict_false(seq != le->next_seq ||
-		    (tcp_data_len == 0 && le->ack_seq == th->th_ack))) {
+		    (tcp_data_len == 0 &&
+		    le->ack_seq == th->th_ack &&
+		    le->window == th->th_win))) {
 			/* Out of order packet or duplicate ACK. */
 			tcp_lro_active_remove(le);
 			tcp_lro_flush(lc, le);
@@ -751,12 +754,20 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32
 			le->tsval = tsval;
 			le->tsecr = *(ts_ptr + 2);
 		}
-
-		le->next_seq += tcp_data_len;
-		le->ack_seq = th->th_ack;
-		le->window = th->th_win;
-		le->append_cnt++;
-
+		if (tcp_data_len || SEQ_GT(ntohl(th->th_ack), ntohl(le->ack_seq))) {
+			le->next_seq += tcp_data_len;
+			le->ack_seq = th->th_ack;
+			le->window = th->th_win;
+			le->append_cnt++;
+		} else if (th->th_ack == le->ack_seq) {
+			le->window = WIN_MAX(le->window, th->th_win);
+			le->append_cnt++;
+		} else {
+			/* no data and old ack */
+			le->append_cnt++;
+			m_freem(m);
+			return (0);
+		}
 #ifdef TCP_LRO_UPDATE_CSUM
 		le->ulp_csum += tcp_lro_rx_csum_fixup(le, l3hdr, th,
 		    tcp_data_len, ~csum);

Modified: stable/11/sys/netinet/tcp_seq.h
==============================================================================
--- stable/11/sys/netinet/tcp_seq.h	Tue Mar 20 17:05:23 2018	(r331248)
+++ stable/11/sys/netinet/tcp_seq.h	Tue Mar 20 17:27:00 2018	(r331249)
@@ -47,6 +47,14 @@
 #define	SEQ_MIN(a, b)	((SEQ_LT(a, b)) ? (a) : (b))
 #define	SEQ_MAX(a, b)	((SEQ_GT(a, b)) ? (a) : (b))
 
+#define	WIN_LT(a,b)	((short)(ntohs(a)-ntohs(b)) < 0)
+#define	WIN_LEQ(a,b)	((short)(ntohs(a)-ntohs(b)) <= 0)
+#define	WIN_GT(a,b)	((short)(ntohs(a)-ntohs(b)) > 0)
+#define	WIN_GEQ(a,b)	((short)(ntohs(a)-ntohs(b)) >= 0)
+
+#define	WIN_MIN(a, b)	((WIN_LT(a, b)) ? (a) : (b))
+#define	WIN_MAX(a, b)	((WIN_GT(a, b)) ? (a) : (b))
+
 /* for modulo comparisons of timestamps */
 #define TSTMP_LT(a,b)	((int)((a)-(b)) < 0)
 #define TSTMP_GT(a,b)	((int)((a)-(b)) > 0)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803201727.w2KHR0rQ045501>