diff options
| author | David Gibson <david@gibson.dropbear.id.au> | 2026-06-15 18:18:31 +1000 |
|---|---|---|
| committer | Stefano Brivio <sbrivio@redhat.com> | 2026-06-16 23:49:39 +0200 |
| commit | 751a6f1d3288334afd3eda687e46968a5b5861bd (patch) | |
| tree | b02da5c9ea982f5b799705b499b4c26fa91c1cea | |
| parent | 46048603c0cbf4899323447e72720e550a684599 (diff) | |
| download | passt-751a6f1d3288334afd3eda687e46968a5b5861bd.tar passt-751a6f1d3288334afd3eda687e46968a5b5861bd.tar.gz passt-751a6f1d3288334afd3eda687e46968a5b5861bd.tar.bz2 passt-751a6f1d3288334afd3eda687e46968a5b5861bd.tar.lz passt-751a6f1d3288334afd3eda687e46968a5b5861bd.tar.xz passt-751a6f1d3288334afd3eda687e46968a5b5861bd.tar.zst passt-751a6f1d3288334afd3eda687e46968a5b5861bd.zip | |
tcp: Merge common sequence logic from tcp_{buf,vu}_data_from_sock()
tcp_buf_data_from_sock() and tcp_vu_data_from_sock() start with some
identical logic to compute the amount of data from the socket that has
already been sent to tap but not acked. Replace it with a single copy in
their common caller tcp_data_from_sock(), passing the already_sent amount
in as a parameter.
This does mean that we now execute this logic in the VU case even if the
queue is not active. The logic is still valid in this case, and we don't
need to worry too much about wasting cycles in this edge case.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
| -rw-r--r-- | tcp.c | 29 | ||||
| -rw-r--r-- | tcp_buf.c | 28 | ||||
| -rw-r--r-- | tcp_buf.h | 3 | ||||
| -rw-r--r-- | tcp_vu.c | 27 | ||||
| -rw-r--r-- | tcp_vu.h | 3 |
5 files changed, 39 insertions, 51 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); } /** @@ -309,42 +309,22 @@ static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn, * tcp_buf_data_from_sock() - Handle new data from socket, queue to tap, in window * @c: Execution context * @conn: Connection pointer + * @already_sent: Number of bytes already sent to tap, but not acked * * Return: negative on connection reset, 0 otherwise * * #syscalls recvmsg */ -int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) +int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent) { uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; int fill_bufs, send_bufs = 0, last_len, iov_rem = 0; int len, dlen, i, s = conn->sock; struct msghdr mh_sock = { 0 }; uint16_t mss = MSS_GET(conn); - uint32_t already_sent, seq; struct iovec *iov; - - /* 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; - } + uint32_t seq; /* Set up buffer descriptors we'll fill completely and partially. */ fill_bufs = DIV_ROUND_UP(wnd_scaled - already_sent, mss); @@ -8,7 +8,8 @@ void tcp_sock_iov_init(const struct ctx *c); void tcp_payload_flush(const struct ctx *c); -int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn); +int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent); int tcp_buf_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags); #endif /*TCP_BUF_H */ @@ -423,46 +423,27 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn, * in window * @c: Execution context * @conn: Connection pointer + * @already_sent: Number of bytes already sent to tap, but not acked * * Return: negative on connection reset, 0 otherwise */ -int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) +int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent) { uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; struct vu_dev *vdev = c->vdev; struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE]; - uint32_t already_sent, check; ssize_t len, previous_dlen; int i, elem_cnt, frame_cnt; size_t hdrlen, fillsize; int v6 = CONN_V6(conn); + uint32_t check; if (!vu_queue_enabled(vq) || !vu_queue_started(vq)) { debug("Got packet, but RX virtqueue not usable yet"); return 0; } - 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; - } - /* Set up buffer descriptors we'll fill completely and partially. */ fillsize = wnd_scaled - already_sent; @@ -7,6 +7,7 @@ #define TCP_VU_H int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags); -int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn); +int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent); #endif /*TCP_VU_H */ |
