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

ipv6: lockless IPV6_AUTOFLOWLABEL implementation

Move np->autoflowlabel and np->autoflowlabel_set in inet->inet_flags,
to fix data-races.

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

authored by

Eric Dumazet and committed by
David S. Miller
5121516b 6559c0ff

+13 -16
-2
include/linux/ipv6.h
··· 253 253 * 100: prefer care-of address 254 254 */ 255 255 dontfrag:1, 256 - autoflowlabel:1, 257 - autoflowlabel_set:1, 258 256 rtalert_isolate:1; 259 257 __u8 min_hopcount; 260 258 __u8 tclass;
+2
include/net/inet_sock.h
··· 271 271 INET_FLAGS_MC6_LOOP = 20, 272 272 INET_FLAGS_RECVERR6_RFC4884 = 21, 273 273 INET_FLAGS_MC6_ALL = 22, 274 + INET_FLAGS_AUTOFLOWLABEL_SET = 23, 275 + INET_FLAGS_AUTOFLOWLABEL = 24, 274 276 }; 275 277 276 278 /* cmsg flags for inet */
+1 -1
include/net/ipv6.h
··· 428 428 int flags); 429 429 int ip6_flowlabel_init(void); 430 430 void ip6_flowlabel_cleanup(void); 431 - bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np); 431 + bool ip6_autoflowlabel(struct net *net, const struct sock *sk); 432 432 433 433 static inline void fl6_sock_release(struct ip6_flowlabel *fl) 434 434 {
+5 -7
net/ipv6/ip6_output.c
··· 232 232 } 233 233 EXPORT_SYMBOL(ip6_output); 234 234 235 - bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np) 235 + bool ip6_autoflowlabel(struct net *net, const struct sock *sk) 236 236 { 237 - if (!np->autoflowlabel_set) 237 + if (!inet6_test_bit(AUTOFLOWLABEL_SET, sk)) 238 238 return ip6_default_np_autolabel(net); 239 - else 240 - return np->autoflowlabel; 239 + return inet6_test_bit(AUTOFLOWLABEL, sk); 241 240 } 242 241 243 242 /* ··· 313 314 hlimit = ip6_dst_hoplimit(dst); 314 315 315 316 ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel, 316 - ip6_autoflowlabel(net, np), fl6)); 317 + ip6_autoflowlabel(net, sk), fl6)); 317 318 318 319 hdr->payload_len = htons(seg_len); 319 320 hdr->nexthdr = proto; ··· 1937 1938 struct sk_buff *skb, *tmp_skb; 1938 1939 struct sk_buff **tail_skb; 1939 1940 struct in6_addr *final_dst; 1940 - struct ipv6_pinfo *np = inet6_sk(sk); 1941 1941 struct net *net = sock_net(sk); 1942 1942 struct ipv6hdr *hdr; 1943 1943 struct ipv6_txoptions *opt = v6_cork->opt; ··· 1979 1981 1980 1982 ip6_flow_hdr(hdr, v6_cork->tclass, 1981 1983 ip6_make_flowlabel(net, skb, fl6->flowlabel, 1982 - ip6_autoflowlabel(net, np), fl6)); 1984 + ip6_autoflowlabel(net, sk), fl6)); 1983 1985 hdr->hop_limit = v6_cork->hop_limit; 1984 1986 hdr->nexthdr = proto; 1985 1987 hdr->saddr = fl6->saddr;
+5 -6
net/ipv6/ipv6_sockglue.c
··· 474 474 return -EINVAL; 475 475 inet6_assign_bit(MC6_ALL, sk, valbool); 476 476 return 0; 477 + case IPV6_AUTOFLOWLABEL: 478 + inet6_assign_bit(AUTOFLOWLABEL, sk, valbool); 479 + inet6_set_bit(AUTOFLOWLABEL_SET, sk); 480 + return 0; 477 481 } 478 482 if (needs_rtnl) 479 483 rtnl_lock(); ··· 974 970 np->dontfrag = valbool; 975 971 retv = 0; 976 972 break; 977 - case IPV6_AUTOFLOWLABEL: 978 - np->autoflowlabel = valbool; 979 - np->autoflowlabel_set = 1; 980 - retv = 0; 981 - break; 982 973 case IPV6_RECVFRAGSIZE: 983 974 np->rxopt.bits.recvfragsize = valbool; 984 975 retv = 0; ··· 1446 1447 break; 1447 1448 1448 1449 case IPV6_AUTOFLOWLABEL: 1449 - val = ip6_autoflowlabel(sock_net(sk), np); 1450 + val = ip6_autoflowlabel(sock_net(sk), sk); 1450 1451 break; 1451 1452 1452 1453 case IPV6_RECVFRAGSIZE: