svn commit: r330675 - head/sys/netinet
Sean Bruno
sbruno at FreeBSD.org
Fri Mar 9 00:08:44 UTC 2018
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.bowling at 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)
More information about the svn-src-all
mailing list