Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/tcp_sack.c
Show First 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end) | ||||
* compliant with RFC 2018. | * compliant with RFC 2018. | ||||
*/ | */ | ||||
struct sackblk head_blk, saved_blks[MAX_SACK_BLKS]; | struct sackblk head_blk, saved_blks[MAX_SACK_BLKS]; | ||||
int num_head, num_saved, i; | int num_head, num_saved, i; | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | INP_WLOCK_ASSERT(tp->t_inpcb); | ||||
/* Check arguments. */ | /* Check arguments. */ | ||||
KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end")); | KASSERT(SEQ_LEQ(rcv_start, rcv_end), ("rcv_start <= rcv_end")); | ||||
/* SACK block for the received segment. */ | /* SACK block for the received segment. */ | ||||
head_blk.start = rcv_start; | head_blk.start = rcv_start; | ||||
head_blk.end = rcv_end; | head_blk.end = rcv_end; | ||||
/* | /* | ||||
* Merge updated SACK blocks into head_blk, and save unchanged SACK | * Merge updated SACK blocks into head_blk, and save unchanged SACK | ||||
* blocks into saved_blks[]. num_saved will have the number of the | * blocks into saved_blks[]. num_saved will have the number of the | ||||
* saved SACK blocks. | * saved SACK blocks. | ||||
*/ | */ | ||||
num_saved = 0; | num_saved = 0; | ||||
for (i = 0; i < tp->rcv_numsacks; i++) { | for (i = 0; i < tp->rcv_numsacks; i++) { | ||||
tcp_seq start = tp->sackblks[i].start; | tcp_seq start = tp->sackblks[i].start; | ||||
tcp_seq end = tp->sackblks[i].end; | tcp_seq end = tp->sackblks[i].end; | ||||
if (SEQ_GEQ(start, end) || SEQ_LEQ(start, tp->rcv_nxt)) { | if (SEQ_GEQ(start, end) || SEQ_LEQ(start, tp->rcv_nxt)) { | ||||
/* | /* | ||||
* Discard this SACK block. | * Discard this SACK block. | ||||
*/ | */ | ||||
} else if (SEQ_LEQ(head_blk.start, end) && | } else if (SEQ_LEQ(head_blk.start, end) && | ||||
SEQ_GEQ(head_blk.end, start)) { | SEQ_GEQ(head_blk.end, start)) { | ||||
/* | /* | ||||
* Merge this SACK block into head_blk. This SACK | * Merge this SACK block into head_blk. This SACK | ||||
* block itself will be discarded. | * block itself will be discarded. | ||||
*/ | */ | ||||
if (SEQ_GT(head_blk.start, start)) | /* | ||||
* |-| | |||||
* |---| merge | |||||
* | |||||
* |-| | |||||
* |---| merge | |||||
* | |||||
* |-----| | |||||
* |-| DSACK smaller | |||||
* | |||||
* |-| | |||||
* |-----| DSACK smaller | |||||
*/ | |||||
if (head_blk.start == end) | |||||
head_blk.start = start; | head_blk.start = start; | ||||
if (SEQ_LT(head_blk.end, end)) | else if (head_blk.end == start) | ||||
head_blk.end = end; | head_blk.end = end; | ||||
else { | |||||
if (SEQ_LT(head_blk.start, start)) { | |||||
tcp_seq temp = start; | |||||
start = head_blk.start; | |||||
head_blk.start = temp; | |||||
} | |||||
if (SEQ_GT(head_blk.end, end)) { | |||||
tcp_seq temp = end; | |||||
end = head_blk.end; | |||||
head_blk.end = temp; | |||||
} | |||||
if ((head_blk.start != start) || | |||||
(head_blk.end != end)) { | |||||
if ((num_saved >= 1) && | |||||
SEQ_GEQ(saved_blks[num_saved-1].start, start) && | |||||
SEQ_LEQ(saved_blks[num_saved-1].end, end)) | |||||
num_saved--; | |||||
saved_blks[num_saved].start = start; | |||||
saved_blks[num_saved].end = end; | |||||
num_saved++; | |||||
} | |||||
} | |||||
} else { | } else { | ||||
/* | /* | ||||
* This block supercedes the prior block | |||||
*/ | |||||
if ((num_saved >= 1) && | |||||
SEQ_GEQ(saved_blks[num_saved-1].start, start) && | |||||
SEQ_LEQ(saved_blks[num_saved-1].end, end)) | |||||
num_saved--; | |||||
/* | |||||
* Save this SACK block. | * Save this SACK block. | ||||
*/ | */ | ||||
saved_blks[num_saved].start = start; | saved_blks[num_saved].start = start; | ||||
saved_blks[num_saved].end = end; | saved_blks[num_saved].end = end; | ||||
num_saved++; | num_saved++; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Update SACK list in tp->sackblks[]. | * Update SACK list in tp->sackblks[]. | ||||
*/ | */ | ||||
num_head = 0; | num_head = 0; | ||||
if (SEQ_GT(head_blk.start, tp->rcv_nxt)) { | if (SEQ_LT(rcv_start, rcv_end)) { | ||||
/* | /* | ||||
* The received data segment is an out-of-order segment. Put | * The received data segment is an out-of-order segment. Put | ||||
* head_blk at the top of SACK list. | * head_blk at the top of SACK list. | ||||
*/ | */ | ||||
tp->sackblks[0] = head_blk; | tp->sackblks[0] = head_blk; | ||||
num_head = 1; | num_head = 1; | ||||
/* | /* | ||||
* If the number of saved SACK blocks exceeds its limit, | * If the number of saved SACK blocks exceeds its limit, | ||||
▲ Show 20 Lines • Show All 475 Lines • Show Last 20 Lines |