diff options
Diffstat (limited to 'tcp.c')
| -rw-r--r-- | tcp.c | 29 |
1 files changed, 27 insertions, 2 deletions
@@ -1837,10 +1837,35 @@ static int tcp_sock_consume(const struct tcp_tap_conn *conn, uint32_t ack_seq) */ static int tcp_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) { + uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; + uint32_t already_sent; + + /* How much have we read/sent since last received ack ? */ + already_sent = conn->seq_to_tap - conn->seq_ack_from_tap; + + if (SEQ_LT(already_sent, 0)) { + /* RFC 761, section 2.1. */ + flow_trace(conn, "ACK sequence gap: ACK for %u, sent: %u", + conn->seq_ack_from_tap, conn->seq_to_tap); + conn->seq_to_tap = conn->seq_ack_from_tap; + already_sent = 0; + if (tcp_set_peek_offset(conn, 0)) { + tcp_rst(c, conn); + return -1; + } + } + + if (!wnd_scaled || already_sent >= wnd_scaled) { + conn_flag(c, conn, ACK_FROM_TAP_BLOCKS); + conn_flag(c, conn, STALLED); + conn_flag(c, conn, ACK_FROM_TAP_DUE); + return 0; + } + if (c->mode == MODE_VU) - return tcp_vu_data_from_sock(c, conn); + return tcp_vu_data_from_sock(c, conn, already_sent); - return tcp_buf_data_from_sock(c, conn); + return tcp_buf_data_from_sock(c, conn, already_sent); } /** |
