From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=R2grUTXh; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by passt.top (Postfix) with ESMTPS id 9EE875A065C for ; Mon, 23 Mar 2026 17:53:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774284787; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RQVJFWnNdLeXOSVnpO3dl8hQSoATRxCt+FunKT4IT2A=; b=R2grUTXh5dOVJJVZDKIddvrXMkpQUz+SxOozAbSLyjJNVPSmOm5/szdgt/v3jak7Q4tMZ0 tKbwUFALOi9WB2y21t/vzNMFiFjobGDnPKaCaFTjAZw1V45MLWMsi+BIAxJr2U+psAU2gq fENmqnRejRrD+pNMoCQhUJ88LfOY3L4= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-679-zNUmWF5nPRayXCu4DVTNTg-1; Mon, 23 Mar 2026 12:53:05 -0400 X-MC-Unique: zNUmWF5nPRayXCu4DVTNTg-1 X-Mimecast-MFC-AGG-ID: zNUmWF5nPRayXCu4DVTNTg_1774284785 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1F6771954B17 for ; Mon, 23 Mar 2026 16:53:05 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.44.32.96]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E268A300019F; Mon, 23 Mar 2026 16:53:03 +0000 (UTC) From: Laurent Vivier To: passt-dev@passt.top Subject: [PATCH 2/7] tcp: use iov_tail to access headers in tcp_fill_headers() Date: Mon, 23 Mar 2026 17:52:54 +0100 Message-ID: <20260323165259.1253482-3-lvivier@redhat.com> In-Reply-To: <20260323165259.1253482-1-lvivier@redhat.com> References: <20260323165259.1253482-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: QzW-ptos8DE8Oexy3RJNbQa_vZTpfBEYR6itUTuzkcI_1774284785 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: FRXL3HU3PQSPQSWN4LPOPJQFG75G72S4 X-Message-ID-Hash: FRXL3HU3PQSPQSWN4LPOPJQFG75G72S4 X-MailFrom: lvivier@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Laurent Vivier X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Instead of receiving individual pointers to each protocol header (eh, ip4h, ip6h, th), have tcp_fill_headers() take an iov_tail starting at the Ethernet header and walk through it using with_header() and IOV_DROP_HEADER() to access each header in turn. Replace the ip4h/ip6h NULL-pointer convention with a bool ipv4 parameter, and move Ethernet header filling (MAC address and ethertype) into tcp_fill_headers() as well, since the function now owns the full header chain. This simplifies callers, which no longer need to extract and pass individual header pointers. Signed-off-by: Laurent Vivier --- tcp.c | 106 +++++++++++++++++++++++++++---------------------- tcp_buf.c | 16 ++------ tcp_internal.h | 4 +- tcp_vu.c | 12 +++--- 4 files changed, 70 insertions(+), 68 deletions(-) diff --git a/tcp.c b/tcp.c index 158a5be0327e..058792d5b184 100644 --- a/tcp.c +++ b/tcp.c @@ -938,11 +938,8 @@ static void tcp_fill_header(struct tcphdr *th, * tcp_fill_headers() - Fill 802.3, IP, TCP headers * @c: Execution context * @conn: Connection pointer - * @eh: Pointer to Ethernet header - * @ip4h: Pointer to IPv4 header, or NULL - * @ip6h: Pointer to IPv6 header, or NULL - * @th: Pointer to TCP header - * @payload: TCP payload + * @ipv4: True for IPv4, false for IPv6 + * @payload: IOV tail starting at the Ethernet header * @ip4_check: IPv4 checksum, if already known * @seq: Sequence number for this segment * @no_tcp_csum: Do not set TCP checksum @@ -950,74 +947,89 @@ static void tcp_fill_header(struct tcphdr *th, * Return: frame length (including L2 headers) */ size_t tcp_fill_headers(const struct ctx *c, struct tcp_tap_conn *conn, - struct ethhdr *eh, - struct iphdr *ip4h, struct ipv6hdr *ip6h, - struct tcphdr *th, struct iov_tail *payload, + bool ipv4, const struct iov_tail *payload, int ip4_check, uint32_t seq, bool no_tcp_csum) { const struct flowside *tapside = TAPFLOW(conn); - size_t l4len = iov_tail_size(payload) + sizeof(*th); + struct iov_tail current = *payload; uint8_t *omac = conn->f.tap_omac; - size_t l3len = l4len; + size_t l3len, l4len; uint32_t psum = 0; - if (ip4h) { + with_header(struct ethhdr, eh, ¤t) { + if (ipv4) + eh->h_proto = htons_constant(ETH_P_IP); + else + eh->h_proto = htons_constant(ETH_P_IPV6); + + /* Find if neighbour table has a recorded MAC address */ + if (MAC_IS_UNDEF(omac)) + fwd_neigh_mac_get(c, &tapside->oaddr, omac); + eth_update_mac(eh, NULL, omac); + } + IOV_DROP_HEADER(¤t, struct ethhdr); + + l3len = iov_tail_size(¤t); + + if (ipv4) { const struct in_addr *src4 = inany_v4(&tapside->oaddr); const struct in_addr *dst4 = inany_v4(&tapside->eaddr); assert(src4 && dst4); - l3len += + sizeof(*ip4h); + l4len = l3len - sizeof(struct iphdr); - ip4h->tot_len = htons(l3len); - ip4h->saddr = src4->s_addr; - ip4h->daddr = dst4->s_addr; + with_header(struct iphdr, ip4h, ¤t) { + ip4h->tot_len = htons(l3len); + ip4h->saddr = src4->s_addr; + ip4h->daddr = dst4->s_addr; - if (ip4_check != -1) - ip4h->check = ip4_check; - else - ip4h->check = csum_ip4_header(l3len, IPPROTO_TCP, - *src4, *dst4); + if (ip4_check != -1) + ip4h->check = ip4_check; + else + ip4h->check = csum_ip4_header(l3len, + IPPROTO_TCP, + *src4, *dst4); + } + IOV_DROP_HEADER(¤t, struct iphdr); if (!no_tcp_csum) { psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP, *src4, *dst4); } - eh->h_proto = htons_constant(ETH_P_IP); - } - - if (ip6h) { - l3len += sizeof(*ip6h); + } else { + l4len = l3len - sizeof(struct ipv6hdr); - ip6h->payload_len = htons(l4len); - ip6h->saddr = tapside->oaddr.a6; - ip6h->daddr = tapside->eaddr.a6; + with_header(struct ipv6hdr, ip6h, ¤t) { + ip6h->payload_len = htons(l4len); + ip6h->saddr = tapside->oaddr.a6; + ip6h->daddr = tapside->eaddr.a6; - ip6h->hop_limit = 255; - ip6h->version = 6; - ip6h->nexthdr = IPPROTO_TCP; + ip6h->hop_limit = 255; + ip6h->version = 6; + ip6h->nexthdr = IPPROTO_TCP; - ip6_set_flow_lbl(ip6h, conn->sock); + ip6_set_flow_lbl(ip6h, conn->sock); - if (!no_tcp_csum) { - psum = proto_ipv6_header_psum(l4len, IPPROTO_TCP, - &ip6h->saddr, - &ip6h->daddr); + if (!no_tcp_csum) { + psum = proto_ipv6_header_psum(l4len, + IPPROTO_TCP, + &ip6h->saddr, + &ip6h->daddr); + } } - eh->h_proto = htons_constant(ETH_P_IPV6); + IOV_DROP_HEADER(¤t, struct ipv6hdr); } - /* Find if neighbour table has a recorded MAC address */ - if (MAC_IS_UNDEF(omac)) - fwd_neigh_mac_get(c, &tapside->oaddr, omac); - eth_update_mac(eh, NULL, omac); - - tcp_fill_header(th, conn, seq); - - if (no_tcp_csum) + with_header(struct tcphdr, th, ¤t) { + tcp_fill_header(th, conn, seq); th->check = 0; - else - tcp_update_csum(psum, th, payload); + } + + if (!no_tcp_csum) { + with_header(struct tcphdr, th, ¤t) + th->check = csum_iov_tail(¤t, psum); + } return MAX(l3len + sizeof(struct ethhdr), ETH_ZLEN); } diff --git a/tcp_buf.c b/tcp_buf.c index bc0f58dd7a5e..891043c96dcb 100644 --- a/tcp_buf.c +++ b/tcp_buf.c @@ -175,23 +175,15 @@ static void tcp_l2_buf_fill_headers(const struct ctx *c, struct iovec *iov, int check, uint32_t seq, bool no_tcp_csum) { - struct iov_tail tail = IOV_TAIL(&iov[TCP_IOV_PAYLOAD], 1, 0); - struct tcphdr th_storage, *th = IOV_REMOVE_HEADER(&tail, th_storage); + struct iov_tail tail = IOV_TAIL(&iov[TCP_IOV_ETH], + TCP_IOV_PAYLOAD + 1 - TCP_IOV_ETH, 0); struct tap_hdr *taph = iov[TCP_IOV_TAP].iov_base; const struct flowside *tapside = TAPFLOW(conn); - const struct in_addr *a4 = inany_v4(&tapside->oaddr); - struct ethhdr *eh = iov[TCP_IOV_ETH].iov_base; - struct ipv6hdr *ip6h = NULL; - struct iphdr *ip4h = NULL; + bool ipv4 = inany_v4(&tapside->oaddr) != NULL; size_t l2len; - if (a4) - ip4h = iov[TCP_IOV_IP].iov_base; - else - ip6h = iov[TCP_IOV_IP].iov_base; + l2len = tcp_fill_headers(c, conn, ipv4, &tail, check, seq, no_tcp_csum); - l2len = tcp_fill_headers(c, conn, eh, ip4h, ip6h, th, &tail, check, seq, - no_tcp_csum); tap_hdr_update(taph, l2len); } diff --git a/tcp_internal.h b/tcp_internal.h index bb7a6629839c..136e947f6e70 100644 --- a/tcp_internal.h +++ b/tcp_internal.h @@ -184,9 +184,7 @@ void tcp_rst_do(const struct ctx *c, struct tcp_tap_conn *conn); struct tcp_info_linux; size_t tcp_fill_headers(const struct ctx *c, struct tcp_tap_conn *conn, - struct ethhdr *eh, - struct iphdr *ip4h, struct ipv6hdr *ip6h, - struct tcphdr *th, struct iov_tail *payload, + bool ipv4, const struct iov_tail *payload, int ip4_check, uint32_t seq, bool no_tcp_csum); int tcp_update_seqack_wnd(const struct ctx *c, struct tcp_tap_conn *conn, diff --git a/tcp_vu.c b/tcp_vu.c index a21ee3499aed..c6206b7a689c 100644 --- a/tcp_vu.c +++ b/tcp_vu.c @@ -132,13 +132,12 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags) } vu_pad(&flags_iov[0], 1, 0, hdrlen + optlen); - payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen); if (flags & KEEPALIVE) seq--; - tcp_fill_headers(c, conn, eh, ip4h, ip6h, th, &payload, - -1, seq, !*c->pcap); + payload = IOV_TAIL(flags_elem[0].in_sg, 1, VNET_HLEN); + tcp_fill_headers(c, conn, CONN_V4(conn), &payload, -1, seq, !*c->pcap); if (*c->pcap) pcap_iov(&flags_elem[0].in_sg[0], 1, VNET_HLEN); @@ -288,10 +287,10 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn, const struct flowside *toside = TAPFLOW(conn); bool v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr)); size_t hdrlen = tcp_vu_hdrlen(v6); - struct iov_tail payload = IOV_TAIL(iov, iov_cnt, hdrlen); char *base = iov[0].iov_base; struct ipv6hdr *ip6h = NULL; struct iphdr *ip4h = NULL; + struct iov_tail payload; struct tcphdr *th; struct ethhdr *eh; @@ -326,8 +325,9 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn, th->ack = 1; th->psh = push; - tcp_fill_headers(c, conn, eh, ip4h, ip6h, th, &payload, - *check, conn->seq_to_tap, no_tcp_csum); + payload = IOV_TAIL(iov, iov_cnt, VNET_HLEN); + tcp_fill_headers(c, conn, !v6, &payload, *check, conn->seq_to_tap, + no_tcp_csum); if (ip4h) *check = ip4h->check; } -- 2.53.0