Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mahesh Bandewar and committed by
Jakub Kicinski
7ab75456 b7b871f5

+22 -2
+7
Documentation/networking/ip-sysctl.rst
··· 2721 2721 2722 2722 Default: 0 2723 2723 2724 + error_anycast_as_unicast - BOOLEAN 2725 + If set to 1, then the kernel will respond with ICMP Errors 2726 + resulting from requests sent to it over the IPv6 protocol destined 2727 + to anycast address essentially treating anycast as unicast. 2728 + 2729 + Default: 0 2730 + 2724 2731 xfrm6_gc_thresh - INTEGER 2725 2732 (Obsolete since linux-4.14) 2726 2733 The threshold at which we will start garbage collecting for IPv6
+1
include/net/netns/ipv6.h
··· 55 55 u64 ioam6_id_wide; 56 56 bool skip_notify_on_dev_down; 57 57 u8 fib_notify_on_flag_change; 58 + u8 icmpv6_error_anycast_as_unicast; 58 59 }; 59 60 60 61 struct netns_ipv6 {
+1
net/ipv6/af_inet6.c
··· 952 952 net->ipv6.sysctl.icmpv6_echo_ignore_all = 0; 953 953 net->ipv6.sysctl.icmpv6_echo_ignore_multicast = 0; 954 954 net->ipv6.sysctl.icmpv6_echo_ignore_anycast = 0; 955 + net->ipv6.sysctl.icmpv6_error_anycast_as_unicast = 0; 955 956 956 957 /* By default, rate limit error messages. 957 958 * Except for pmtu discovery, it would break it.
+13 -2
net/ipv6/icmp.c
··· 362 362 363 363 /* 364 364 * We won't send icmp if the destination is known 365 - * anycast. 365 + * anycast unless we need to treat anycast as unicast. 366 366 */ 367 - if (ipv6_anycast_destination(dst, &fl6->daddr)) { 367 + if (!READ_ONCE(net->ipv6.sysctl.icmpv6_error_anycast_as_unicast) && 368 + ipv6_anycast_destination(dst, &fl6->daddr)) { 368 369 net_dbg_ratelimited("icmp6_send: acast source\n"); 369 370 dst_release(dst); 370 371 return ERR_PTR(-EINVAL); ··· 1196 1195 .mode = 0644, 1197 1196 .proc_handler = proc_do_large_bitmap, 1198 1197 }, 1198 + { 1199 + .procname = "error_anycast_as_unicast", 1200 + .data = &init_net.ipv6.sysctl.icmpv6_error_anycast_as_unicast, 1201 + .maxlen = sizeof(u8), 1202 + .mode = 0644, 1203 + .proc_handler = proc_dou8vec_minmax, 1204 + .extra1 = SYSCTL_ZERO, 1205 + .extra2 = SYSCTL_ONE, 1206 + }, 1199 1207 { }, 1200 1208 }; 1201 1209 ··· 1222 1212 table[2].data = &net->ipv6.sysctl.icmpv6_echo_ignore_multicast; 1223 1213 table[3].data = &net->ipv6.sysctl.icmpv6_echo_ignore_anycast; 1224 1214 table[4].data = &net->ipv6.sysctl.icmpv6_ratemask_ptr; 1215 + table[5].data = &net->ipv6.sysctl.icmpv6_error_anycast_as_unicast; 1225 1216 } 1226 1217 return table; 1227 1218 }