summaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/tcp/tcp_input.c')
-rw-r--r--src/vnet/tcp/tcp_input.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index ddee41e0b9e..9d3f4cc39e9 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -533,12 +533,13 @@ tcp_rcv_sacks (tcp_connection_t * tc, u32 ack)
sack_scoreboard_t *sb = &tc->sack_sb;
sack_block_t *blk, tmp;
sack_scoreboard_hole_t *hole, *next_hole, *last_hole, *new_hole;
- u32 blk_index = 0, old_sacked_bytes, hole_index;
+ u32 blk_index = 0, old_sacked_bytes, delivered_bytes, hole_index;
int i, j;
sb->last_sacked_bytes = 0;
sb->snd_una_adv = 0;
old_sacked_bytes = sb->sacked_bytes;
+ delivered_bytes = 0;
if (!tcp_opts_sack (&tc->opt) && sb->head == TCP_INVALID_SACK_HOLE_INDEX)
return;
@@ -584,6 +585,8 @@ tcp_rcv_sacks (tcp_connection_t * tc, u32 ack)
last_hole = scoreboard_insert_hole (sb, TCP_INVALID_SACK_HOLE_INDEX,
tc->snd_una, tc->snd_una_max);
sb->tail = scoreboard_hole_index (sb, last_hole);
+ tmp = tc->opt.sacks[vec_len (tc->opt.sacks) - 1];
+ sb->max_byte_sacked = tmp.end;
}
else
{
@@ -614,37 +617,43 @@ tcp_rcv_sacks (tcp_connection_t * tc, u32 ack)
{
/* Bytes lost because snd_wnd left edge advances */
if (next_hole && seq_leq (next_hole->start, ack))
- sb->sacked_bytes -= next_hole->start - hole->end;
+ delivered_bytes += next_hole->start - hole->end;
else
- sb->sacked_bytes -= ack - hole->end;
+ delivered_bytes += ack - hole->end;
}
else
{
sb->sacked_bytes += scoreboard_hole_bytes (hole);
}
- /* snd_una needs to be advanced */
- if (seq_geq (ack, hole->end))
- {
- if (next_hole && seq_lt (ack, next_hole->start))
- sb->snd_una_adv = next_hole->start - ack;
- else
- sb->snd_una_adv = sb->max_byte_sacked - ack;
-
- /* all these can be delivered */
- sb->sacked_bytes -= sb->snd_una_adv;
- }
-
/* About to remove last hole */
if (hole == last_hole)
{
sb->tail = hole->prev;
last_hole = scoreboard_last_hole (sb);
- /* keep track of max byte sacked in case the last hole
+ /* keep track of max byte sacked for when the last hole
* is acked */
if (seq_gt (hole->end, sb->max_byte_sacked))
sb->max_byte_sacked = hole->end;
}
+
+ /* snd_una needs to be advanced */
+ if (blk->end == ack && seq_geq (ack, hole->end))
+ {
+ if (next_hole && seq_lt (ack, next_hole->start))
+ {
+ sb->snd_una_adv = next_hole->start - ack;
+
+ /* all these can be delivered */
+ delivered_bytes += sb->snd_una_adv;
+ }
+ else if (!next_hole)
+ {
+ sb->snd_una_adv = sb->max_byte_sacked - ack;
+ delivered_bytes += sb->snd_una_adv;
+ }
+ }
+
scoreboard_remove_hole (sb, hole);
hole = next_hole;
}
@@ -693,8 +702,8 @@ tcp_rcv_sacks (tcp_connection_t * tc, u32 ack)
}
}
- sb->last_sacked_bytes = sb->sacked_bytes + sb->snd_una_adv
- - old_sacked_bytes;
+ sb->last_sacked_bytes = sb->sacked_bytes - old_sacked_bytes;
+ sb->sacked_bytes -= delivered_bytes;
}
/** Update snd_wnd