tcp: Ignore out-of-order ACKs from tap instead of resetting connection
We might receive out-of-order ACK packets from the tap device, just like any other packet. I guess I've been overcautious and regarded it as a condition we can't recover from, but all that happens is that we have already seen a higher ACK sequence number, which means that data has been already received and discarded from the buffer. We have to ignore the lower sequence number we receive later, though, because that would force the buffer bookkeeping into throwing away more data than expected. Drop the ACK sequence assignment from tcp_tap_handler(), which was redundant, and let tcp_sock_consume() take exclusive care of that. Now that tcp_sock_consume() can never fail, make it a void, and drop checks from callers. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
a418946837
commit
4f675d63e8
1 changed files with 11 additions and 22 deletions
33
tcp.c
33
tcp.c
|
@ -970,26 +970,27 @@ static int tcp_is_dupack(int s, uint32_t ack_seq)
|
|||
}
|
||||
|
||||
/**
|
||||
* tcp_sock_consume() - Consume (discard) data from socket buffer
|
||||
* tcp_sock_consume() - Consume (discard) data from buffer, update ACK sequence
|
||||
* @s: File descriptor number for socket
|
||||
* @ack_seq: ACK sequence, host order
|
||||
*
|
||||
* Return: negative on invalid sequence, 0 otherwise
|
||||
*/
|
||||
static int tcp_sock_consume(int s, uint32_t ack_seq)
|
||||
static void tcp_sock_consume(int s, uint32_t ack_seq)
|
||||
{
|
||||
int to_ack;
|
||||
|
||||
/* Implicitly take care of wrap-arounds */
|
||||
to_ack = ack_seq - tc[s].seq_ack_from_tap;
|
||||
|
||||
/* Simply ignore out-of-order ACKs: we already consumed the data we
|
||||
* needed from the buffer, and we won't rewind back to a lower ACK
|
||||
* sequence.
|
||||
*/
|
||||
if (to_ack < 0)
|
||||
return -EIO;
|
||||
return;
|
||||
|
||||
recv(s, NULL, to_ack, MSG_DONTWAIT | MSG_TRUNC);
|
||||
tc[s].seq_ack_from_tap = ack_seq;
|
||||
|
||||
return 0;
|
||||
tc[s].seq_ack_from_tap = ack_seq;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1146,12 +1147,7 @@ void tcp_tap_handler(struct ctx *c, int af, void *addr, char *in, size_t len)
|
|||
if (len == off)
|
||||
retrans = tcp_is_dupack(s, ntohl(th->ack_seq));
|
||||
|
||||
if (tcp_sock_consume(s, ntohl(th->ack_seq))) {
|
||||
tcp_rst(c, s);
|
||||
return;
|
||||
}
|
||||
|
||||
tc[s].seq_ack_from_tap = ntohl(th->ack_seq);
|
||||
tcp_sock_consume(s, ntohl(th->ack_seq));
|
||||
|
||||
if (retrans)
|
||||
tc[s].seq_to_tap = tc[s].seq_ack_from_tap;
|
||||
|
@ -1177,10 +1173,7 @@ void tcp_tap_handler(struct ctx *c, int af, void *addr, char *in, size_t len)
|
|||
|
||||
break;
|
||||
case CLOSE_WAIT:
|
||||
if (tcp_sock_consume(s, ntohl(th->ack_seq))) {
|
||||
tcp_rst(c, s);
|
||||
return;
|
||||
}
|
||||
tcp_sock_consume(s, ntohl(th->ack_seq));
|
||||
|
||||
if (skip < len - off &&
|
||||
tcp_send_to_sock(c, s, in + off + skip, len - off - skip,
|
||||
|
@ -1282,11 +1275,7 @@ void tcp_sock_handler(struct ctx *c, int s, uint32_t events)
|
|||
shutdown(s, SHUT_RD);
|
||||
tcp_data_from_sock(c, s);
|
||||
tcp_send_to_tap(c, s, FIN | ACK, NULL, 0);
|
||||
|
||||
if (tcp_sock_consume(s, tc[s].seq_ack_from_tap)) {
|
||||
tcp_rst(c, s);
|
||||
return;
|
||||
}
|
||||
tcp_sock_consume(s, tc[s].seq_ack_from_tap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue