public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v3 0/2] Add support for seg6 tunsrc
@ 2026-03-16 16:29 Justin Iurman
  2026-03-16 16:29 ` [PATCH net-next v3 1/2] seg6: add per-route tunnel source address Justin Iurman
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Justin Iurman @ 2026-03-16 16:29 UTC (permalink / raw)
  To: netdev
  Cc: andrea.mayer, davem, edumazet, kuba, pabeni, horms, justin.iurman,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels,
	Justin Iurman

This series adds support for the new per-route seg6 "tunsrc" parameter.
Some tests are extended to check for it.

Example:
ip -6 r a 2001:db8:1::/64 encap seg6 mode encap tunsrc 2001:db8:ab::
    segs 2001:db8:42::1,2001:db8:ffff::2 dev eth0


Justin Iurman (2):
  seg6: add per-route tunnel source address
  selftests: add check for seg6 tunsrc

 include/uapi/linux/seg6_iptunnel.h            |   1 +
 net/ipv6/seg6_iptunnel.c                      | 114 +++++++++++++-----
 .../net/srv6_hencap_red_l3vpn_test.sh         |  65 +++++++---
 3 files changed, 134 insertions(+), 46 deletions(-)

---
v3:
 - add selftest for tunsrc
 - tunsrc: forbid loopback and multicast addresses as well

v2: https://lore.kernel.org/netdev/20260311152845.278354-1-justin.iurman@6wind.com/T/#u

v1: https://lore.kernel.org/netdev/CAOY2BqxUswHYoisKjABPunMUC5QJ-B-O9aXu=wKrhTZaqSqedQ@mail.gmail.com/T/

--
2.39.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net-next v3 1/2] seg6: add per-route tunnel source address
  2026-03-16 16:29 [PATCH net-next v3 0/2] Add support for seg6 tunsrc Justin Iurman
@ 2026-03-16 16:29 ` Justin Iurman
  2026-03-16 16:29 ` [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc Justin Iurman
  2026-03-16 20:01 ` [PATCH net-next v3 0/2] Add support " Justin Iurman
  2 siblings, 0 replies; 9+ messages in thread
From: Justin Iurman @ 2026-03-16 16:29 UTC (permalink / raw)
  To: netdev
  Cc: andrea.mayer, davem, edumazet, kuba, pabeni, horms, justin.iurman,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels,
	Justin Iurman, David Ahern

Add SEG6_IPTUNNEL_SRC in the uapi for users to configure a specific
tunnel source address. Make seg6_iptunnel handle the new attribute
correctly. It has priority over the configured per-netns tunnel
source address, if any.

Cc: David Ahern <dsahern@kernel.org>
Signed-off-by: Justin Iurman <justin.iurman@6wind.com>
---
 include/uapi/linux/seg6_iptunnel.h |   1 +
 net/ipv6/seg6_iptunnel.c           | 114 +++++++++++++++++++++--------
 2 files changed, 84 insertions(+), 31 deletions(-)

diff --git a/include/uapi/linux/seg6_iptunnel.h b/include/uapi/linux/seg6_iptunnel.h
index ae78791372b8..485889b19900 100644
--- a/include/uapi/linux/seg6_iptunnel.h
+++ b/include/uapi/linux/seg6_iptunnel.h
@@ -20,6 +20,7 @@
 enum {
 	SEG6_IPTUNNEL_UNSPEC,
 	SEG6_IPTUNNEL_SRH,
+	SEG6_IPTUNNEL_SRC,	/* struct in6_addr */
 	__SEG6_IPTUNNEL_MAX,
 };
 #define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 3e1b9991131a..e76cc0cc481e 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -49,6 +49,7 @@ static size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo)
 
 struct seg6_lwt {
 	struct dst_cache cache;
+	struct in6_addr tunsrc;
 	struct seg6_iptunnel_encap tuninfo[];
 };
 
@@ -65,6 +66,7 @@ seg6_encap_lwtunnel(struct lwtunnel_state *lwt)
 
 static const struct nla_policy seg6_iptunnel_policy[SEG6_IPTUNNEL_MAX + 1] = {
 	[SEG6_IPTUNNEL_SRH]	= { .type = NLA_BINARY },
+	[SEG6_IPTUNNEL_SRC]	= NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
 };
 
 static int nla_put_srh(struct sk_buff *skb, int attrtype,
@@ -87,23 +89,32 @@ static int nla_put_srh(struct sk_buff *skb, int attrtype,
 }
 
 static void set_tun_src(struct net *net, struct net_device *dev,
-			struct in6_addr *daddr, struct in6_addr *saddr)
+			struct in6_addr *daddr, struct in6_addr *saddr,
+			struct in6_addr *route_tunsrc)
 {
 	struct seg6_pernet_data *sdata = seg6_pernet(net);
 	struct in6_addr *tun_src;
 
-	rcu_read_lock();
-
-	tun_src = rcu_dereference(sdata->tun_src);
-
-	if (!ipv6_addr_any(tun_src)) {
-		memcpy(saddr, tun_src, sizeof(struct in6_addr));
+	/* Priority order to select tunnel source address:
+	 *  1. per route source address (if configured)
+	 *  2. per network namespace source address (if configured)
+	 *  3. dynamic resolution
+	 */
+	if (route_tunsrc && !ipv6_addr_any(route_tunsrc)) {
+		memcpy(saddr, route_tunsrc, sizeof(struct in6_addr));
 	} else {
-		ipv6_dev_get_saddr(net, dev, daddr, IPV6_PREFER_SRC_PUBLIC,
-				   saddr);
-	}
+		rcu_read_lock();
+		tun_src = rcu_dereference(sdata->tun_src);
+
+		if (!ipv6_addr_any(tun_src)) {
+			memcpy(saddr, tun_src, sizeof(struct in6_addr));
+		} else {
+			ipv6_dev_get_saddr(net, dev, daddr,
+					   IPV6_PREFER_SRC_PUBLIC, saddr);
+		}
 
-	rcu_read_unlock();
+		rcu_read_unlock();
+	}
 }
 
 /* Compute flowlabel for outer IPv6 header */
@@ -125,7 +136,8 @@ static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb,
 }
 
 static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
-			       int proto, struct dst_entry *cache_dst)
+			       int proto, struct dst_entry *cache_dst,
+			       struct in6_addr *route_tunsrc)
 {
 	struct dst_entry *dst = skb_dst(skb);
 	struct net_device *dev = dst_dev(dst);
@@ -182,7 +194,7 @@ static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
 	isrh->nexthdr = proto;
 
 	hdr->daddr = isrh->segments[isrh->first_segment];
-	set_tun_src(net, dev, &hdr->daddr, &hdr->saddr);
+	set_tun_src(net, dev, &hdr->daddr, &hdr->saddr, route_tunsrc);
 
 #ifdef CONFIG_IPV6_SEG6_HMAC
 	if (sr_has_hmac(isrh)) {
@@ -202,14 +214,15 @@ static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
 /* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
 int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
 {
-	return __seg6_do_srh_encap(skb, osrh, proto, NULL);
+	return __seg6_do_srh_encap(skb, osrh, proto, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(seg6_do_srh_encap);
 
 /* encapsulate an IPv6 packet within an outer IPv6 header with reduced SRH */
 static int seg6_do_srh_encap_red(struct sk_buff *skb,
 				 struct ipv6_sr_hdr *osrh, int proto,
-				 struct dst_entry *cache_dst)
+				 struct dst_entry *cache_dst,
+				 struct in6_addr *route_tunsrc)
 {
 	__u8 first_seg = osrh->first_segment;
 	struct dst_entry *dst = skb_dst(skb);
@@ -272,7 +285,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
 	if (skip_srh) {
 		hdr->nexthdr = proto;
 
-		set_tun_src(net, dev, &hdr->daddr, &hdr->saddr);
+		set_tun_src(net, dev, &hdr->daddr, &hdr->saddr, route_tunsrc);
 		goto out;
 	}
 
@@ -308,7 +321,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
 
 srcaddr:
 	isrh->nexthdr = proto;
-	set_tun_src(net, dev, &hdr->daddr, &hdr->saddr);
+	set_tun_src(net, dev, &hdr->daddr, &hdr->saddr, route_tunsrc);
 
 #ifdef CONFIG_IPV6_SEG6_HMAC
 	if (unlikely(!skip_srh && sr_has_hmac(isrh))) {
@@ -383,9 +396,11 @@ static int seg6_do_srh(struct sk_buff *skb, struct dst_entry *cache_dst)
 {
 	struct dst_entry *dst = skb_dst(skb);
 	struct seg6_iptunnel_encap *tinfo;
+	struct seg6_lwt *slwt;
 	int proto, err = 0;
 
-	tinfo = seg6_encap_lwtunnel(dst->lwtstate);
+	slwt = seg6_lwt_lwtunnel(dst->lwtstate);
+	tinfo = slwt->tuninfo;
 
 	switch (tinfo->mode) {
 	case SEG6_IPTUN_MODE_INLINE:
@@ -410,11 +425,11 @@ static int seg6_do_srh(struct sk_buff *skb, struct dst_entry *cache_dst)
 			return -EINVAL;
 
 		if (tinfo->mode == SEG6_IPTUN_MODE_ENCAP)
-			err = __seg6_do_srh_encap(skb, tinfo->srh,
-						  proto, cache_dst);
+			err = __seg6_do_srh_encap(skb, tinfo->srh, proto,
+						  cache_dst, &slwt->tunsrc);
 		else
-			err = seg6_do_srh_encap_red(skb, tinfo->srh,
-						    proto, cache_dst);
+			err = seg6_do_srh_encap_red(skb, tinfo->srh, proto,
+						    cache_dst, &slwt->tunsrc);
 
 		if (err)
 			return err;
@@ -436,12 +451,12 @@ static int seg6_do_srh(struct sk_buff *skb, struct dst_entry *cache_dst)
 
 		if (tinfo->mode == SEG6_IPTUN_MODE_L2ENCAP)
 			err = __seg6_do_srh_encap(skb, tinfo->srh,
-						  IPPROTO_ETHERNET,
-						  cache_dst);
+						  IPPROTO_ETHERNET, cache_dst,
+						  &slwt->tunsrc);
 		else
 			err = seg6_do_srh_encap_red(skb, tinfo->srh,
-						    IPPROTO_ETHERNET,
-						    cache_dst);
+						    IPPROTO_ETHERNET, cache_dst,
+						    &slwt->tunsrc);
 
 		if (err)
 			return err;
@@ -678,6 +693,10 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
 		if (family != AF_INET6)
 			return -EINVAL;
 
+		if (tb[SEG6_IPTUNNEL_SRC]) {
+			NL_SET_ERR_MSG(extack, "incompatible mode for tunsrc");
+			return -EINVAL;
+		}
 		break;
 	case SEG6_IPTUN_MODE_ENCAP:
 		break;
@@ -702,13 +721,23 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
 	slwt = seg6_lwt_lwtunnel(newts);
 
 	err = dst_cache_init(&slwt->cache, GFP_ATOMIC);
-	if (err) {
-		kfree(newts);
-		return err;
-	}
+	if (err)
+		goto free_lwt_state;
 
 	memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
 
+	if (tb[SEG6_IPTUNNEL_SRC]) {
+		slwt->tunsrc = nla_get_in6_addr(tb[SEG6_IPTUNNEL_SRC]);
+
+		if (ipv6_addr_any(&slwt->tunsrc) ||
+		    ipv6_addr_is_multicast(&slwt->tunsrc) ||
+		    ipv6_addr_loopback(&slwt->tunsrc)) {
+			NL_SET_ERR_MSG(extack, "invalid tunsrc address");
+			err = -EINVAL;
+			goto free_dst_cache;
+		}
+	}
+
 	newts->type = LWTUNNEL_ENCAP_SEG6;
 	newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
 
@@ -720,6 +749,12 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
 	*ts = newts;
 
 	return 0;
+
+free_dst_cache:
+	dst_cache_destroy(&slwt->cache);
+free_lwt_state:
+	kfree(newts);
+	return err;
 }
 
 static void seg6_destroy_state(struct lwtunnel_state *lwt)
@@ -731,29 +766,46 @@ static int seg6_fill_encap_info(struct sk_buff *skb,
 				struct lwtunnel_state *lwtstate)
 {
 	struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate);
+	struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwtstate);
 
 	if (nla_put_srh(skb, SEG6_IPTUNNEL_SRH, tuninfo))
 		return -EMSGSIZE;
 
+	if (!ipv6_addr_any(&slwt->tunsrc) &&
+	    nla_put_in6_addr(skb, SEG6_IPTUNNEL_SRC, &slwt->tunsrc))
+		return -EMSGSIZE;
+
 	return 0;
 }
 
 static int seg6_encap_nlsize(struct lwtunnel_state *lwtstate)
 {
 	struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate);
+	struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwtstate);
+	int nlsize;
+
+	nlsize = nla_total_size(SEG6_IPTUN_ENCAP_SIZE(tuninfo));
 
-	return nla_total_size(SEG6_IPTUN_ENCAP_SIZE(tuninfo));
+	if (!ipv6_addr_any(&slwt->tunsrc))
+		nlsize += nla_total_size(sizeof(slwt->tunsrc));
+
+	return nlsize;
 }
 
 static int seg6_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
 {
 	struct seg6_iptunnel_encap *a_hdr = seg6_encap_lwtunnel(a);
 	struct seg6_iptunnel_encap *b_hdr = seg6_encap_lwtunnel(b);
+	struct seg6_lwt *a_slwt = seg6_lwt_lwtunnel(a);
+	struct seg6_lwt *b_slwt = seg6_lwt_lwtunnel(b);
 	int len = SEG6_IPTUN_ENCAP_SIZE(a_hdr);
 
 	if (len != SEG6_IPTUN_ENCAP_SIZE(b_hdr))
 		return 1;
 
+	if (!ipv6_addr_equal(&a_slwt->tunsrc, &b_slwt->tunsrc))
+		return 1;
+
 	return memcmp(a_hdr, b_hdr, len);
 }
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc
  2026-03-16 16:29 [PATCH net-next v3 0/2] Add support for seg6 tunsrc Justin Iurman
  2026-03-16 16:29 ` [PATCH net-next v3 1/2] seg6: add per-route tunnel source address Justin Iurman
@ 2026-03-16 16:29 ` Justin Iurman
  2026-03-17 10:54   ` Andrea Mayer
  2026-03-16 20:01 ` [PATCH net-next v3 0/2] Add support " Justin Iurman
  2 siblings, 1 reply; 9+ messages in thread
From: Justin Iurman @ 2026-03-16 16:29 UTC (permalink / raw)
  To: netdev
  Cc: andrea.mayer, davem, edumazet, kuba, pabeni, horms, justin.iurman,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels,
	Justin Iurman, Shuah Khan, linux-kselftest

Extend srv6_hencap_red_l3vpn_test.sh to include checks for the new
"tunsrc" feature.

Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Justin Iurman <justin.iurman@6wind.com>
---
 .../net/srv6_hencap_red_l3vpn_test.sh         | 65 ++++++++++++++-----
 1 file changed, 50 insertions(+), 15 deletions(-)

diff --git a/tools/testing/selftests/net/srv6_hencap_red_l3vpn_test.sh b/tools/testing/selftests/net/srv6_hencap_red_l3vpn_test.sh
index 6a68c7eff1dc..bdc485640f79 100755
--- a/tools/testing/selftests/net/srv6_hencap_red_l3vpn_test.sh
+++ b/tools/testing/selftests/net/srv6_hencap_red_l3vpn_test.sh
@@ -345,6 +345,10 @@ setup_rt_networking()
 		ip -netns "${nsname}" addr \
 			add "${net_prefix}::${rt}/64" dev "${devname}" nodad
 
+		ip -netns "${nsname}" addr \
+			add "${net_prefix}::dead:${rt}/64" dev "${devname}" \
+			nodad preferred_lft 0
+
 		ip -netns "${nsname}" link set "${devname}" up
 	done
 
@@ -419,7 +423,8 @@ setup_rt_local_sids()
 #  $4 - SRv6 router configured for removing the SRv6 Policy (router connected
 #       to the destination host)
 #  $5 - encap mode (full or red)
-#  $6 - traffic type (IPv6 or IPv4)
+#  $6 - force tunsrc (true or false)
+#  $7 - traffic type (IPv6 or IPv4)
 __setup_rt_policy()
 {
 	local dst="$1"
@@ -427,11 +432,40 @@ __setup_rt_policy()
 	local end_rts="$3"
 	local dec_rt="$4"
 	local mode="$5"
-	local traffic="$6"
+	local with_tunsrc="$6"
+	local traffic="$7"
 	local nsname
 	local policy=''
+	local tunsrc=''
 	local n
 
+	if [ "$with_tunsrc" = "true" ]; then
+		local net_prefix
+		local drule
+		local nxt
+
+		[ "$end_rts" = "" ] && nxt="${dec_rt}" || nxt="${end_rts%% *}"
+
+		net_prefix="$(get_network_prefix "${encap_rt}" "${nxt}")"
+		tunsrc="tunsrc ${net_prefix}::dead:${encap_rt}"
+
+		eval nsname=\${$(get_rtname "${dec_rt}")}
+
+		drule="PREROUTING \
+		       -d ${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC} \
+		       -j DROP"
+
+		if ! ip netns exec "${nsname}" \
+			ip6tables -t raw -C ${drule} &>/dev/null; then
+			ip netns exec "${nsname}" ip6tables -t raw -A ${drule}
+		fi
+
+		ip netns exec "${nsname}" ip6tables -t raw -I PREROUTING 1 \
+			-s "${net_prefix}::dead:${encap_rt}" \
+			-d ${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC} \
+			-j ACCEPT
+	fi
+
 	eval nsname=\${$(get_rtname "${encap_rt}")}
 
 	for n in ${end_rts}; do
@@ -444,7 +478,7 @@ __setup_rt_policy()
 	if [ "${traffic}" -eq 6 ]; then
 		ip -netns "${nsname}" -6 route \
 			add "${IPv6_HS_NETWORK}::${dst}" vrf "${VRF_DEVNAME}" \
-			encap seg6 mode "${mode}" segs "${policy}" \
+			encap seg6 mode "${mode}" ${tunsrc} segs "${policy}" \
 			dev "${VRF_DEVNAME}"
 
 		ip -netns "${nsname}" -6 neigh \
@@ -455,7 +489,7 @@ __setup_rt_policy()
 		# received, otherwise the proxy arp does not work.
 		ip -netns "${nsname}" -4 route \
 			add "${IPv4_HS_NETWORK}.${dst}" vrf "${VRF_DEVNAME}" \
-			encap seg6 mode "${mode}" segs "${policy}" \
+			encap seg6 mode "${mode}" ${tunsrc} segs "${policy}" \
 			dev "${VRF_DEVNAME}"
 	fi
 }
@@ -463,13 +497,13 @@ __setup_rt_policy()
 # see __setup_rt_policy
 setup_rt_policy_ipv6()
 {
-	__setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6
+	__setup_rt_policy "$1" "$2" "$3" "$4" "$5" "$6" 6
 }
 
 #see __setup_rt_policy
 setup_rt_policy_ipv4()
 {
-	__setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4
+	__setup_rt_policy "$1" "$2" "$3" "$4" "$5" "$6" 4
 }
 
 setup_hs()
@@ -567,41 +601,41 @@ setup()
 	# the network path between hs-1 and hs-2 traverses several routers
 	# depending on the direction of traffic.
 	#
-	# Direction hs-1 -> hs-2 (H.Encaps.Red)
+	# Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
 	#  - rt-3,rt-4 (SRv6 End behaviors)
 	#  - rt-2 (SRv6 End.DT46 behavior)
 	#
 	# Direction hs-2 -> hs-1 (H.Encaps.Red)
 	#  - rt-1 (SRv6 End.DT46 behavior)
-	setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red
-	setup_rt_policy_ipv6 1 2 "" 1 encap.red
+	setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red true
+	setup_rt_policy_ipv6 1 2 "" 1 encap.red false
 
 	# create an IPv4 VPN between hosts hs-1 and hs-2
 	# the network path between hs-1 and hs-2 traverses several routers
 	# depending on the direction of traffic.
 	#
-	# Direction hs-1 -> hs-2 (H.Encaps.Red)
+	# Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
 	# - rt-2 (SRv6 End.DT46 behavior)
 	#
 	# Direction hs-2 -> hs-1 (H.Encaps.Red)
 	#  - rt-4,rt-3 (SRv6 End behaviors)
 	#  - rt-1 (SRv6 End.DT46 behavior)
-	setup_rt_policy_ipv4 2 1 "" 2 encap.red
-	setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red
+	setup_rt_policy_ipv4 2 1 "" 2 encap.red true
+	setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red false
 
 	# create an IPv6 VPN between hosts hs-3 and hs-4
 	# the network path between hs-3 and hs-4 traverses several routers
 	# depending on the direction of traffic.
 	#
-	# Direction hs-3 -> hs-4 (H.Encaps.Red)
+	# Direction hs-3 -> hs-4 (H.Encaps.Red + tunsrc)
 	# - rt-2 (SRv6 End Behavior)
 	# - rt-4 (SRv6 End.DT46 behavior)
 	#
 	# Direction hs-4 -> hs-3 (H.Encaps.Red)
 	#  - rt-1 (SRv6 End behavior)
 	#  - rt-3 (SRv6 End.DT46 behavior)
-	setup_rt_policy_ipv6 4 3 "2" 4 encap.red
-	setup_rt_policy_ipv6 3 4 "1" 3 encap.red
+	setup_rt_policy_ipv6 4 3 "2" 4 encap.red true
+	setup_rt_policy_ipv6 3 4 "1" 3 encap.red false
 
 	# testing environment was set up successfully
 	SETUP_ERR=0
@@ -819,6 +853,7 @@ test_command_or_ksft_skip ip
 test_command_or_ksft_skip ping
 test_command_or_ksft_skip sysctl
 test_command_or_ksft_skip grep
+test_command_or_ksft_skip ip6tables
 
 test_iproute2_supp_or_ksft_skip
 test_vrf_or_ksft_skip
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v3 0/2] Add support for seg6 tunsrc
  2026-03-16 16:29 [PATCH net-next v3 0/2] Add support for seg6 tunsrc Justin Iurman
  2026-03-16 16:29 ` [PATCH net-next v3 1/2] seg6: add per-route tunnel source address Justin Iurman
  2026-03-16 16:29 ` [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc Justin Iurman
@ 2026-03-16 20:01 ` Justin Iurman
  2026-03-17  0:15   ` Jakub Kicinski
  2 siblings, 1 reply; 9+ messages in thread
From: Justin Iurman @ 2026-03-16 20:01 UTC (permalink / raw)
  To: Justin Iurman, netdev
  Cc: andrea.mayer, davem, edumazet, kuba, pabeni, horms,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels

On 3/16/26 17:29, Justin Iurman wrote:
> This series adds support for the new per-route seg6 "tunsrc" parameter.
> Some tests are extended to check for it.
> 
> Example:
> ip -6 r a 2001:db8:1::/64 encap seg6 mode encap tunsrc 2001:db8:ab::
>      segs 2001:db8:42::1,2001:db8:ffff::2 dev eth0
> 
> 
> Justin Iurman (2):
>    seg6: add per-route tunnel source address
>    selftests: add check for seg6 tunsrc
> 
>   include/uapi/linux/seg6_iptunnel.h            |   1 +
>   net/ipv6/seg6_iptunnel.c                      | 114 +++++++++++++-----
>   .../net/srv6_hencap_red_l3vpn_test.sh         |  65 +++++++---
>   3 files changed, 134 insertions(+), 46 deletions(-)

Looks like patchwork considered that this series has been superseded by 
the companion series for iproute2-next :-(

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v3 0/2] Add support for seg6 tunsrc
  2026-03-16 20:01 ` [PATCH net-next v3 0/2] Add support " Justin Iurman
@ 2026-03-17  0:15   ` Jakub Kicinski
  0 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2026-03-17  0:15 UTC (permalink / raw)
  To: Justin Iurman
  Cc: Justin Iurman, netdev, andrea.mayer, davem, edumazet, pabeni,
	horms, nicolas.dichtel, stefano.salsano, paolo.lungaroni,
	ahabdels

On Mon, 16 Mar 2026 21:01:25 +0100 Justin Iurman wrote:
> >   include/uapi/linux/seg6_iptunnel.h            |   1 +
> >   net/ipv6/seg6_iptunnel.c                      | 114 +++++++++++++-----
> >   .../net/srv6_hencap_red_l3vpn_test.sh         |  65 +++++++---
> >   3 files changed, 134 insertions(+), 46 deletions(-)  
> 
> Looks like patchwork considered that this series has been superseded by 
> the companion series for iproute2-next :-(

It's kernel.org's pw-bot not patchwork itself FWIW.
I revived the series. Let's see if the bot discards it again.
If it does you'll have to repost with a different title cause
our CI needs to see it "active" in patchwork to run tests.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc
  2026-03-16 16:29 ` [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc Justin Iurman
@ 2026-03-17 10:54   ` Andrea Mayer
  2026-03-17 22:07     ` Jakub Kicinski
  2026-03-18 12:29     ` Justin Iurman
  0 siblings, 2 replies; 9+ messages in thread
From: Andrea Mayer @ 2026-03-17 10:54 UTC (permalink / raw)
  To: Justin Iurman
  Cc: netdev, davem, edumazet, kuba, pabeni, horms, justin.iurman,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels,
	Shuah Khan, linux-kselftest, Andrea Mayer

On Mon, 16 Mar 2026 17:29:55 +0100
Justin Iurman <justin.iurman@6wind.com> wrote:

> Extend srv6_hencap_red_l3vpn_test.sh to include checks for the new
> "tunsrc" feature.
> 
> Cc: Shuah Khan <shuah@kernel.org>
> Cc: linux-kselftest@vger.kernel.org
> Signed-off-by: Justin Iurman <justin.iurman@6wind.com>
> ---
>  .../net/srv6_hencap_red_l3vpn_test.sh         | 65 ++++++++++++++-----
>  1 file changed, 50 insertions(+), 15 deletions(-)
> 

Hi Justin,
 
Thanks for working on this!
I'll focus on a couple of design aspects for now, and we can look at the
details once we settle on those.

>
> [snip]
>  
>  setup_hs()
> @@ -567,41 +601,41 @@ setup()
>  	# the network path between hs-1 and hs-2 traverses several routers
>  	# depending on the direction of traffic.
>  	#
> -	# Direction hs-1 -> hs-2 (H.Encaps.Red)
> +	# Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
>  	#  - rt-3,rt-4 (SRv6 End behaviors)
>  	#  - rt-2 (SRv6 End.DT46 behavior)
>  	#
>  	# Direction hs-2 -> hs-1 (H.Encaps.Red)
>  	#  - rt-1 (SRv6 End.DT46 behavior)
> -	setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red
> -	setup_rt_policy_ipv6 1 2 "" 1 encap.red
> +	setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red true
> +	setup_rt_policy_ipv6 1 2 "" 1 encap.red false
>  
>  	# create an IPv4 VPN between hosts hs-1 and hs-2
>  	# the network path between hs-1 and hs-2 traverses several routers
>  	# depending on the direction of traffic.
>  	#
> -	# Direction hs-1 -> hs-2 (H.Encaps.Red)
> +	# Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
>  	# - rt-2 (SRv6 End.DT46 behavior)
>  	#
>  	# Direction hs-2 -> hs-1 (H.Encaps.Red)
>  	#  - rt-4,rt-3 (SRv6 End behaviors)
>  	#  - rt-1 (SRv6 End.DT46 behavior)
> -	setup_rt_policy_ipv4 2 1 "" 2 encap.red
> -	setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red
> +	setup_rt_policy_ipv4 2 1 "" 2 encap.red true
> +	setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red false
>  
>  	# create an IPv6 VPN between hosts hs-3 and hs-4
>  	# the network path between hs-3 and hs-4 traverses several routers
>  	# depending on the direction of traffic.
>  	#
> -	# Direction hs-3 -> hs-4 (H.Encaps.Red)
> +	# Direction hs-3 -> hs-4 (H.Encaps.Red + tunsrc)
>  	# - rt-2 (SRv6 End Behavior)
>  	# - rt-4 (SRv6 End.DT46 behavior)
>  	#
>  	# Direction hs-4 -> hs-3 (H.Encaps.Red)
>  	#  - rt-1 (SRv6 End behavior)
>  	#  - rt-3 (SRv6 End.DT46 behavior)
> -	setup_rt_policy_ipv6 4 3 "2" 4 encap.red
> -	setup_rt_policy_ipv6 3 4 "1" 3 encap.red
> +	setup_rt_policy_ipv6 4 3 "2" 4 encap.red true
> +	setup_rt_policy_ipv6 3 4 "1" 3 encap.red false
>  
>  	# testing environment was set up successfully
>  	SETUP_ERR=0


The paths marked "true" here were testing the encap.red baseline before
this change. They need to stay exactly as they were originally.
Furthermore, if tunsrc is not supported by the kernel running the test,
the ip route command with tunsrc will fail during setup() (since
set -e is used), and the entire script dies before any test runs.
 
The idea here is to avoid duplicating the entire test suite, while still
providing dedicated test cases for the new per-route tunsrc. A reasonable
approach could be adding the tunsrc checks as new, separate test cases
that run after the baseline ones, leaving the existing paths completely
untouched.
 
For example, a dedicated test_tunsrc() function could take care of the
whole thing for a given path: setting up the tunsrc address, installing
the route with tunsrc, verifying the behavior, cleaning up, and finally
restoring the original route.

>
> [snip]
> @@ -819,6 +853,7 @@ test_command_or_ksft_skip ip
>  test_command_or_ksft_skip ping
>  test_command_or_ksft_skip sysctl
>  test_command_or_ksft_skip grep
> +test_command_or_ksft_skip ip6tables
>

This will skip the entire script if ip6tables is not present, which
takes down the baseline tests too.
I think a probe at startup that checks for both tunsrc support and
ip6tables would work well here. If either is missing, we can
just gracefully skip the new tunsrc tests and let the rest of the script
run as usual.

The bottom line is that the script needs to keep working exactly as
before when tunsrc is not supported or its dependencies are missing.
 
Thanks,
Andrea

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc
  2026-03-17 10:54   ` Andrea Mayer
@ 2026-03-17 22:07     ` Jakub Kicinski
  2026-03-18 12:29     ` Justin Iurman
  1 sibling, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2026-03-17 22:07 UTC (permalink / raw)
  To: Andrea Mayer
  Cc: Justin Iurman, netdev, davem, edumazet, pabeni, horms,
	justin.iurman, nicolas.dichtel, stefano.salsano, paolo.lungaroni,
	ahabdels, Shuah Khan, linux-kselftest

On Tue, 17 Mar 2026 11:54:30 +0100 Andrea Mayer wrote:
> > @@ -819,6 +853,7 @@ test_command_or_ksft_skip ip
> >  test_command_or_ksft_skip ping
> >  test_command_or_ksft_skip sysctl
> >  test_command_or_ksft_skip grep
> > +test_command_or_ksft_skip ip6tables
> 
> This will skip the entire script if ip6tables is not present, which
> takes down the baseline tests too.
> I think a probe at startup that checks for both tunsrc support and
> ip6tables would work well here. If either is missing, we can
> just gracefully skip the new tunsrc tests and let the rest of the script
> run as usual.
> 
> The bottom line is that the script needs to keep working exactly as
> before when tunsrc is not supported or its dependencies are missing.

FWIW that's not the general guidance for networking tests.
If it's easy to handle cleanly then sure, but we should try to avoid
complicating tests with workarounds for degraded environments.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc
  2026-03-17 10:54   ` Andrea Mayer
  2026-03-17 22:07     ` Jakub Kicinski
@ 2026-03-18 12:29     ` Justin Iurman
  2026-03-19  3:50       ` Andrea Mayer
  1 sibling, 1 reply; 9+ messages in thread
From: Justin Iurman @ 2026-03-18 12:29 UTC (permalink / raw)
  To: Andrea Mayer
  Cc: netdev, davem, edumazet, kuba, pabeni, horms, justin.iurman,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels,
	Shuah Khan, linux-kselftest

On Tue, Mar 17, 2026 at 11:54 AM Andrea Mayer <andrea.mayer@uniroma2.it> wrote:
>
> On Mon, 16 Mar 2026 17:29:55 +0100
> Justin Iurman <justin.iurman@6wind.com> wrote:
>
> > Extend srv6_hencap_red_l3vpn_test.sh to include checks for the new
> > "tunsrc" feature.
> >
> > Cc: Shuah Khan <shuah@kernel.org>
> > Cc: linux-kselftest@vger.kernel.org
> > Signed-off-by: Justin Iurman <justin.iurman@6wind.com>
> > ---
> >  .../net/srv6_hencap_red_l3vpn_test.sh         | 65 ++++++++++++++-----
> >  1 file changed, 50 insertions(+), 15 deletions(-)

[snip]

> > -     # Direction hs-1 -> hs-2 (H.Encaps.Red)
> > +     # Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
> >       # - rt-2 (SRv6 End.DT46 behavior)
> >       #
> >       # Direction hs-2 -> hs-1 (H.Encaps.Red)
> >       #  - rt-4,rt-3 (SRv6 End behaviors)
> >       #  - rt-1 (SRv6 End.DT46 behavior)
> > -     setup_rt_policy_ipv4 2 1 "" 2 encap.red
> > -     setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red
> > +     setup_rt_policy_ipv4 2 1 "" 2 encap.red true
> > +     setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red false
> >
> >       # create an IPv6 VPN between hosts hs-3 and hs-4
> >       # the network path between hs-3 and hs-4 traverses several routers
> >       # depending on the direction of traffic.
> >       #
> > -     # Direction hs-3 -> hs-4 (H.Encaps.Red)
> > +     # Direction hs-3 -> hs-4 (H.Encaps.Red + tunsrc)
> >       # - rt-2 (SRv6 End Behavior)
> >       # - rt-4 (SRv6 End.DT46 behavior)
> >       #
> >       # Direction hs-4 -> hs-3 (H.Encaps.Red)
> >       #  - rt-1 (SRv6 End behavior)
> >       #  - rt-3 (SRv6 End.DT46 behavior)
> > -     setup_rt_policy_ipv6 4 3 "2" 4 encap.red
> > -     setup_rt_policy_ipv6 3 4 "1" 3 encap.red
> > +     setup_rt_policy_ipv6 4 3 "2" 4 encap.red true
> > +     setup_rt_policy_ipv6 3 4 "1" 3 encap.red false
> >
> >       # testing environment was set up successfully
> >       SETUP_ERR=0
>
>
> The paths marked "true" here were testing the encap.red baseline before
> this change. They need to stay exactly as they were originally.
> Furthermore, if tunsrc is not supported by the kernel running the test,
> the ip route command with tunsrc will fail during setup() (since
> set -e is used), and the entire script dies before any test runs.

I kinda disagree here: you're not supposed to run the updated
selftests on an old kernel or with an old iproute2 version (versions
are kept aligned). And I also concur with Jakub about degraded
environments on your last comment below.

> The idea here is to avoid duplicating the entire test suite, while still
> providing dedicated test cases for the new per-route tunsrc. A reasonable
> approach could be adding the tunsrc checks as new, separate test cases
> that run after the baseline ones, leaving the existing paths completely
> untouched.
>
> For example, a dedicated test_tunsrc() function could take care of the
> whole thing for a given path: setting up the tunsrc address, installing
> the route with tunsrc, verifying the behavior, cleaning up, and finally
> restoring the original route.

Well, I actually thought that this approach would be easier, and would
specifically avoid adding too much code or having duplication. FWIW, I
don't think providing dedicated test cases for the new per-route
tunsrc really makes sense, as it's the same behavior as without
"tunsrc". It doesn't impact the encap baseline by itself, since
nothing in the selftests depends on the outer source address. I'm open
to implement what you suggest, though, it's just that I'm not sure
it's the best way forward.

What I suggest as next step: I'll ship patch #1 alone, along with the
iproute2-next companion series, so that we don't miss the merge window
and have the feature in 7.1. In parallel, we keep discussing design
choices for the selftest and ship it as soon as we settle. Would you
agree with that plan?

Cheers,
Justin

> > [snip]
> > @@ -819,6 +853,7 @@ test_command_or_ksft_skip ip
> >  test_command_or_ksft_skip ping
> >  test_command_or_ksft_skip sysctl
> >  test_command_or_ksft_skip grep
> > +test_command_or_ksft_skip ip6tables
> >
>
> This will skip the entire script if ip6tables is not present, which
> takes down the baseline tests too.
> I think a probe at startup that checks for both tunsrc support and
> ip6tables would work well here. If either is missing, we can
> just gracefully skip the new tunsrc tests and let the rest of the script
> run as usual.
>
> The bottom line is that the script needs to keep working exactly as
> before when tunsrc is not supported or its dependencies are missing.
>
> Thanks,
> Andrea

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc
  2026-03-18 12:29     ` Justin Iurman
@ 2026-03-19  3:50       ` Andrea Mayer
  0 siblings, 0 replies; 9+ messages in thread
From: Andrea Mayer @ 2026-03-19  3:50 UTC (permalink / raw)
  To: Justin Iurman
  Cc: netdev, davem, edumazet, kuba, pabeni, horms, justin.iurman,
	nicolas.dichtel, stefano.salsano, paolo.lungaroni, ahabdels,
	Shuah Khan, linux-kselftest, Andrea Mayer

On Wed, 18 Mar 2026 13:29:56 +0100
Justin Iurman <justin.iurman@6wind.com> wrote:

> On Tue, Mar 17, 2026 at 11:54 AM Andrea Mayer <andrea.mayer@uniroma2.it> wrote:
> >
> > On Mon, 16 Mar 2026 17:29:55 +0100
> > Justin Iurman <justin.iurman@6wind.com> wrote:
> >
> > > Extend srv6_hencap_red_l3vpn_test.sh to include checks for the new
> > > "tunsrc" feature.
> > >
> > > Cc: Shuah Khan <shuah@kernel.org>
> > > Cc: linux-kselftest@vger.kernel.org
> > > Signed-off-by: Justin Iurman <justin.iurman@6wind.com>
> > > ---
> > >  .../net/srv6_hencap_red_l3vpn_test.sh         | 65 ++++++++++++++-----
> > >  1 file changed, 50 insertions(+), 15 deletions(-)
> 
> [snip]
> 
> > > -     # Direction hs-1 -> hs-2 (H.Encaps.Red)
> > > +     # Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
> > >       # - rt-2 (SRv6 End.DT46 behavior)
> > >       #
> > >       # Direction hs-2 -> hs-1 (H.Encaps.Red)
> > >       #  - rt-4,rt-3 (SRv6 End behaviors)
> > >       #  - rt-1 (SRv6 End.DT46 behavior)
> > > -     setup_rt_policy_ipv4 2 1 "" 2 encap.red
> > > -     setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red
> > > +     setup_rt_policy_ipv4 2 1 "" 2 encap.red true
> > > +     setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red false
> > >
> > >       # create an IPv6 VPN between hosts hs-3 and hs-4
> > >       # the network path between hs-3 and hs-4 traverses several routers
> > >       # depending on the direction of traffic.
> > >       #
> > > -     # Direction hs-3 -> hs-4 (H.Encaps.Red)
> > > +     # Direction hs-3 -> hs-4 (H.Encaps.Red + tunsrc)
> > >       # - rt-2 (SRv6 End Behavior)
> > >       # - rt-4 (SRv6 End.DT46 behavior)
> > >       #
> > >       # Direction hs-4 -> hs-3 (H.Encaps.Red)
> > >       #  - rt-1 (SRv6 End behavior)
> > >       #  - rt-3 (SRv6 End.DT46 behavior)
> > > -     setup_rt_policy_ipv6 4 3 "2" 4 encap.red
> > > -     setup_rt_policy_ipv6 3 4 "1" 3 encap.red
> > > +     setup_rt_policy_ipv6 4 3 "2" 4 encap.red true
> > > +     setup_rt_policy_ipv6 3 4 "1" 3 encap.red false
> > >
> > >       # testing environment was set up successfully
> > >       SETUP_ERR=0
> >
> >
> > The paths marked "true" here were testing the encap.red baseline before
> > this change. They need to stay exactly as they were originally.
> > Furthermore, if tunsrc is not supported by the kernel running the test,
> > the ip route command with tunsrc will fail during setup() (since
> > set -e is used), and the entire script dies before any test runs.
> 
> I kinda disagree here: you're not supposed to run the updated
> selftests on an old kernel or with an old iproute2 version (versions
> are kept aligned). And I also concur with Jakub about degraded
> environments on your last comment below.
> 
> > The idea here is to avoid duplicating the entire test suite, while still
> > providing dedicated test cases for the new per-route tunsrc. A reasonable
> > approach could be adding the tunsrc checks as new, separate test cases
> > that run after the baseline ones, leaving the existing paths completely
> > untouched.
> >
> > For example, a dedicated test_tunsrc() function could take care of the
> > whole thing for a given path: setting up the tunsrc address, installing
> > the route with tunsrc, verifying the behavior, cleaning up, and finally
> > restoring the original route.
> 
> Well, I actually thought that this approach would be easier, and would
> specifically avoid adding too much code or having duplication. FWIW, I
> don't think providing dedicated test cases for the new per-route
> tunsrc really makes sense, as it's the same behavior as without
> "tunsrc". It doesn't impact the encap baseline by itself, since
> nothing in the selftests depends on the outer source address. I'm open
> to implement what you suggest, though, it's just that I'm not sure
> it's the best way forward.
> 
> What I suggest as next step: I'll ship patch #1 alone, along with the
> iproute2-next companion series, so that we don't miss the merge window
> and have the feature in 7.1. In parallel, we keep discussing design
> choices for the selftest and ship it as soon as we settle. Would you
> agree with that plan?
> 
> Cheers,
> Justin
> 

Hi Justin,

IMHO, the optimal goals should be:
1) have at least a selftest that covers the new feature;
2) re-use *if reasonable* existing selftests;
3) have selftests that run on a reasonable set of kernels and
   environments, without unreasonably increasing their complexity.

I'd prefer to have the selftest shipped together with the feature.
I think we could find a reasonable way to integrate the tunsrc checks
without overcomplicating the existing selftest.
Let me send you an idea offline so we can evaluate it together.

I certainly don't want to hold up the tunsrc feature, it's something
I find very interesting and that I also discussed at netdev 0x19 (2025).

Thanks,
Andrea

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-03-19  3:51 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-16 16:29 [PATCH net-next v3 0/2] Add support for seg6 tunsrc Justin Iurman
2026-03-16 16:29 ` [PATCH net-next v3 1/2] seg6: add per-route tunnel source address Justin Iurman
2026-03-16 16:29 ` [PATCH net-next v3 2/2] selftests: add check for seg6 tunsrc Justin Iurman
2026-03-17 10:54   ` Andrea Mayer
2026-03-17 22:07     ` Jakub Kicinski
2026-03-18 12:29     ` Justin Iurman
2026-03-19  3:50       ` Andrea Mayer
2026-03-16 20:01 ` [PATCH net-next v3 0/2] Add support " Justin Iurman
2026-03-17  0:15   ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox