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: Mahesh Bandewar <maheshb@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Maciej Żenczykowski <maze@google.com>
Link: https://lore.kernel.org/r/20230419013238.2691167-1-maheshb@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Mahesh Bandewar 2023-04-18 18:32:38 -07:00 committed by Jakub Kicinski
parent b7b871f5dc
commit 7ab75456be
4 changed files with 22 additions and 2 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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.

View File

@ -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;
}