Skip to content

Commit 76c231b

Browse files
committed
Merge branch 'icmp-add-rfc-5837-support'
Ido Schimmel says: ==================== icmp: Add RFC 5837 support tl;dr ===== This patchset extends certain ICMP error messages (e.g., "Time Exceeded") with incoming interface information in accordance with RFC 5837 [1]. This is required for more meaningful traceroute results in unnumbered networks. Like other ICMP settings, the feature is controlled via a per-{netns, address family} sysctl. The interface and the implementation are designed to support more ICMP extensions. Motivation ========== Over the years, the kernel was extended with the ability to derive the source IP of ICMP error messages from the interface that received the datagram which elicited the ICMP error [2][3][4]. This is especially important for "Time Exceeded" messages as it allows traceroute users to trace the actual packet path along the network. The above scheme does not work in unnumbered networks. In these networks, only the loopback / VRF interface is assigned a global IP address while router interfaces are assigned IPv6 link-local addresses. As such, ICMP error messages are generated with a source IP derived from the loopback / VRF interface, making it impossible to trace the actual packet path when parallel links exist between routers. The problem can be solved by implementing the solution proposed by RFC 4884 [5] and RFC 5837. The former defines an ICMP extension structure that can be appended to selected ICMP messages and carry extension objects. The latter defines an extension object called the "Interface Information Object" (IIO) that can carry interface information (e.g., name, index, MTU) about interfaces with certain roles such as the interface that received the datagram which elicited the ICMP error. The payload of the datagram that elicited the error (potentially padded / trimmed) along with the ICMP extension structure will be queued to the error queue of the originating socket, thereby allowing traceroute applications to parse and display the information encoded in the ICMP extension structure. Example: # traceroute6 -e 2001:db8:1::3 traceroute to 2001:db8:1::3 (2001:db8:1::3), 30 hops max, 80 byte packets 1 2001:db8:1::2 (2001:db8:1::2) <INC:11,"eth1",mtu=1500> 0.214 ms 0.171 ms 0.162 ms 2 2001:db8:1::3 (2001:db8:1::3) <INC:12,"eth2",mtu=1500> 0.154 ms 0.135 ms 0.127 ms # traceroute -e 192.0.2.3 traceroute to 192.0.2.3 (192.0.2.3), 30 hops max, 60 byte packets 1 192.0.2.2 (192.0.2.2) <INC:11,"eth1",mtu=1500> 0.191 ms 0.148 ms 0.144 ms 2 192.0.2.3 (192.0.2.3) <INC:12,"eth2",mtu=1500> 0.137 ms 0.122 ms 0.114 ms Implementation ============== As previously stated, the feature is controlled via a per-{netns, address} sysctl. Specifically, a bit mask where each bit controls the addition of a different ICMP extension to ICMP error messages. Currently, only a single value is supported, to append the incoming interface information. Key points: 1. Global knob vs finer control. I am not aware of users who require finer control, but it is possible that some users will want to avoid appending ICMP extensions when the packet is sent out of a specific interface (e.g., the management interface) or to a specific subnet. This can be accomplished via a tc-bpf program that trims the ICMP extension structure. An example program can be found here [6]. 2. Split implementation between IPv4 / IPv6. While the implementation is currently similar, there are some differences between both address families. In addition, some extensions (e.g., RFC 8883 [7]) are IPv6-specific. Given the above and given that the implementation is not very complex, it makes sense to keep both implementations separate. 3. Compatibility with legacy applications. RFC 4884 from 2007 extended certain ICMP messages with a length field that encodes the length of the "original datagram" field, so that applications will be able to tell where the "original datagram" ends and where the ICMP extension structure starts. Before the introduction of the IP{,6}_RECVERR_RFC4884 socket options [8][9] in 2020 it was impossible for applications to know where the ICMP extension structure starts and to this day some applications assume that it starts at offset 128, which is the minimum length of the "original datagram" field as specified by RFC 4884. Therefore, in order to be compatible with both legacy and modern applications, the datagram that elicited the ICMP error is trimmed / padded to 128 bytes before appending the ICMP extension structure. This behavior is specifically called out by RFC 4884: "Those wishing to be backward compatible with non-compliant TRACEROUTE implementations will include exactly 128 octets" [10]. Note that in 128 bytes we should be able to include enough headers for the originating node to match the ICMP error message with the relevant socket. For example, the following headers will be present in the "original datagram" field when a VXLAN encapsulated IPv6 packet elicits an ICMP error in an IPv6 underlay: IPv6 (40) | UDP (8) | VXLAN (8) | Eth (14) | IPv6 (40) | UDP (8). Overall, 118 bytes. If the 128 bytes limit proves to be insufficient for some use case, we can consider dedicating a new bit in the previously mentioned sysctl to allow for more bytes to be included in the "original datagram" field. 4. Extensibility. This patchset adds partial support for a single ICMP extension. However, the interface and the implementation should be able to support more extensions, if needed. Examples: * More interface information objects as part of RFC 5837. We should be able to derive the outgoing interface information and nexthop IP from the dst entry attached to the packet that elicited the error. * Node identification object (e.g., hostname / loopback IP) [11]. * Extended Information object which encodes aggregate header limits as part of RFC 8883. A previous proposal from Ishaan Gandhi and Ron Bonica is available here [12]. Testing ======= The existing traceroute selftest is extended to test that ICMP extensions are reported correctly when enabled. Both address families are tested and with different packet sizes in order to make sure that trimming / padding works correctly. Tested that packets are parsed correctly by the IP{,6}_RECVERR_RFC4884 socket options using Willem's selftest [13]. Changelog ========= Changes since v1 [14]: * Patches #1-#2: Added a comment about field ordering and review tags. * Patch #3: Converted "sysctl" to "echo" when testing the return value. Added a check to skip the test if traceroute version is older than 2.1.5. [1] https://datatracker.ietf.org/doc/html/rfc5837 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1c2fb7f93cb20621772bf304f3dba0849942e5db [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fac6fce9bdb59837bb89930c3a92f5e0d1482f0b [4] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4a8c416602d97a4e2073ed563d4d4c7627de19cf [5] https://datatracker.ietf.org/doc/html/rfc4884 [6] https://gist.github.com/idosch/5013448cdb5e9e060e6bfdc8b433577c [7] https://datatracker.ietf.org/doc/html/rfc8883 [8] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eba75c587e811d3249c8bd50d22bb2266ccd3c0f [9] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=01370434df85eb76ecb1527a4466013c4aca2436 [10] https://datatracker.ietf.org/doc/html/rfc4884#section-5.3 [11] https://datatracker.ietf.org/doc/html/draft-ietf-intarea-extended-icmp-nodeid-04 [12] https://lore.kernel.org/netdev/[email protected]/ [13] https://lore.kernel.org/netdev/aPpMItF35gwpgzZx@shredder/ [14] https://lore.kernel.org/netdev/[email protected]/ ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents b8a7826 + 02da595 commit 76c231b

File tree

10 files changed

+796
-3
lines changed

10 files changed

+796
-3
lines changed

Documentation/networking/ip-sysctl.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,23 @@ icmp_errors_use_inbound_ifaddr - BOOLEAN
17961796

17971797
Default: 0 (disabled)
17981798

1799+
icmp_errors_extension_mask - UNSIGNED INTEGER
1800+
Bitmask of ICMP extensions to append to ICMPv4 error messages
1801+
("Destination Unreachable", "Time Exceeded" and "Parameter Problem").
1802+
The original datagram is trimmed / padded to 128 bytes in order to be
1803+
compatible with applications that do not comply with RFC 4884.
1804+
1805+
Possible extensions are:
1806+
1807+
==== ==============================================================
1808+
0x01 Incoming IP interface information according to RFC 5837.
1809+
Extension will include the index, IPv4 address (if present),
1810+
name and MTU of the IP interface that received the datagram
1811+
which elicited the ICMP error.
1812+
==== ==============================================================
1813+
1814+
Default: 0x00 (no extensions)
1815+
17991816
igmp_max_memberships - INTEGER
18001817
Change the maximum number of multicast groups we can subscribe to.
18011818
Default: 20
@@ -3262,6 +3279,23 @@ error_anycast_as_unicast - BOOLEAN
32623279

32633280
Default: 0 (disabled)
32643281

3282+
errors_extension_mask - UNSIGNED INTEGER
3283+
Bitmask of ICMP extensions to append to ICMPv6 error messages
3284+
("Destination Unreachable" and "Time Exceeded"). The original datagram
3285+
is trimmed / padded to 128 bytes in order to be compatible with
3286+
applications that do not comply with RFC 4884.
3287+
3288+
Possible extensions are:
3289+
3290+
==== ==============================================================
3291+
0x01 Incoming IP interface information according to RFC 5837.
3292+
Extension will include the index, IPv6 address (if present),
3293+
name and MTU of the IP interface that received the datagram
3294+
which elicited the ICMP error.
3295+
==== ==============================================================
3296+
3297+
Default: 0x00 (no extensions)
3298+
32653299
xfrm6_gc_thresh - INTEGER
32663300
(Obsolete since linux-4.14)
32673301
The threshold at which we will start garbage collecting for IPv6

include/linux/icmp.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,36 @@ void ip_icmp_error_rfc4884(const struct sk_buff *skb,
4040
struct sock_ee_data_rfc4884 *out,
4141
int thlen, int off);
4242

43+
/* RFC 4884 */
44+
#define ICMP_EXT_ORIG_DGRAM_MIN_LEN 128
45+
#define ICMP_EXT_VERSION_2 2
46+
47+
/* ICMP Extension Object Classes */
48+
#define ICMP_EXT_OBJ_CLASS_IIO 2 /* RFC 5837 */
49+
50+
/* Interface Information Object - RFC 5837 */
51+
enum {
52+
ICMP_EXT_CTYPE_IIO_ROLE_IIF,
53+
};
54+
55+
#define ICMP_EXT_CTYPE_IIO_ROLE(ROLE) ((ROLE) << 6)
56+
#define ICMP_EXT_CTYPE_IIO_MTU BIT(0)
57+
#define ICMP_EXT_CTYPE_IIO_NAME BIT(1)
58+
#define ICMP_EXT_CTYPE_IIO_IPADDR BIT(2)
59+
#define ICMP_EXT_CTYPE_IIO_IFINDEX BIT(3)
60+
61+
struct icmp_ext_iio_name_subobj {
62+
u8 len;
63+
char name[IFNAMSIZ];
64+
};
65+
66+
enum {
67+
/* RFC 5837 - Incoming IP Interface Role */
68+
ICMP_ERR_EXT_IIO_IIF,
69+
/* Add new constants above. Used by "icmp_errors_extension_mask"
70+
* sysctl.
71+
*/
72+
ICMP_ERR_EXT_COUNT,
73+
};
74+
4375
#endif /* _LINUX_ICMP_H */

include/net/netns/ipv4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct netns_ipv4 {
135135
u8 sysctl_icmp_echo_ignore_broadcasts;
136136
u8 sysctl_icmp_ignore_bogus_error_responses;
137137
u8 sysctl_icmp_errors_use_inbound_ifaddr;
138+
u8 sysctl_icmp_errors_extension_mask;
138139
int sysctl_icmp_ratelimit;
139140
int sysctl_icmp_ratemask;
140141
int sysctl_icmp_msgs_per_sec;

include/net/netns/ipv6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct netns_sysctl_ipv6 {
5656
u8 skip_notify_on_dev_down;
5757
u8 fib_notify_on_flag_change;
5858
u8 icmpv6_error_anycast_as_unicast;
59+
u8 icmpv6_errors_extension_mask;
5960
};
6061

6162
struct netns_ipv6 {

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,7 @@ void netdev_copy_name(struct net_device *dev, char *name)
11631163
strscpy(name, dev->name, IFNAMSIZ);
11641164
} while (read_seqretry(&netdev_rename_lock, seq));
11651165
}
1166+
EXPORT_IPV6_MOD_GPL(netdev_copy_name);
11661167

11671168
/**
11681169
* netdev_get_name - get a netdevice name, knowing its ifindex.

net/ipv4/icmp.c

Lines changed: 190 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,185 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
582582
return ERR_PTR(err);
583583
}
584584

585+
struct icmp_ext_iio_addr4_subobj {
586+
__be16 afi;
587+
__be16 reserved;
588+
__be32 addr4;
589+
};
590+
591+
static unsigned int icmp_ext_iio_len(void)
592+
{
593+
return sizeof(struct icmp_extobj_hdr) +
594+
/* ifIndex */
595+
sizeof(__be32) +
596+
/* Interface Address Sub-Object */
597+
sizeof(struct icmp_ext_iio_addr4_subobj) +
598+
/* Interface Name Sub-Object. Length must be a multiple of 4
599+
* bytes.
600+
*/
601+
ALIGN(sizeof(struct icmp_ext_iio_name_subobj), 4) +
602+
/* MTU */
603+
sizeof(__be32);
604+
}
605+
606+
static unsigned int icmp_ext_max_len(u8 ext_objs)
607+
{
608+
unsigned int ext_max_len;
609+
610+
ext_max_len = sizeof(struct icmp_ext_hdr);
611+
612+
if (ext_objs & BIT(ICMP_ERR_EXT_IIO_IIF))
613+
ext_max_len += icmp_ext_iio_len();
614+
615+
return ext_max_len;
616+
}
617+
618+
static __be32 icmp_ext_iio_addr4_find(const struct net_device *dev)
619+
{
620+
struct in_device *in_dev;
621+
struct in_ifaddr *ifa;
622+
623+
in_dev = __in_dev_get_rcu(dev);
624+
if (!in_dev)
625+
return 0;
626+
627+
/* It is unclear from RFC 5837 which IP address should be chosen, but
628+
* it makes sense to choose a global unicast address.
629+
*/
630+
in_dev_for_each_ifa_rcu(ifa, in_dev) {
631+
if (READ_ONCE(ifa->ifa_flags) & IFA_F_SECONDARY)
632+
continue;
633+
if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
634+
ipv4_is_multicast(ifa->ifa_address))
635+
continue;
636+
return ifa->ifa_address;
637+
}
638+
639+
return 0;
640+
}
641+
642+
static void icmp_ext_iio_iif_append(struct net *net, struct sk_buff *skb,
643+
int iif)
644+
{
645+
struct icmp_ext_iio_name_subobj *name_subobj;
646+
struct icmp_extobj_hdr *objh;
647+
struct net_device *dev;
648+
__be32 data;
649+
650+
if (!iif)
651+
return;
652+
653+
/* Add the fields in the order specified by RFC 5837. */
654+
objh = skb_put(skb, sizeof(*objh));
655+
objh->class_num = ICMP_EXT_OBJ_CLASS_IIO;
656+
objh->class_type = ICMP_EXT_CTYPE_IIO_ROLE(ICMP_EXT_CTYPE_IIO_ROLE_IIF);
657+
658+
data = htonl(iif);
659+
skb_put_data(skb, &data, sizeof(__be32));
660+
objh->class_type |= ICMP_EXT_CTYPE_IIO_IFINDEX;
661+
662+
rcu_read_lock();
663+
664+
dev = dev_get_by_index_rcu(net, iif);
665+
if (!dev)
666+
goto out;
667+
668+
data = icmp_ext_iio_addr4_find(dev);
669+
if (data) {
670+
struct icmp_ext_iio_addr4_subobj *addr4_subobj;
671+
672+
addr4_subobj = skb_put_zero(skb, sizeof(*addr4_subobj));
673+
addr4_subobj->afi = htons(ICMP_AFI_IP);
674+
addr4_subobj->addr4 = data;
675+
objh->class_type |= ICMP_EXT_CTYPE_IIO_IPADDR;
676+
}
677+
678+
name_subobj = skb_put_zero(skb, ALIGN(sizeof(*name_subobj), 4));
679+
name_subobj->len = ALIGN(sizeof(*name_subobj), 4);
680+
netdev_copy_name(dev, name_subobj->name);
681+
objh->class_type |= ICMP_EXT_CTYPE_IIO_NAME;
682+
683+
data = htonl(READ_ONCE(dev->mtu));
684+
skb_put_data(skb, &data, sizeof(__be32));
685+
objh->class_type |= ICMP_EXT_CTYPE_IIO_MTU;
686+
687+
out:
688+
rcu_read_unlock();
689+
objh->length = htons(skb_tail_pointer(skb) - (unsigned char *)objh);
690+
}
691+
692+
static void icmp_ext_objs_append(struct net *net, struct sk_buff *skb,
693+
u8 ext_objs, int iif)
694+
{
695+
if (ext_objs & BIT(ICMP_ERR_EXT_IIO_IIF))
696+
icmp_ext_iio_iif_append(net, skb, iif);
697+
}
698+
699+
static struct sk_buff *
700+
icmp_ext_append(struct net *net, struct sk_buff *skb_in, struct icmphdr *icmph,
701+
unsigned int room, int iif)
702+
{
703+
unsigned int payload_len, ext_max_len, ext_len;
704+
struct icmp_ext_hdr *ext_hdr;
705+
struct sk_buff *skb;
706+
u8 ext_objs;
707+
int nhoff;
708+
709+
switch (icmph->type) {
710+
case ICMP_DEST_UNREACH:
711+
case ICMP_TIME_EXCEEDED:
712+
case ICMP_PARAMETERPROB:
713+
break;
714+
default:
715+
return NULL;
716+
}
717+
718+
ext_objs = READ_ONCE(net->ipv4.sysctl_icmp_errors_extension_mask);
719+
if (!ext_objs)
720+
return NULL;
721+
722+
ext_max_len = icmp_ext_max_len(ext_objs);
723+
if (ICMP_EXT_ORIG_DGRAM_MIN_LEN + ext_max_len > room)
724+
return NULL;
725+
726+
skb = skb_clone(skb_in, GFP_ATOMIC);
727+
if (!skb)
728+
return NULL;
729+
730+
nhoff = skb_network_offset(skb);
731+
payload_len = min(skb->len - nhoff, ICMP_EXT_ORIG_DGRAM_MIN_LEN);
732+
733+
if (!pskb_network_may_pull(skb, payload_len))
734+
goto free_skb;
735+
736+
if (pskb_trim(skb, nhoff + ICMP_EXT_ORIG_DGRAM_MIN_LEN) ||
737+
__skb_put_padto(skb, nhoff + ICMP_EXT_ORIG_DGRAM_MIN_LEN, false))
738+
goto free_skb;
739+
740+
if (pskb_expand_head(skb, 0, ext_max_len, GFP_ATOMIC))
741+
goto free_skb;
742+
743+
ext_hdr = skb_put_zero(skb, sizeof(*ext_hdr));
744+
ext_hdr->version = ICMP_EXT_VERSION_2;
745+
746+
icmp_ext_objs_append(net, skb, ext_objs, iif);
747+
748+
/* Do not send an empty extension structure. */
749+
ext_len = skb_tail_pointer(skb) - (unsigned char *)ext_hdr;
750+
if (ext_len == sizeof(*ext_hdr))
751+
goto free_skb;
752+
753+
ext_hdr->checksum = ip_compute_csum(ext_hdr, ext_len);
754+
/* The length of the original datagram in 32-bit words (RFC 4884). */
755+
icmph->un.reserved[1] = ICMP_EXT_ORIG_DGRAM_MIN_LEN / sizeof(u32);
756+
757+
return skb;
758+
759+
free_skb:
760+
consume_skb(skb);
761+
return NULL;
762+
}
763+
585764
/*
586765
* Send an ICMP message in response to a situation
587766
*
@@ -601,6 +780,7 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
601780
struct icmp_bxm icmp_param;
602781
struct rtable *rt = skb_rtable(skb_in);
603782
bool apply_ratelimit = false;
783+
struct sk_buff *ext_skb;
604784
struct ipcm_cookie ipc;
605785
struct flowi4 fl4;
606786
__be32 saddr;
@@ -770,7 +950,12 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
770950
if (room <= (int)sizeof(struct iphdr))
771951
goto ende;
772952

773-
icmp_param.data_len = skb_in->len - icmp_param.offset;
953+
ext_skb = icmp_ext_append(net, skb_in, &icmp_param.data.icmph, room,
954+
parm->iif);
955+
if (ext_skb)
956+
icmp_param.skb = ext_skb;
957+
958+
icmp_param.data_len = icmp_param.skb->len - icmp_param.offset;
774959
if (icmp_param.data_len > room)
775960
icmp_param.data_len = room;
776961
icmp_param.head_len = sizeof(struct icmphdr);
@@ -785,6 +970,9 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
785970
trace_icmp_send(skb_in, type, code);
786971

787972
icmp_push_reply(sk, &icmp_param, &fl4, &ipc, &rt);
973+
974+
if (ext_skb)
975+
consume_skb(ext_skb);
788976
ende:
789977
ip_rt_put(rt);
790978
out_unlock:
@@ -1502,6 +1690,7 @@ static int __net_init icmp_sk_init(struct net *net)
15021690
net->ipv4.sysctl_icmp_ratelimit = 1 * HZ;
15031691
net->ipv4.sysctl_icmp_ratemask = 0x1818;
15041692
net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0;
1693+
net->ipv4.sysctl_icmp_errors_extension_mask = 0;
15051694
net->ipv4.sysctl_icmp_msgs_per_sec = 1000;
15061695
net->ipv4.sysctl_icmp_msgs_burst = 50;
15071696

net/ipv4/sysctl_net_ipv4.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ static int tcp_plb_max_rounds = 31;
4848
static int tcp_plb_max_cong_thresh = 256;
4949
static unsigned int tcp_tw_reuse_delay_max = TCP_PAWS_MSL * MSEC_PER_SEC;
5050
static int tcp_ecn_mode_max = 2;
51+
static u32 icmp_errors_extension_mask_all =
52+
GENMASK_U8(ICMP_ERR_EXT_COUNT - 1, 0);
5153

5254
/* obsolete */
5355
static int sysctl_tcp_low_latency __read_mostly;
@@ -674,6 +676,15 @@ static struct ctl_table ipv4_net_table[] = {
674676
.extra1 = SYSCTL_ZERO,
675677
.extra2 = SYSCTL_ONE
676678
},
679+
{
680+
.procname = "icmp_errors_extension_mask",
681+
.data = &init_net.ipv4.sysctl_icmp_errors_extension_mask,
682+
.maxlen = sizeof(u8),
683+
.mode = 0644,
684+
.proc_handler = proc_dou8vec_minmax,
685+
.extra1 = SYSCTL_ZERO,
686+
.extra2 = &icmp_errors_extension_mask_all,
687+
},
677688
{
678689
.procname = "icmp_ratelimit",
679690
.data = &init_net.ipv4.sysctl_icmp_ratelimit,

net/ipv6/af_inet6.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ static int __net_init inet6_net_init(struct net *net)
960960
net->ipv6.sysctl.icmpv6_echo_ignore_multicast = 0;
961961
net->ipv6.sysctl.icmpv6_echo_ignore_anycast = 0;
962962
net->ipv6.sysctl.icmpv6_error_anycast_as_unicast = 0;
963+
net->ipv6.sysctl.icmpv6_errors_extension_mask = 0;
963964

964965
/* By default, rate limit error messages.
965966
* Except for pmtu discovery, it would break it.

0 commit comments

Comments
 (0)