Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153346432
D21038.id60073.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D21038.id60073.diff
View Options
Index: sys/netinet/tcp_input.c
===================================================================
--- sys/netinet/tcp_input.c
+++ sys/netinet/tcp_input.c
@@ -2262,7 +2262,11 @@
* DSACK - add SACK block for dropped range
*/
if (tp->t_flags & TF_SACK_PERMIT) {
- tcp_update_sack_list(tp, th->th_seq, th->th_seq+tlen);
+ /*
+ * up here, we only need to store the duplicated range
+ * as sackblk[0], for reference below during dsack
+ */
+ tcp_update_sack_list(tp, th->th_seq, th->th_seq+todrop);
/*
* ACK now, as the next in-sequence segment
* will clear the DSACK block again
@@ -3052,18 +3056,20 @@
tcp_update_sack_list(tp, save_start, save_start + save_tlen);
} else
if ((tlen > 0) && SEQ_GT(tp->rcv_nxt, save_rnxt)) {
- /*
- * Cleaning sackblks by using zero length
- * update.
- */
- tcp_update_sack_list(tp, save_start, save_start);
+ if ((tp->rcv_numsacks >= 1) &&
+ (tp->sackblks[0].end == save_start)) {
+ /* partial overlap */
+ tcp_update_sack_list(tp, tp->sackblks[0].start, tp->sackblks[0].end);
+ } else {
+ tcp_update_dsack_list(tp, save_start, save_start + save_tlen);
+ }
} else
if ((tlen > 0) && (tlen >= save_tlen)) {
/* Update of sackblks. */
- tcp_update_sack_list(tp, save_start, save_start + save_tlen);
+ tcp_update_dsack_list(tp, save_start, save_start + save_tlen);
} else
if (tlen > 0) {
- tcp_update_sack_list(tp, save_start, save_start+tlen);
+ tcp_update_dsack_list(tp, save_start, save_start+tlen);
}
}
#if 0
Index: sys/netinet/tcp_sack.c
===================================================================
--- sys/netinet/tcp_sack.c
+++ sys/netinet/tcp_sack.c
@@ -149,6 +149,108 @@
&VNET_NAME(tcp_sack_globalholes), 0,
"Global number of TCP SACK holes currently allocated");
+
+/*
+ * This function will find overlaps with the currently stored sackblocks
+ * and add any overlap as a dsack block upfront
+ */
+void
+tcp_update_dsack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
+{
+ struct sackblk head_blk,mid_blk,saved_blks[MAX_SACK_BLKS];
+ int i, j, n, identical;
+ tcp_seq start, end;
+
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end"));
+
+ if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+ log(LOG_DEBUG, "\nDSACK update: %d..%d, rcv_nxt: %u\n",
+ rcv_start, rcv_end, tp->rcv_nxt);
+ }
+
+ if (SEQ_LT(rcv_end, tp->rcv_nxt) ||
+ ((rcv_end == tp->rcv_nxt) &&
+ (tp->rcv_numsacks > 0 ) &&
+ (tp->sackblks[0].end == tp->rcv_nxt))) {
+ saved_blks[0].start = rcv_start;
+ saved_blks[0].end = rcv_end;
+ } else {
+ saved_blks[0].start = saved_blks[0].end = 0;
+ }
+
+ head_blk.start = head_blk.end = 0;
+ mid_blk.start = rcv_start;
+ mid_blk.end = rcv_end;
+ identical = 0;
+
+ for (i = 0; i < tp->rcv_numsacks; i++) {
+ start = tp->sackblks[i].start;
+ end = tp->sackblks[i].end;
+ if (SEQ_LT(rcv_end, start)) {
+ /* pkt left to sack blk */
+ continue;
+ }
+ if (SEQ_GT(rcv_start, end)) {
+ /* pkt right to sack blk */
+ continue;
+ }
+ if (SEQ_GT(tp->rcv_nxt, end)) {
+ if ((SEQ_MAX(rcv_start, start) != SEQ_MIN(rcv_end, end)) &&
+ (SEQ_GT(head_blk.start, SEQ_MAX(rcv_start, start)) ||
+ (head_blk.start == head_blk.end))) {
+ head_blk.start = SEQ_MAX(rcv_start, start);
+ head_blk.end = SEQ_MIN(rcv_end, end);
+ }
+ continue;
+ }
+ if (((head_blk.start == head_blk.end) ||
+ SEQ_LT(start, head_blk.start)) &&
+ (SEQ_GT(end, rcv_start) &&
+ SEQ_LEQ(start, rcv_end))) {
+ head_blk.start = start;
+ head_blk.end = end;
+ }
+ mid_blk.start = SEQ_MIN(mid_blk.start, start);
+ mid_blk.end = SEQ_MAX(mid_blk.end, end);
+ if ((mid_blk.start == start) &&
+ (mid_blk.end == end))
+ identical = 1;
+ }
+ if (SEQ_LT(head_blk.start, head_blk.end)) {
+ /* store overlapping range */
+ saved_blks[0].start = SEQ_MAX(rcv_start, head_blk.start);
+ saved_blks[0].end = SEQ_MIN(rcv_end, head_blk.end);
+ }
+ n=1;
+ /*
+ * Second, if not ACKed, store the SACK block that
+ * overlaps with the DSACK block unless it is identical
+ */
+ if ((SEQ_LT(tp->rcv_nxt, mid_blk.end) &&
+ !((mid_blk.start == saved_blks[0].start) &&
+ (mid_blk.end == saved_blks[0].end))) ||
+ identical == 1) {
+ saved_blks[n].start = mid_blk.start;
+ saved_blks[n++].end = mid_blk.end;
+ }
+ for (j = 0; (j < tp->rcv_numsacks) && (j < MAX_SACK_BLKS-1); j++) {
+ if (((SEQ_LT(tp->sackblks[j].end, mid_blk.start) ||
+ SEQ_GT(tp->sackblks[j].start, mid_blk.end)) &&
+ (SEQ_GT(tp->sackblks[j].start, tp->rcv_nxt))))
+ saved_blks[n++] = tp->sackblks[j];
+ }
+ j=0;
+ for (i=0; i<n; i++) {
+ /* we can end up with a stale inital entry */
+ if (SEQ_LT(saved_blks[i].start, saved_blks[i].end)) {
+ tp->sackblks[j++] = saved_blks[i];
+ }
+ }
+ tp->rcv_numsacks = j;
+}
+
/*
* This function is called upon receipt of new valid data (while not in
* header prediction mode), and it updates the ordered list of sacks.
@@ -170,9 +272,16 @@
/* Check arguments. */
KASSERT(SEQ_LEQ(rcv_start, rcv_end), ("rcv_start <= rcv_end"));
+ if ((rcv_start == rcv_end) &&
+ (tp->rcv_numsacks >= 1) &&
+ (rcv_start == tp->sackblks[0].end)) {
+ head_blk = tp->sackblks[0];
+ } else {
+
/* SACK block for the received segment. */
head_blk.start = rcv_start;
head_blk.end = rcv_end;
+ }
/*
* Merge updated SACK blocks into head_blk, and save unchanged SACK
@@ -267,6 +376,10 @@
if (num_saved >= MAX_SACK_BLKS)
num_saved--;
}
+ if ((rcv_start == rcv_end) &&
+ (rcv_start == tp->sackblks[0].end)) {
+ num_head = 1;
+ }
if (num_saved > 0) {
/*
* Copy the saved SACK blocks back.
Index: sys/netinet/tcp_stacks/rack.c
===================================================================
--- sys/netinet/tcp_stacks/rack.c
+++ sys/netinet/tcp_stacks/rack.c
@@ -1787,6 +1787,14 @@
TCPSTAT_INC(tcps_rcvpartduppack);
TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop);
}
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ /*
+ * record the left, to-be-dropped edge of data
+ * here, for use as dsack block further down
+ */
+ tcp_update_sack_list(tp, th->th_seq,
+ th->th_seq + todrop);
+ }
*drop_hdrlen += todrop; /* drop from the top afterwards */
th->th_seq += todrop;
tlen -= todrop;
@@ -4944,12 +4952,22 @@
* Cleaning sackblks by using zero length
* update.
*/
- tcp_update_sack_list(tp, save_start, save_start);
+ if ((tp->rcv_numsacks >= 1) &&
+ (tp->sackblks[0].end == save_start)) {
+ /* partial overlap, recorded at todrop above */
+ tcp_update_sack_list(tp, tp->sackblks[0].start,
+ tp->sackblks[0].end);
+ } else {
+ tcp_update_dsack_list(tp, save_start,
+ save_start + save_tlen);
+ }
} else if ((tlen > 0) && (tlen >= save_tlen)) {
/* Update of sackblks. */
- tcp_update_sack_list(tp, save_start, save_start + save_tlen);
+ tcp_update_dsack_list(tp, save_start,
+ save_start + save_tlen);
} else if (tlen > 0) {
- tcp_update_sack_list(tp, save_start, save_start+tlen);
+ tcp_update_dsack_list(tp, save_start,
+ save_start + tlen);
}
} else {
m_freem(m);
Index: sys/netinet/tcp_var.h
===================================================================
--- sys/netinet/tcp_var.h
+++ sys/netinet/tcp_var.h
@@ -938,6 +938,7 @@
tcp_seq tcp_new_isn(struct in_conninfo *);
int tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq);
+void tcp_update_dsack_list(struct tcpcb *, tcp_seq, tcp_seq);
void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend);
void tcp_clean_dsack_blocks(struct tcpcb *tp);
void tcp_clean_sackreport(struct tcpcb *tp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 21, 3:06 PM (1 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31917088
Default Alt Text
D21038.id60073.diff (7 KB)
Attached To
Mode
D21038: DSACK patch to conform fully with RFC2883
Attached
Detach File
Event Timeline
Log In to Comment