svn commit: r331249 - stable/11/sys/netinet
Sean Bruno
sbruno at FreeBSD.org
Tue Mar 20 17:27:01 UTC 2018
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 at 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)
More information about the svn-src-stable-11
mailing list