Commit f645ea6b authored by Olivier Crête's avatar Olivier Crête

pseudotcp: Make sure duplicate ack representing losses have no data

If they have data in them, they won't be recognized as duplicate acks by
the sender.
parent adba0d4a
...@@ -429,6 +429,7 @@ typedef enum { ...@@ -429,6 +429,7 @@ typedef enum {
sfImmediateAck, sfImmediateAck,
sfFin, sfFin,
sfRst, sfRst,
sfDuplicateAck,
} SendFlags; } SendFlags;
typedef struct { typedef struct {
...@@ -1936,7 +1937,7 @@ process(PseudoTcpSocket *self, Segment *seg) ...@@ -1936,7 +1937,7 @@ process(PseudoTcpSocket *self, Segment *seg)
* see RFC 793, §3.3. Also see: RFC 793, §3.5. * see RFC 793, §3.3. Also see: RFC 793, §3.5.
*/ */
if (seg->seq != priv->rcv_nxt) { if (seg->seq != priv->rcv_nxt) {
sflags = sfImmediateAck; // (Fast Recovery) sflags = sfDuplicateAck; // (Fast Recovery)
} else if (seg->len != 0) { } else if (seg->len != 0) {
if (priv->ack_delay == 0) { if (priv->ack_delay == 0) {
sflags = sfImmediateAck; sflags = sfImmediateAck;
...@@ -1949,7 +1950,7 @@ process(PseudoTcpSocket *self, Segment *seg) ...@@ -1949,7 +1950,7 @@ process(PseudoTcpSocket *self, Segment *seg)
sflags = sfImmediateAck; sflags = sfImmediateAck;
} }
if (sflags == sfImmediateAck) { if (sflags == sfDuplicateAck) {
if (seg->seq > priv->rcv_nxt) { if (seg->seq > priv->rcv_nxt) {
DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too new"); DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too new");
} else if (SMALLER_OR_EQUAL(seg->seq + seg->len, priv->rcv_nxt)) { } else if (SMALLER_OR_EQUAL(seg->seq + seg->len, priv->rcv_nxt)) {
...@@ -2208,12 +2209,19 @@ attempt_send(PseudoTcpSocket *self, SendFlags sflags) ...@@ -2208,12 +2209,19 @@ attempt_send(PseudoTcpSocket *self, SendFlags sflags)
available_space, snd_buffered - nInFlight, priv->ssthresh); available_space, snd_buffered - nInFlight, priv->ssthresh);
} }
if (sflags == sfDuplicateAck) {
packet(self, priv->snd_nxt, 0, 0, 0, now);
sflags = sfNone;
continue;
}
if (nAvailable == 0 && sflags != sfFin && sflags != sfRst) { if (nAvailable == 0 && sflags != sfFin && sflags != sfRst) {
if (sflags == sfNone) if (sflags == sfNone)
return; return;
// If this is an immediate ack, or the second delayed ack // If this is an immediate ack, or the second delayed ack
if ((sflags == sfImmediateAck) || priv->t_ack) { if ((sflags == sfImmediateAck || sflags == sfDuplicateAck) ||
priv->t_ack) {
packet(self, priv->snd_nxt, 0, 0, 0, now); packet(self, priv->snd_nxt, 0, 0, 0, now);
} else { } else {
priv->t_ack = now; priv->t_ack = now;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment