public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Jon Maloy <jmaloy@redhat.com>
To: sbrivio@redhat.com, dgibson@redhat.com, jmaloy@redhat.com,
	passt-dev@passt.top
Subject: [PATCH 1/2] make ttl parametrized
Date: Wed, 23 Apr 2025 22:52:26 -0400	[thread overview]
Message-ID: <20250424025227.61697-2-jmaloy@redhat.com> (raw)
In-Reply-To: <20250424025227.61697-1-jmaloy@redhat.com>

Currently, IPv4 TTL and IPv6 hop_limit for packets sent out over the tap
interface always are given the value 255. Even the checksum algorithm
is hard coded to assume this value.

In some cases we may want the TTL of packets arriving at the incoming
socket to be propagated to the internal peer via the tap interface, so
we need to make the value parametrized when we set the ip header. We
also need to update the checksum algorithms to take this change into
account.

We do that in this commit, at the same time changing the default
TTL/hop_limit from 255 to 64.

Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
 checksum.c     |  7 +++++--
 checksum.h     |  2 +-
 ip.h           | 11 +++++------
 tap.c          | 16 +++++++++-------
 tap.h          |  6 ++----
 tcp.c          |  5 +++--
 udp.c          | 18 +++++++++++-------
 udp_internal.h |  4 ++--
 udp_vu.c       |  6 ++++--
 9 files changed, 42 insertions(+), 33 deletions(-)

diff --git a/checksum.c b/checksum.c
index 0894eca..2e19722 100644
--- a/checksum.c
+++ b/checksum.c
@@ -124,11 +124,14 @@ static uint16_t csum_fold(uint32_t sum)
  *
  * Return: 16-bit folded sum of the IPv4 header
  */
-uint16_t csum_ip4_header(uint16_t l3len, uint8_t protocol,
+uint16_t csum_ip4_header(uint16_t l3len, uint8_t protocol, uint8_t ttl,
 			 struct in_addr saddr, struct in_addr daddr)
 {
-	uint32_t sum = L2_BUF_IP4_PSUM(protocol);
+	uint32_t sum;
 
+	sum = (uint32_t)htons_constant(0x4500);
+	sum += (uint32_t)htons_constant(IP_DF);
+	sum += htons((ttl << 8) | protocol);
 	sum += htons(l3len);
 	sum += (saddr.s_addr >> 16) & 0xffff;
 	sum += saddr.s_addr & 0xffff;
diff --git a/checksum.h b/checksum.h
index 683a09b..a9ebf96 100644
--- a/checksum.h
+++ b/checksum.h
@@ -12,7 +12,7 @@ struct icmp6hdr;
 struct iov_tail;
 
 uint16_t csum_unaligned(const void *buf, size_t len, uint32_t init);
-uint16_t csum_ip4_header(uint16_t l3len, uint8_t protocol,
+uint16_t csum_ip4_header(uint16_t l3len, uint8_t protocol, uint8_t ttl,
 			 struct in_addr saddr, struct in_addr daddr);
 uint32_t proto_ipv4_header_psum(uint16_t l4len, uint8_t protocol,
 				struct in_addr saddr, struct in_addr daddr);
diff --git a/ip.h b/ip.h
index 471c57e..b67a7b7 100644
--- a/ip.h
+++ b/ip.h
@@ -9,6 +9,9 @@
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
 
+#define DEFAULT_TTL 64
+#define NTP_HOP_LIMIT 255
+
 #define IN4_IS_ADDR_UNSPECIFIED(a) \
 	(((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_ANY))
 #define IN4_IS_ADDR_BROADCAST(a) \
@@ -37,15 +40,11 @@
 		.tot_len	= 0,					\
 		.id		= 0,					\
 		.frag_off	= htons(IP_DF), 			\
-		.ttl		= 0xff,					\
+		.ttl		= DEFAULT_TTL,				\
 		.protocol	= (proto),				\
 		.saddr		= 0,					\
 		.daddr		= 0,					\
 	}
-#define L2_BUF_IP4_PSUM(proto)	((uint32_t)htons_constant(0x4500) +	\
-				 (uint32_t)htons_constant(IP_DF) +	\
-				 (uint32_t)htons(0xff00 | (proto)))
-
 
 #define IN6_IS_PREFIX_LINKLOCAL(a, len)					\
 	((len) >= 10 && IN6_IS_ADDR_LINKLOCAL(a))
@@ -57,7 +56,7 @@
 		.flow_lbl	= { 0 },				\
 		.payload_len	= 0,					\
 		.nexthdr	= (proto),				\
-		.hop_limit	= 255,					\
+		.hop_limit	= DEFAULT_TTL,				\
 		.saddr		= IN6ADDR_ANY_INIT,			\
 		.daddr		= IN6ADDR_ANY_INIT,			\
 	}
diff --git a/tap.c b/tap.c
index d630f6d..8a66ca3 100644
--- a/tap.c
+++ b/tap.c
@@ -205,11 +205,11 @@ void *tap_push_ip4h(struct iphdr *ip4h, struct in_addr src,
 	ip4h->tot_len = htons(l3len);
 	ip4h->id = 0;
 	ip4h->frag_off = htons(IP_DF);
-	ip4h->ttl = 255;
+	ip4h->ttl = DEFAULT_TTL;
 	ip4h->protocol = proto;
 	ip4h->saddr = src.s_addr;
 	ip4h->daddr = dst.s_addr;
-	ip4h->check = csum_ip4_header(l3len, proto, src, dst);
+	ip4h->check = csum_ip4_header(l3len, proto, DEFAULT_TTL, src, dst);
 	return (char *)ip4h + sizeof(*ip4h);
 }
 
@@ -302,13 +302,14 @@ void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
  */
 void *tap_push_ip6h(struct ipv6hdr *ip6h,
 		    const struct in6_addr *src, const struct in6_addr *dst,
-		    size_t l4len, uint8_t proto, uint32_t flow)
+		    size_t l4len, uint8_t proto, uint8_t hop_limit,
+		    uint32_t flow)
 {
 	ip6h->payload_len = htons(l4len);
 	ip6h->priority = 0;
 	ip6h->version = 6;
 	ip6h->nexthdr = proto;
-	ip6h->hop_limit = 255;
+	ip6h->hop_limit = hop_limit;
 	ip6h->saddr = *src;
 	ip6h->daddr = *dst;
 	ip6_set_flow_lbl(ip6h, flow);
@@ -366,8 +367,8 @@ void tap_udp6_send(const struct ctx *c,
 	size_t l4len = dlen + sizeof(struct udphdr);
 	char buf[USHRT_MAX];
 	struct ipv6hdr *ip6h = tap_push_l2h(c, buf, ETH_P_IPV6);
-	struct udphdr *uh = tap_push_ip6h(ip6h, src, dst,
-					  l4len, IPPROTO_UDP, flow);
+	struct udphdr *uh = tap_push_ip6h(ip6h, src, dst, l4len,
+					  IPPROTO_UDP, DEFAULT_TTL, flow);
 	char *data = tap_push_uh6(uh, src, sport, dst, dport, in, dlen);
 
 	memcpy(data, in, dlen);
@@ -389,7 +390,8 @@ void tap_icmp6_send(const struct ctx *c,
 	char buf[USHRT_MAX];
 	struct ipv6hdr *ip6h = tap_push_l2h(c, buf, ETH_P_IPV6);
 	struct icmp6hdr *icmp6h = tap_push_ip6h(ip6h, src, dst, l4len,
-						IPPROTO_ICMPV6, 0);
+						IPPROTO_ICMPV6, NTP_HOP_LIMIT,
+						0);
 
 	memcpy(icmp6h, in, l4len);
 	csum_icmp6(icmp6h, src, dst, icmp6h + 1, l4len - sizeof(*icmp6h));
diff --git a/tap.h b/tap.h
index 6fe3d15..d166226 100644
--- a/tap.h
+++ b/tap.h
@@ -85,7 +85,8 @@ void *tap_push_ip4h(struct iphdr *ip4h, struct in_addr src,
 void *tap_push_ip6h(struct ipv6hdr *ip6h,
 		    const struct in6_addr *src,
 		    const struct in6_addr *dst,
-		    size_t l4len, uint8_t proto, uint32_t flow);
+		    size_t l4len, uint8_t proto,
+		    uint8_t hop_limit, uint32_t flow);
 void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport,
 		   struct in_addr dst, in_port_t dport,
 		   const void *in, size_t dlen);
@@ -93,9 +94,6 @@ void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
 		    const void *in, size_t l4len);
 const struct in6_addr *tap_ip6_daddr(const struct ctx *c,
 				     const struct in6_addr *src);
-void *tap_push_ip6h(struct ipv6hdr *ip6h,
-		    const struct in6_addr *src, const struct in6_addr *dst,
-		    size_t l4len, uint8_t proto, uint32_t flow);
 void tap_udp6_send(const struct ctx *c,
 		   const struct in6_addr *src, in_port_t sport,
 		   const struct in6_addr *dst, in_port_t dport,
diff --git a/tcp.c b/tcp.c
index 0ac298a..6948c5e 100644
--- a/tcp.c
+++ b/tcp.c
@@ -946,7 +946,7 @@ void tcp_fill_headers(const struct tcp_tap_conn *conn,
 			ip4h->check = *ip4_check;
 		else
 			ip4h->check = csum_ip4_header(l3len, IPPROTO_TCP,
-						      *src4, *dst4);
+						      ip4h->ttl, *src4, *dst4);
 
 		if (!no_tcp_csum) {
 			psum = proto_ipv4_header_psum(l4len, IPPROTO_TCP,
@@ -1908,7 +1908,8 @@ static void tcp_rst_no_conn(const struct ctx *c, int af,
 		const struct in6_addr *rst_dst = saddr;
 
 		rsth = tap_push_ip6h(ip6h, rst_src, rst_dst,
-				     sizeof(*rsth), IPPROTO_TCP, flow_lbl);
+				     sizeof(*rsth), IPPROTO_TCP,
+				     DEFAULT_TTL, flow_lbl);
 		psum = proto_ipv6_header_psum(sizeof(*rsth), IPPROTO_TCP,
 					      rst_src, rst_dst);
 	}
diff --git a/udp.c b/udp.c
index f5a5cd1..7cc050c 100644
--- a/udp.c
+++ b/udp.c
@@ -272,7 +272,7 @@ static void udp_iov_init(const struct ctx *c)
  */
 size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp,
 		       const struct flowside *toside, size_t dlen,
-		       bool no_udp_csum)
+		       uint8_t ttl, bool no_udp_csum)
 {
 	const struct in_addr *src = inany_v4(&toside->oaddr);
 	const struct in_addr *dst = inany_v4(&toside->eaddr);
@@ -282,9 +282,10 @@ size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp,
 	ASSERT(src && dst);
 
 	ip4h->tot_len = htons(l3len);
+	ip4h->ttl = ttl;
 	ip4h->daddr = dst->s_addr;
 	ip4h->saddr = src->s_addr;
-	ip4h->check = csum_ip4_header(l3len, IPPROTO_UDP, *src, *dst);
+	ip4h->check = csum_ip4_header(l3len, IPPROTO_UDP, ttl, *src, *dst);
 
 	bp->uh.source = htons(toside->oport);
 	bp->uh.dest = htons(toside->eport);
@@ -316,7 +317,7 @@ size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp,
  */
 size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp,
 		       const struct flowside *toside, size_t dlen,
-		       bool no_udp_csum)
+		       uint8_t hop_limit, bool no_udp_csum)
 {
 	uint16_t l4len = dlen + sizeof(bp->uh);
 
@@ -325,7 +326,7 @@ size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp,
 	ip6h->saddr = toside->oaddr.a6;
 	ip6h->version = 6;
 	ip6h->nexthdr = IPPROTO_UDP;
-	ip6h->hop_limit = 255;
+	ip6h->hop_limit = hop_limit;
 
 	bp->uh.source = htons(toside->oport);
 	bp->uh.dest = htons(toside->eport);
@@ -366,14 +367,16 @@ static void udp_tap_prepare(const struct mmsghdr *mmh,
 
 	if (!inany_v4(&toside->eaddr) || !inany_v4(&toside->oaddr)) {
 		l4len = udp_update_hdr6(&bm->ip6h, bp, toside,
-					mmh[idx].msg_len, no_udp_csum);
+					mmh[idx].msg_len,
+					DEFAULT_TTL, 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_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);
+					mmh[idx].msg_len,
+					DEFAULT_TTL, 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);
@@ -463,7 +466,8 @@ static void udp_send_tap_icmp6(const struct ctx *c,
 		msg.icmp6h.icmp6_dataun.icmp6_un_data32[0] = htonl(ee->ee_info);
 
 	/* Reconstruct the original headers as returned in the ICMP message */
-	tap_push_ip6h(&msg.ip6h, eaddr, oaddr, l4len, IPPROTO_UDP, flow);
+	tap_push_ip6h(&msg.ip6h, eaddr, oaddr, l4len,
+		      IPPROTO_UDP, DEFAULT_TTL, flow);
 	tap_push_uh6(&msg.uh, eaddr, eport, oaddr, oport, in, dlen);
 	memcpy(&msg.data, in, dlen);
 
diff --git a/udp_internal.h b/udp_internal.h
index 96d11cf..2a73779 100644
--- a/udp_internal.h
+++ b/udp_internal.h
@@ -24,10 +24,10 @@ struct udp_payload_t {
 
 size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp,
 		       const struct flowside *toside, size_t dlen,
-		       bool no_udp_csum);
+		       uint8_t ttl, bool no_udp_csum);
 size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp,
                        const struct flowside *toside, size_t dlen,
-		       bool no_udp_csum);
+		       uint8_t hop_limit, bool no_udp_csum);
 void udp_sock_fwd(const struct ctx *c, int s, uint8_t frompif,
 		  in_port_t port, const struct timespec *now);
 
diff --git a/udp_vu.c b/udp_vu.c
index 1f89509..ef2257c 100644
--- a/udp_vu.c
+++ b/udp_vu.c
@@ -152,7 +152,8 @@ static size_t udp_vu_prepare(const struct ctx *c,
 
 		*iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_UDP);
 
-		l4len = udp_update_hdr4(iph, bp, toside, dlen, true);
+		l4len = udp_update_hdr4(iph, bp, toside, dlen,
+					DEFAULT_TTL, true);
 	} else {
 		struct ipv6hdr *ip6h = vu_ip(iov_vu[0].iov_base);
 		struct udp_payload_t *bp = vu_payloadv6(iov_vu[0].iov_base);
@@ -161,7 +162,8 @@ static size_t udp_vu_prepare(const struct ctx *c,
 
 		*ip6h = (struct ipv6hdr)L2_BUF_IP6_INIT(IPPROTO_UDP);
 
-		l4len = udp_update_hdr6(ip6h, bp, toside, dlen, true);
+		l4len = udp_update_hdr6(ip6h, bp, toside, dlen,
+					DEFAULT_TTL, true);
 	}
 
 	return l4len;
-- 
@@ -152,7 +152,8 @@ static size_t udp_vu_prepare(const struct ctx *c,
 
 		*iph = (struct iphdr)L2_BUF_IP4_INIT(IPPROTO_UDP);
 
-		l4len = udp_update_hdr4(iph, bp, toside, dlen, true);
+		l4len = udp_update_hdr4(iph, bp, toside, dlen,
+					DEFAULT_TTL, true);
 	} else {
 		struct ipv6hdr *ip6h = vu_ip(iov_vu[0].iov_base);
 		struct udp_payload_t *bp = vu_payloadv6(iov_vu[0].iov_base);
@@ -161,7 +162,8 @@ static size_t udp_vu_prepare(const struct ctx *c,
 
 		*ip6h = (struct ipv6hdr)L2_BUF_IP6_INIT(IPPROTO_UDP);
 
-		l4len = udp_update_hdr6(ip6h, bp, toside, dlen, true);
+		l4len = udp_update_hdr6(ip6h, bp, toside, dlen,
+					DEFAULT_TTL, true);
 	}
 
 	return l4len;
-- 
2.48.1


  reply	other threads:[~2025-04-24  2:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-24  2:52 [PATCH 0/2] udp: copy ttl or hop limit from socket to tap Jon Maloy
2025-04-24  2:52 ` Jon Maloy [this message]
2025-04-24  2:52 ` [PATCH 2/2] udp: copy incoming packet TTL " Jon Maloy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250424025227.61697-2-jmaloy@redhat.com \
    --to=jmaloy@redhat.com \
    --cc=dgibson@redhat.com \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).