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

ipv6: lockless IPV6_DONTFRAG implementation

Move np->dontfrag flag to 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
1086ca7c 5121516b

+16 -17
-1
include/linux/ipv6.h
··· 252 252 * 010: prefer public address 253 253 * 100: prefer care-of address 254 254 */ 255 - dontfrag:1, 256 255 rtalert_isolate:1; 257 256 __u8 min_hopcount; 258 257 __u8 tclass;
+1
include/net/inet_sock.h
··· 273 273 INET_FLAGS_MC6_ALL = 22, 274 274 INET_FLAGS_AUTOFLOWLABEL_SET = 23, 275 275 INET_FLAGS_AUTOFLOWLABEL = 24, 276 + INET_FLAGS_DONTFRAG = 25, 276 277 }; 277 278 278 279 /* cmsg flags for inet */
+3 -3
include/net/ipv6.h
··· 373 373 } 374 374 375 375 static inline void ipcm6_init_sk(struct ipcm6_cookie *ipc6, 376 - const struct ipv6_pinfo *np) 376 + const struct sock *sk) 377 377 { 378 378 *ipc6 = (struct ipcm6_cookie) { 379 379 .hlimit = -1, 380 - .tclass = np->tclass, 381 - .dontfrag = np->dontfrag, 380 + .tclass = inet6_sk(sk)->tclass, 381 + .dontfrag = inet6_test_bit(DONTFRAG, sk), 382 382 }; 383 383 } 384 384
+1 -1
include/net/xfrm.h
··· 2166 2166 2167 2167 proto = sk->sk_protocol; 2168 2168 if (proto == IPPROTO_UDP || proto == IPPROTO_RAW) 2169 - return inet6_sk(sk)->dontfrag; 2169 + return inet6_test_bit(DONTFRAG, sk); 2170 2170 2171 2171 return false; 2172 2172 }
+2 -2
net/ipv6/icmp.c
··· 588 588 else if (!fl6.flowi6_oif) 589 589 fl6.flowi6_oif = np->ucast_oif; 590 590 591 - ipcm6_init_sk(&ipc6, np); 591 + ipcm6_init_sk(&ipc6, sk); 592 592 ipc6.sockc.mark = mark; 593 593 fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel); 594 594 ··· 791 791 msg.offset = 0; 792 792 msg.type = type; 793 793 794 - ipcm6_init_sk(&ipc6, np); 794 + ipcm6_init_sk(&ipc6, sk); 795 795 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 796 796 ipc6.tclass = ipv6_get_dsfield(ipv6_hdr(skb)); 797 797 ipc6.sockc.mark = mark;
+1 -1
net/ipv6/ip6_output.c
··· 2092 2092 return ERR_PTR(err); 2093 2093 } 2094 2094 if (ipc6->dontfrag < 0) 2095 - ipc6->dontfrag = inet6_sk(sk)->dontfrag; 2095 + ipc6->dontfrag = inet6_test_bit(DONTFRAG, sk); 2096 2096 2097 2097 err = __ip6_append_data(sk, &queue, cork, &v6_cork, 2098 2098 &current->task_frag, getfrag, from,
+4 -5
net/ipv6/ipv6_sockglue.c
··· 478 478 inet6_assign_bit(AUTOFLOWLABEL, sk, valbool); 479 479 inet6_set_bit(AUTOFLOWLABEL_SET, sk); 480 480 return 0; 481 + case IPV6_DONTFRAG: 482 + inet6_assign_bit(DONTFRAG, sk, valbool); 483 + return 0; 481 484 } 482 485 if (needs_rtnl) 483 486 rtnl_lock(); ··· 973 970 goto e_inval; 974 971 retv = __ip6_sock_set_addr_preferences(sk, val); 975 972 break; 976 - case IPV6_DONTFRAG: 977 - np->dontfrag = valbool; 978 - retv = 0; 979 - break; 980 973 case IPV6_RECVFRAGSIZE: 981 974 np->rxopt.bits.recvfragsize = valbool; 982 975 retv = 0; ··· 1441 1442 break; 1442 1443 1443 1444 case IPV6_DONTFRAG: 1444 - val = np->dontfrag; 1445 + val = inet6_test_bit(DONTFRAG, sk); 1445 1446 break; 1446 1447 1447 1448 case IPV6_AUTOFLOWLABEL:
+1 -1
net/ipv6/ping.c
··· 118 118 l3mdev_master_ifindex_by_index(sock_net(sk), oif) != sk->sk_bound_dev_if)) 119 119 return -EINVAL; 120 120 121 - ipcm6_init_sk(&ipc6, np); 121 + ipcm6_init_sk(&ipc6, sk); 122 122 ipc6.sockc.tsflags = READ_ONCE(sk->sk_tsflags); 123 123 ipc6.sockc.mark = READ_ONCE(sk->sk_mark); 124 124
+1 -1
net/ipv6/raw.c
··· 898 898 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 899 899 900 900 if (ipc6.dontfrag < 0) 901 - ipc6.dontfrag = np->dontfrag; 901 + ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk); 902 902 903 903 if (msg->msg_flags&MSG_CONFIRM) 904 904 goto do_confirm;
+1 -1
net/ipv6/udp.c
··· 1595 1595 1596 1596 do_append_data: 1597 1597 if (ipc6.dontfrag < 0) 1598 - ipc6.dontfrag = np->dontfrag; 1598 + ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk); 1599 1599 up->len += ulen; 1600 1600 err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr), 1601 1601 &ipc6, fl6, (struct rt6_info *)dst,
+1 -1
net/l2tp/l2tp_ip6.c
··· 621 621 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 622 622 623 623 if (ipc6.dontfrag < 0) 624 - ipc6.dontfrag = np->dontfrag; 624 + ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk); 625 625 626 626 if (msg->msg_flags & MSG_CONFIRM) 627 627 goto do_confirm;