aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorLaurent Vivier <lvivier@redhat.com>2024-06-13 14:36:48 +0200
committerStefano Brivio <sbrivio@redhat.com>2024-06-13 15:43:35 +0200
commitec26fa013ad94cab4e7585c3eaedddb4b41a64fa (patch)
tree98574b49b11de1ade779c0b49e182e88e6237d4e
parentd949667436a2c213a25170449894b312fad62d18 (diff)
downloadpasst-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.tar
passt-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.tar.gz
passt-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.tar.bz2
passt-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.tar.lz
passt-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.tar.xz
passt-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.tar.zst
passt-ec26fa013ad94cab4e7585c3eaedddb4b41a64fa.zip
tcp: extract buffer management from tcp_send_flag()
This commit isolates the internal data structure management used for storing data (e.g., tcp4_l2_flags_iov[], tcp6_l2_flags_iov[], tcp4_flags_ip[], tcp4_flags[], ...) from the tcp_send_flag() function. The extracted functionality is relocated to a new function named tcp_fill_flag_header(). tcp_fill_flag_header() is now a generic function that accepts parameters such as struct tcphdr and a data pointer. tcp_send_flag() utilizes this parameter to pass memory pointers from tcp4_l2_flags_iov[] and tcp6_l2_flags_iov[]. This separation sets the stage for utilizing tcp_prepare_flags() to set the memory provided by the guest via vhost-user in future developments. Signed-off-by: Laurent Vivier <lvivier@redhat.com> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r--tcp.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/tcp.c b/tcp.c
index dd8d46e..e40f422 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1567,24 +1567,25 @@ static void tcp_update_seqack_from_tap(const struct ctx *c,
}
/**
- * tcp_send_flag() - Send segment with flags to tap (no payload)
+ * tcp_prepare_flags() - Prepare header for flags-only segment (no payload)
* @c: Execution context
* @conn: Connection pointer
* @flags: TCP flags: if not set, send segment only if ACK is due
+ * @th: TCP header to update
+ * @data: buffer to store TCP option
+ * @optlen: size of the TCP option buffer (output parameter)
*
- * Return: negative error code on connection reset, 0 otherwise
+ * Return: < 0 error code on connection reset,
+ * 0 if there is no flag to send
+ * 1 otherwise
*/
-static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
+static int tcp_prepare_flags(struct ctx *c, struct tcp_tap_conn *conn,
+ int flags, struct tcphdr *th, char *data,
+ size_t *optlen)
{
- struct tcp_flags_t *payload;
struct tcp_info tinfo = { 0 };
socklen_t sl = sizeof(tinfo);
int s = conn->sock;
- size_t optlen = 0;
- struct tcphdr *th;
- struct iovec *iov;
- size_t l4len;
- char *data;
if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap) &&
!flags && conn->wnd_to_tap)
@@ -1606,20 +1607,12 @@ static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
if (!tcp_update_seqack_wnd(c, conn, flags, &tinfo) && !flags)
return 0;
- if (CONN_V4(conn))
- iov = tcp4_l2_flags_iov[tcp4_flags_used++];
- else
- iov = tcp6_l2_flags_iov[tcp6_flags_used++];
-
- payload = iov[TCP_IOV_PAYLOAD].iov_base;
- th = &payload->th;
- data = payload->opts;
-
+ *optlen = 0;
if (flags & SYN) {
int mss;
/* Options: MSS, NOP and window scale (8 bytes) */
- optlen = OPT_MSS_LEN + 1 + OPT_WS_LEN;
+ *optlen = OPT_MSS_LEN + 1 + OPT_WS_LEN;
*data++ = OPT_MSS;
*data++ = OPT_MSS_LEN;
@@ -1653,17 +1646,13 @@ static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
flags |= ACK;
}
- th->doff = (sizeof(*th) + optlen) / 4;
+ th->doff = (sizeof(*th) + *optlen) / 4;
th->ack = !!(flags & ACK);
th->rst = !!(flags & RST);
th->syn = !!(flags & SYN);
th->fin = !!(flags & FIN);
- l4len = tcp_l2_buf_fill_headers(c, conn, iov, optlen, NULL,
- conn->seq_to_tap);
- iov[TCP_IOV_PAYLOAD].iov_len = l4len;
-
if (th->ack) {
if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap))
conn_flag(c, conn, ~ACK_TO_TAP_DUE);
@@ -1678,6 +1667,47 @@ static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
if (th->fin || th->syn)
conn->seq_to_tap++;
+ return 1;
+}
+
+/**
+ * tcp_send_flag() - Send segment with flags to tap (no payload)
+ * @c: Execution context
+ * @conn: Connection pointer
+ * @flags: TCP flags: if not set, send segment only if ACK is due
+ *
+ * Return: negative error code on connection reset, 0 otherwise
+ */
+static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
+{
+ struct tcp_flags_t *payload;
+ struct iovec *iov;
+ size_t optlen;
+ size_t l4len;
+ uint32_t seq;
+ int ret;
+
+ if (CONN_V4(conn))
+ iov = tcp4_l2_flags_iov[tcp4_flags_used++];
+ else
+ iov = tcp6_l2_flags_iov[tcp6_flags_used++];
+
+ payload = iov[TCP_IOV_PAYLOAD].iov_base;
+
+ seq = conn->seq_to_tap;
+ ret = tcp_prepare_flags(c, conn, flags, &payload->th,
+ payload->opts, &optlen);
+ if (ret <= 0) {
+ if (CONN_V4(conn))
+ tcp4_flags_used--;
+ else
+ tcp6_flags_used--;
+ return ret;
+ }
+
+ l4len = tcp_l2_buf_fill_headers(c, conn, iov, optlen, NULL, seq);
+ iov[TCP_IOV_PAYLOAD].iov_len = l4len;
+
if (flags & DUP_ACK) {
struct iovec *dup_iov;
int i;