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

ipv6: icmp: allow flowlabel reflection in echo replies

Extend flowlabel_reflect bitmask to allow conditional
reflection of incoming flowlabels in echo replies.

Note this has precedence against auto flowlabels.

Add flowlabel_reflect enum to replace hard coded
values.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
a346abe0 954a5a02

+17 -5
+3 -1
Documentation/networking/ip-sysctl.txt
··· 1452 1452 environments. See RFC 7690 and: 1453 1453 https://tools.ietf.org/html/draft-wang-6man-flow-label-reflection-01 1454 1454 1455 - This is a mask of two bits. 1455 + This is a bitmask. 1456 1456 1: enabled for established flows 1457 1457 1458 1458 Note that this prevents automatic flowlabel changes, as done ··· 1462 1462 2: enabled for TCP RESET packets (no active listener) 1463 1463 If set, a RST packet sent in response to a SYN packet on a closed 1464 1464 port will reflect the incoming flow label. 1465 + 1466 + 4: enabled for ICMPv6 echo reply messages. 1465 1467 1466 1468 Default: 0 1467 1469
+7
include/net/ipv6.h
··· 301 301 /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ 302 302 }; 303 303 304 + /* flowlabel_reflect sysctl values */ 305 + enum flowlabel_reflect { 306 + FLOWLABEL_REFLECT_ESTABLISHED = 1, 307 + FLOWLABEL_REFLECT_TCP_RESET = 2, 308 + FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES = 4, 309 + }; 310 + 304 311 struct ip6_flowlabel { 305 312 struct ip6_flowlabel __rcu *next; 306 313 __be32 label;
+1 -1
net/ipv6/af_inet6.c
··· 208 208 np->mc_loop = 1; 209 209 np->mc_all = 1; 210 210 np->pmtudisc = IPV6_PMTUDISC_WANT; 211 - np->repflow = net->ipv6.sysctl.flowlabel_reflect & 1; 211 + np->repflow = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED; 212 212 sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; 213 213 214 214 /* Init the ipv4 part of the socket since we can have sockets
+3
net/ipv6/icmp.c
··· 703 703 tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; 704 704 705 705 memset(&fl6, 0, sizeof(fl6)); 706 + if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES) 707 + fl6.flowlabel = ip6_flowlabel(ipv6_hdr(skb)); 708 + 706 709 fl6.flowi6_proto = IPPROTO_ICMPV6; 707 710 fl6.daddr = ipv6_hdr(skb)->saddr; 708 711 if (saddr)
+2 -2
net/ipv6/sysctl_net_ipv6.c
··· 23 23 24 24 static int zero; 25 25 static int one = 1; 26 - static int three = 3; 26 + static int flowlabel_reflect_max = 0x7; 27 27 static int auto_flowlabels_min; 28 28 static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX; 29 29 ··· 116 116 .mode = 0644, 117 117 .proc_handler = proc_dointvec, 118 118 .extra1 = &zero, 119 - .extra2 = &three, 119 + .extra2 = &flowlabel_reflect_max, 120 120 }, 121 121 { 122 122 .procname = "max_dst_opts_number",
+1 -1
net/ipv6/tcp_ipv6.c
··· 989 989 if (sk->sk_state == TCP_TIME_WAIT) 990 990 label = cpu_to_be32(inet_twsk(sk)->tw_flowlabel); 991 991 } else { 992 - if (net->ipv6.sysctl.flowlabel_reflect & 2) 992 + if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_TCP_RESET) 993 993 label = ip6_flowlabel(ipv6h); 994 994 } 995 995