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=VttPAmLW; 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 D3F8B5A027A for ; Wed, 20 Aug 2025 05:10:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1755659419; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GNtFd5PEi6TPzVfoLawKZSea/xuNEFimG4ijW0zIctU=; b=VttPAmLW25zoBJ1JRF2DaPGaTTOJY2iBoRd74Aj8vUdal8LqlMHltksLFnaabFht4d4J0X bOlPLfG1zA/VTUfhcKo+syx7bGwxn36PgR4/c7tFyRerb/KpeDO/FaHqA+IxtsRBOmXZbe MkpjUAxNzGSw/BbP1Wy0SbZ2SmsXM+0= 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-543-1ckmF5eWMBuazdcW5EZPYw-1; Tue, 19 Aug 2025 23:10:15 -0400 X-MC-Unique: 1ckmF5eWMBuazdcW5EZPYw-1 X-Mimecast-MFC-AGG-ID: 1ckmF5eWMBuazdcW5EZPYw_1755659414 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 C3C2319775A8; Wed, 20 Aug 2025 03:10:13 +0000 (UTC) Received: from jmaloy-thinkpadp16vgen1.rmtcaqc.csb (unknown [10.22.88.50]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id ABE8119A4C9C; Wed, 20 Aug 2025 03:10:12 +0000 (UTC) From: Jon Maloy To: sbrivio@redhat.com, dgibson@redhat.com, david@gibson.dropbear.id.au, jmaloy@redhat.com, passt-dev@passt.top Subject: [PATCH v4 4/9] udp: forward external source MAC address through tap interface Date: Tue, 19 Aug 2025 23:10:00 -0400 Message-ID: <20250820031005.2725591-5-jmaloy@redhat.com> In-Reply-To: <20250820031005.2725591-1-jmaloy@redhat.com> References: <20250820031005.2725591-1-jmaloy@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: LT3qkUGd1c8eHYCC2kUUL3PX4AiSv2ztftVJSSJqCq8_1755659414 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: RK2WN7BNJXPOFQ3VDJH2IDDNMWTPHEJ4 X-Message-ID-Hash: RK2WN7BNJXPOFQ3VDJH2IDDNMWTPHEJ4 X-MailFrom: jmaloy@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 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: We forward the incoming MAC address through the tap interface when receiving incoming packets from network local hosts. Packets from the own host are excepted from this rule, and are still forwarded with the default PASST/PASTA MAC address as source. This is a part of the solution to bug https://bugs.passt.top/show_bug.cgi?id=120 Signed-off-by: Jon Maloy --- passt.c | 2 +- udp.c | 39 ++++++++++++++++++++------------------- udp.h | 2 +- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/passt.c b/passt.c index 388d10f..477a01f 100644 --- a/passt.c +++ b/passt.c @@ -154,7 +154,7 @@ static void timer_init(struct ctx *c, const struct timespec *now) void proto_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s) { tcp_update_l2_buf(eth_d, eth_s); - udp_update_l2_buf(eth_d, eth_s); + udp_update_l2_buf(eth_d); } /** diff --git a/udp.c b/udp.c index 75edc20..35e3603 100644 --- a/udp.c +++ b/udp.c @@ -133,11 +133,8 @@ static int udp_splice_init[IP_VERSIONS][NUM_PORTS]; /* UDP header and data for inbound messages */ static struct udp_payload_t udp_payload[UDP_MAX_FRAMES]; -/* Ethernet header for IPv4 frames */ -static struct ethhdr udp4_eth_hdr; - -/* Ethernet header for IPv6 frames */ -static struct ethhdr udp6_eth_hdr; +/* Ethernet headers for IPv4 and IPv6 frames */ +static struct ethhdr udp_eth_hdr[UDP_MAX_FRAMES]; /** * struct udp_meta_t - Pre-cooked headers for UDP packets @@ -212,10 +209,12 @@ void udp_portmap_clear(void) * @eth_d: Ethernet destination address, NULL if unchanged * @eth_s: Ethernet source address, NULL if unchanged */ -void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s) +void udp_update_l2_buf(const unsigned char *eth_d) { - eth_update_mac(&udp4_eth_hdr, eth_d, eth_s); - eth_update_mac(&udp6_eth_hdr, eth_d, eth_s); + int i; + + for (i = 0; i < UDP_MAX_FRAMES; i++) + eth_update_mac(&udp_eth_hdr[i], eth_d, NULL); } /** @@ -238,6 +237,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i) *siov = IOV_OF_LVALUE(payload->data); + tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp_eth_hdr[i]); tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &meta->taph); tiov[UDP_IOV_PAYLOAD].iov_base = payload; @@ -253,9 +253,6 @@ static void udp_iov_init(const struct ctx *c) { size_t i; - udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP); - udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6); - for (i = 0; i < UDP_MAX_FRAMES; i++) udp_iov_init_one(c, i); } @@ -352,31 +349,34 @@ size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp, * udp_tap_prepare() - Convert one datagram into a tap frame * @mmh: Receiving mmsghdr array * @idx: Index of the datagram to prepare + * @tap_omac: MAC address of remote endpoint as seen from the guest * @toside: Flowside for destination side * @no_udp_csum: Do not set UDP checksum */ static void udp_tap_prepare(const struct mmsghdr *mmh, - unsigned idx, const struct flowside *toside, + unsigned int idx, + const unsigned char *tap_omac, + const struct flowside *toside, bool no_udp_csum) { struct iovec (*tap_iov)[UDP_NUM_IOVS] = &udp_l2_iov[idx]; struct udp_payload_t *bp = &udp_payload[idx]; struct udp_meta_t *bm = &udp_meta[idx]; + struct ethhdr *eh = (*tap_iov)[UDP_IOV_ETH].iov_base; size_t l4len; + eth_update_mac(eh, 0, tap_omac); if (!inany_v4(&toside->eaddr) || !inany_v4(&toside->oaddr)) { l4len = udp_update_hdr6(&bm->ip6h, bp, toside, mmh[idx].msg_len, no_udp_csum); - tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) + - sizeof(udp6_eth_hdr)); - (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr); + tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip6h) + ETH_HLEN); + eh->h_proto = htons_constant(ETH_P_IPV6); (*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip6h); } else { l4len = udp_update_hdr4(&bm->ip4h, bp, toside, mmh[idx].msg_len, no_udp_csum); - tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) + - sizeof(udp4_eth_hdr)); - (*tap_iov)[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr); + tap_hdr_update(&bm->taph, l4len + sizeof(bm->ip4h) + ETH_HLEN); + eh->h_proto = htons_constant(ETH_P_IP); (*tap_iov)[UDP_IOV_IP] = IOV_OF_LVALUE(bm->ip4h); } (*tap_iov)[UDP_IOV_PAYLOAD].iov_len = l4len; @@ -801,13 +801,14 @@ static void udp_buf_sock_to_tap(const struct ctx *c, int s, int n, flow_sidx_t tosidx) { const struct flowside *toside = flowside_at_sidx(tosidx); + const struct udp_flow *uflow = udp_at_sidx(tosidx); int i; if ((n = udp_sock_recv(c, s, udp_mh_recv, n)) <= 0) return; for (i = 0; i < n; i++) - udp_tap_prepare(udp_mh_recv, i, toside, false); + udp_tap_prepare(udp_mh_recv, i, uflow->f.tap_omac, toside, false); tap_send_frames(c, &udp_l2_iov[0][0], UDP_NUM_IOVS, n); } diff --git a/udp.h b/udp.h index 8f8531a..dd6e5ad 100644 --- a/udp.h +++ b/udp.h @@ -21,7 +21,7 @@ int udp_sock_init(const struct ctx *c, int ns, const union inany_addr *addr, const char *ifname, in_port_t port); int udp_init(struct ctx *c); void udp_timer(struct ctx *c, const struct timespec *now); -void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s); +void udp_update_l2_buf(const unsigned char *eth_d); /** * union udp_listen_epoll_ref - epoll reference for "listening" UDP sockets -- 2.50.1