diff options
author | Florin Coras <fcoras@cisco.com> | 2017-04-25 00:05:27 -0700 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2017-04-25 15:44:15 +0000 |
commit | 45d3496f3d86ee1a930ce0ffd6ca3d1730355eb8 (patch) | |
tree | 447191fb0e69cf8700a3bd503ea1fd7d3d70e8df /src/vnet/tcp/tcp_input.c | |
parent | 68d2e24fbba2ab67eaaec1192db827325fc9068e (diff) |
Add sack tx unit test
Change-Id: Ib91db6e531231bdc52b0104673a912bee024872f
Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/tcp/tcp_input.c')
-rw-r--r-- | src/vnet/tcp/tcp_input.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index bfe3665ab00..e184a4d69e3 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -894,37 +894,51 @@ tcp_rcv_ack (tcp_connection_t * tc, vlib_buffer_t * b, * @param start Start sequence number of the newest SACK block * @param end End sequence of the newest SACK block */ -static void +void tcp_update_sack_list (tcp_connection_t * tc, u32 start, u32 end) { - sack_block_t *new_list = 0, block; + sack_block_t *new_list = 0, *block = 0; int i; /* If the first segment is ooo add it to the list. Last write might've moved * rcv_nxt over the first segment. */ if (seq_lt (tc->rcv_nxt, start)) { - block.start = start; - block.end = end; - vec_add1 (new_list, block); + vec_add2 (new_list, block, 1); + block->start = start; + block->end = end; } /* Find the blocks still worth keeping. */ for (i = 0; i < vec_len (tc->snd_sacks); i++) { - /* Discard if: - * 1) rcv_nxt advanced beyond current block OR - * 2) Segment overlapped by the first segment, i.e., it has been merged - * into it.*/ - if (seq_leq (tc->snd_sacks[i].start, tc->rcv_nxt) - || seq_leq (tc->snd_sacks[i].start, end)) + /* Discard if rcv_nxt advanced beyond current block */ + if (seq_leq (tc->snd_sacks[i].start, tc->rcv_nxt)) continue; - /* Save to new SACK list. */ - vec_add1 (new_list, tc->snd_sacks[i]); + /* Merge or drop if segment overlapped by the new segment */ + if (block && (seq_geq (tc->snd_sacks[i].end, new_list[0].start) + && seq_leq (tc->snd_sacks[i].start, new_list[0].end))) + { + if (seq_lt (tc->snd_sacks[i].start, new_list[0].start)) + new_list[0].start = tc->snd_sacks[i].start; + if (seq_lt (new_list[0].end, tc->snd_sacks[i].end)) + new_list[0].end = tc->snd_sacks[i].end; + continue; + } + + /* Save to new SACK list if we have space. */ + if (vec_len (new_list) < TCP_MAX_SACK_BLOCKS) + { + vec_add1 (new_list, tc->snd_sacks[i]); + } + else + { + clib_warning ("dropped sack blocks"); + } } - ASSERT (vec_len (new_list) < TCP_MAX_SACK_BLOCKS); + ASSERT (vec_len (new_list) <= TCP_MAX_SACK_BLOCKS); /* Replace old vector with new one */ vec_free (tc->snd_sacks); |