Commit 7ab75456 authored by Mahesh Bandewar's avatar Mahesh Bandewar Committed by Jakub Kicinski
Browse files

ipv6: add icmpv6_error_anycast_as_unicast for ICMPv6



ICMPv6 error packets are not sent to the anycast destinations and this
prevents things like traceroute from working. So create a setting similar
to ECHO when dealing with Anycast sources (icmpv6_echo_ignore_anycast).

Signed-off-by: default avatarMahesh Bandewar <maheshb@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Reviewed-by: default avatarMaciej Żenczykowski <maze@google.com>
Link: https://lore.kernel.org/r/20230419013238.2691167-1-maheshb@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b7b871f5
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2721,6 +2721,13 @@ echo_ignore_anycast - BOOLEAN

	Default: 0

error_anycast_as_unicast - BOOLEAN
	If set to 1, then the kernel will respond with ICMP Errors
	resulting from requests sent to it over the IPv6 protocol destined
	to anycast address essentially treating anycast as unicast.

	Default: 0

xfrm6_gc_thresh - INTEGER
	(Obsolete since linux-4.14)
	The threshold at which we will start garbage collecting for IPv6
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct netns_sysctl_ipv6 {
	u64 ioam6_id_wide;
	bool skip_notify_on_dev_down;
	u8 fib_notify_on_flag_change;
	u8 icmpv6_error_anycast_as_unicast;
};

struct netns_ipv6 {
+1 −0
Original line number Diff line number Diff line
@@ -952,6 +952,7 @@ static int __net_init inet6_net_init(struct net *net)
	net->ipv6.sysctl.icmpv6_echo_ignore_all = 0;
	net->ipv6.sysctl.icmpv6_echo_ignore_multicast = 0;
	net->ipv6.sysctl.icmpv6_echo_ignore_anycast = 0;
	net->ipv6.sysctl.icmpv6_error_anycast_as_unicast = 0;

	/* By default, rate limit error messages.
	 * Except for pmtu discovery, it would break it.
+13 −2
Original line number Diff line number Diff line
@@ -362,9 +362,10 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net,

	/*
	 * We won't send icmp if the destination is known
	 * anycast.
	 * anycast unless we need to treat anycast as unicast.
	 */
	if (ipv6_anycast_destination(dst, &fl6->daddr)) {
	if (!READ_ONCE(net->ipv6.sysctl.icmpv6_error_anycast_as_unicast) &&
	    ipv6_anycast_destination(dst, &fl6->daddr)) {
		net_dbg_ratelimited("icmp6_send: acast source\n");
		dst_release(dst);
		return ERR_PTR(-EINVAL);
@@ -1195,6 +1196,15 @@ static struct ctl_table ipv6_icmp_table_template[] = {
		.mode		= 0644,
		.proc_handler = proc_do_large_bitmap,
	},
	{
		.procname	= "error_anycast_as_unicast",
		.data		= &init_net.ipv6.sysctl.icmpv6_error_anycast_as_unicast,
		.maxlen		= sizeof(u8),
		.mode		= 0644,
		.proc_handler	= proc_dou8vec_minmax,
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
	},
	{ },
};

@@ -1212,6 +1222,7 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
		table[2].data = &net->ipv6.sysctl.icmpv6_echo_ignore_multicast;
		table[3].data = &net->ipv6.sysctl.icmpv6_echo_ignore_anycast;
		table[4].data = &net->ipv6.sysctl.icmpv6_ratemask_ptr;
		table[5].data = &net->ipv6.sysctl.icmpv6_error_anycast_as_unicast;
	}
	return table;
}