Commit b34441e3 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'seg6-allow-end-x-behavior-to-accept-an-oif'

Ido Schimmel says:

====================
seg6: Allow End.X behavior to accept an oif

Patches #1-#3 gradually extend the End.X behavior to accept an output
interface as an optional argument. This is needed for cases where user
space wishes to specify an IPv6 link-local address as the nexthop
address.

Patch #4 adds test cases to the existing End.X selftest to cover the new
functionality.
====================

Link: https://patch.msgid.link/20250612122323.584113-1-idosch@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0550890b 04d752d6
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ static void advance_nextseg(struct ipv6_sr_hdr *srh, struct in6_addr *daddr)

static int
seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
			u32 tbl_id, bool local_delivery)
			u32 tbl_id, bool local_delivery, int oif)
{
	struct net *net = dev_net(skb->dev);
	struct ipv6hdr *hdr = ipv6_hdr(skb);
@@ -282,6 +282,7 @@ seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,

	memset(&fl6, 0, sizeof(fl6));
	fl6.flowi6_iif = skb->dev->ifindex;
	fl6.flowi6_oif = oif;
	fl6.daddr = nhaddr ? *nhaddr : hdr->daddr;
	fl6.saddr = hdr->saddr;
	fl6.flowlabel = ip6_flowinfo(hdr);
@@ -291,17 +292,19 @@ seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
	if (nhaddr)
		fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;

	if (!tbl_id) {
	if (!tbl_id && !oif) {
		dst = ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags);
	} else {
	} else if (tbl_id) {
		struct fib6_table *table;

		table = fib6_get_table(net, tbl_id);
		if (!table)
			goto out;

		rt = ip6_pol_route(net, table, 0, &fl6, skb, flags);
		rt = ip6_pol_route(net, table, oif, &fl6, skb, flags);
		dst = &rt->dst;
	} else {
		dst = ip6_route_output(net, NULL, &fl6);
	}

	/* we want to discard traffic destined for local packet processing,
@@ -330,7 +333,7 @@ seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
int seg6_lookup_nexthop(struct sk_buff *skb,
			struct in6_addr *nhaddr, u32 tbl_id)
{
	return seg6_lookup_any_nexthop(skb, nhaddr, tbl_id, false);
	return seg6_lookup_any_nexthop(skb, nhaddr, tbl_id, false, 0);
}

static __u8 seg6_flv_lcblock_octects(const struct seg6_flavors_info *finfo)
@@ -418,7 +421,7 @@ static int end_next_csid_core(struct sk_buff *skb, struct seg6_local_lwt *slwt)
static int input_action_end_x_finish(struct sk_buff *skb,
				     struct seg6_local_lwt *slwt)
{
	seg6_lookup_nexthop(skb, &slwt->nh6, 0);
	seg6_lookup_any_nexthop(skb, &slwt->nh6, 0, false, slwt->oif);

	return dst_input(skb);
}
@@ -1277,7 +1280,7 @@ static int input_action_end_dt6(struct sk_buff *skb,
	/* note: this time we do not need to specify the table because the VRF
	 * takes care of selecting the correct table.
	 */
	seg6_lookup_any_nexthop(skb, NULL, 0, true);
	seg6_lookup_any_nexthop(skb, NULL, 0, true, 0);

	return dst_input(skb);

@@ -1285,7 +1288,7 @@ static int input_action_end_dt6(struct sk_buff *skb,
#endif
	skb_set_transport_header(skb, sizeof(struct ipv6hdr));

	seg6_lookup_any_nexthop(skb, NULL, slwt->table, true);
	seg6_lookup_any_nexthop(skb, NULL, slwt->table, true, 0);

	return dst_input(skb);

@@ -1477,7 +1480,8 @@ static struct seg6_action_desc seg6_action_table[] = {
		.action		= SEG6_LOCAL_ACTION_END_X,
		.attrs		= SEG6_F_ATTR(SEG6_LOCAL_NH6),
		.optattrs	= SEG6_F_LOCAL_COUNTERS |
				  SEG6_F_LOCAL_FLAVORS,
				  SEG6_F_LOCAL_FLAVORS |
				  SEG6_F_ATTR(SEG6_LOCAL_OIF),
		.input		= input_action_end_x,
	},
	{
+48 −0
Original line number Diff line number Diff line
@@ -72,6 +72,9 @@
# Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y in
# the selftest network.
#
# In addition, every router interface connecting rt-x to rt-y is assigned an
# IPv6 link-local address fe80::x:y/64.
#
# Local SID/C-SID table
# =====================
#
@@ -521,6 +524,9 @@ setup_rt_networking()
		ip -netns "${nsname}" addr \
			add "${net_prefix}::${rt}/64" dev "${devname}" nodad

		ip -netns "${nsname}" addr \
			add "fe80::${rt}:${neigh}/64" dev "${devname}" nodad

		ip -netns "${nsname}" link set "${devname}" up
	done

@@ -609,6 +615,27 @@ set_end_x_nextcsid()
		nflen "${LCNODEFUNC_BLEN}" dev "${DUMMY_DEVNAME}"
}

set_end_x_ll_nextcsid()
{
	local rt="$1"
	local adj="$2"

	eval nsname=\${$(get_rtname "${rt}")}
	lcnode_func_prefix="$(build_lcnode_func_prefix "${rt}")"
	nh6_ll_addr="fe80::${adj}:${rt}"
	oifname="veth-rt-${rt}-${adj}"

	# enabled NEXT-C-SID SRv6 End.X behavior via an IPv6 link-local nexthop
	# address (note that "dev" is the dummy dum0 device chosen for the sake
	# of simplicity).
	ip -netns "${nsname}" -6 route \
		replace "${lcnode_func_prefix}" \
		table "${LOCALSID_TABLE_ID}" \
		encap seg6local action End.X nh6 "${nh6_ll_addr}" \
		oif "${oifname}" flavors next-csid lblen "${LCBLOCK_BLEN}" \
		nflen "${LCNODEFUNC_BLEN}" dev "${DUMMY_DEVNAME}"
}

set_underlay_sids_reachability()
{
	local rt="$1"
@@ -1016,6 +1043,27 @@ host_vpn_tests()

	check_and_log_hs_ipv4_connectivity 1 2
	check_and_log_hs_ipv4_connectivity 2 1

	# Setup the adjacencies in the SRv6 aware routers using IPv6 link-local
	# addresses.
	# - rt-3 SRv6 End.X adjacency with rt-4
	# - rt-4 SRv6 End.X adjacency with rt-1
	set_end_x_ll_nextcsid 3 4
	set_end_x_ll_nextcsid 4 1

	log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv6), link-local"

	check_and_log_hs_ipv6_connectivity 1 2
	check_and_log_hs_ipv6_connectivity 2 1

	log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4), link-local"

	check_and_log_hs_ipv4_connectivity 1 2
	check_and_log_hs_ipv4_connectivity 2 1

	# Restore the previous adjacencies.
	set_end_x_nextcsid 3 4
	set_end_x_nextcsid 4 1
}

__nextcsid_end_x_behavior_test()