tcp: Don't set ACK flag while merely updating window value
The receiver might take this as a duplicate ACK othewise. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
81128241d6
commit
ffaf1d09f2
1 changed files with 19 additions and 15 deletions
34
tcp.c
34
tcp.c
|
@ -1273,6 +1273,7 @@ static int tcp_send_to_tap(struct ctx *c, struct tcp_tap_conn *conn, int flags,
|
||||||
{
|
{
|
||||||
char buf[sizeof(struct tcphdr) + OPT_MSS_LEN + OPT_WS_LEN + 1] = { 0 };
|
char buf[sizeof(struct tcphdr) + OPT_MSS_LEN + OPT_WS_LEN + 1] = { 0 };
|
||||||
uint32_t prev_ack_to_tap = conn->seq_ack_to_tap;
|
uint32_t prev_ack_to_tap = conn->seq_ack_to_tap;
|
||||||
|
uint32_t prev_wnd_to_tap = conn->wnd_to_tap;
|
||||||
struct tcp_info info = { 0 };
|
struct tcp_info info = { 0 };
|
||||||
socklen_t sl = sizeof(info);
|
socklen_t sl = sizeof(info);
|
||||||
int s = conn->sock;
|
int s = conn->sock;
|
||||||
|
@ -1284,17 +1285,30 @@ static int tcp_send_to_tap(struct ctx *c, struct tcp_tap_conn *conn, int flags,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (conn->snd_buf < SNDBUF_SMALL)
|
if (conn->snd_buf < SNDBUF_SMALL)
|
||||||
tcp_get_sndbuf(c, conn);
|
tcp_get_sndbuf(conn);
|
||||||
|
|
||||||
if (getsockopt(s, SOL_TCP, TCP_INFO, &info, &sl)) {
|
if (getsockopt(s, SOL_TCP, TCP_INFO, &info, &sl)) {
|
||||||
tcp_rst(c, conn);
|
tcp_rst(c, conn);
|
||||||
return -ECONNRESET;
|
return -ECONNRESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!conn->local)
|
||||||
|
tcp_rtt_dst_check(conn, &info);
|
||||||
|
|
||||||
th = (struct tcphdr *)buf;
|
th = (struct tcphdr *)buf;
|
||||||
data = (char *)(th + 1);
|
data = (char *)(th + 1);
|
||||||
th->doff = sizeof(*th) / 4;
|
th->doff = sizeof(*th) / 4;
|
||||||
|
|
||||||
|
if (conn->state > ESTABLISHED || (flags & (DUP_ACK | FORCE_ACK))) {
|
||||||
|
conn->seq_ack_to_tap = conn->seq_from_tap;
|
||||||
|
} else {
|
||||||
|
conn->seq_ack_to_tap = info.tcpi_bytes_acked +
|
||||||
|
conn->seq_init_from_tap;
|
||||||
|
|
||||||
|
if (SEQ_LT(conn->seq_ack_to_tap, prev_ack_to_tap))
|
||||||
|
conn->seq_ack_to_tap = prev_ack_to_tap;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & SYN) {
|
if (flags & SYN) {
|
||||||
uint16_t mss;
|
uint16_t mss;
|
||||||
|
|
||||||
|
@ -1338,23 +1352,13 @@ static int tcp_send_to_tap(struct ctx *c, struct tcp_tap_conn *conn, int flags,
|
||||||
|
|
||||||
th->ack = !!(flags & ACK);
|
th->ack = !!(flags & ACK);
|
||||||
} else {
|
} else {
|
||||||
th->ack = 1;
|
th->ack = !!(flags & (ACK | FORCE_ACK | DUP_ACK)) ||
|
||||||
|
conn->seq_ack_to_tap != prev_ack_to_tap;
|
||||||
th->seq = htonl(conn->seq_to_tap);
|
th->seq = htonl(conn->seq_to_tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->state > ESTABLISHED || (flags & (DUP_ACK | FORCE_ACK))) {
|
if (!flags && conn->seq_ack_to_tap == prev_ack_to_tap &&
|
||||||
conn->seq_ack_to_tap = conn->seq_from_tap;
|
conn->wnd_to_tap == prev_wnd_to_tap)
|
||||||
} else {
|
|
||||||
conn->seq_ack_to_tap = info.tcpi_bytes_acked +
|
|
||||||
conn->seq_init_from_tap;
|
|
||||||
|
|
||||||
if (SEQ_LT(conn->seq_ack_to_tap, prev_ack_to_tap))
|
|
||||||
conn->seq_ack_to_tap = prev_ack_to_tap;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!flags &&
|
|
||||||
conn->seq_ack_to_tap == prev_ack_to_tap &&
|
|
||||||
c->tcp.kernel_snd_wnd && conn->wnd_to_tap == info.tcpi_snd_wnd)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
th->ack_seq = htonl(conn->seq_ack_to_tap);
|
th->ack_seq = htonl(conn->seq_ack_to_tap);
|
||||||
|
|
Loading…
Reference in a new issue