Author: sbruno
Date: Fri Mar  9 00:08:43 2018
New Revision: 330675
URL: https://svnweb.freebsd.org/changeset/base/330675

Log:
  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.bowl...@kev009.com>
  Reviewed by:  rstone gallatin
  Sponsored by: NetFlix and Limelight Networks
  Differential Revision:        https://reviews.freebsd.org/D14540

Modified:
  head/sys/netinet/tcp_lro.c
  head/sys/netinet/tcp_seq.h

Modified: head/sys/netinet/tcp_lro.c
==============================================================================
--- head/sys/netinet/tcp_lro.c  Thu Mar  8 22:54:50 2018        (r330674)
+++ head/sys/netinet/tcp_lro.c  Fri Mar  9 00:08:43 2018        (r330675)
@@ -57,6 +57,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>
 
@@ -794,7 +795,9 @@ tcp_lro_rx2(struct lro_ctrl *lc, struct mbuf *m, uint3
 
                /* 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);
@@ -811,12 +814,20 @@ tcp_lro_rx2(struct lro_ctrl *lc, struct mbuf *m, uint3
                        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: head/sys/netinet/tcp_seq.h
==============================================================================
--- head/sys/netinet/tcp_seq.h  Thu Mar  8 22:54:50 2018        (r330674)
+++ head/sys/netinet/tcp_seq.h  Fri Mar  9 00:08:43 2018        (r330675)
@@ -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)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to