mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
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>
This commit is contained in:
parent
5121516b0c
commit
1086ca7cce
|
@ -252,7 +252,6 @@ struct ipv6_pinfo {
|
|||
* 010: prefer public address
|
||||
* 100: prefer care-of address
|
||||
*/
|
||||
dontfrag:1,
|
||||
rtalert_isolate:1;
|
||||
__u8 min_hopcount;
|
||||
__u8 tclass;
|
||||
|
|
|
@ -273,6 +273,7 @@ enum {
|
|||
INET_FLAGS_MC6_ALL = 22,
|
||||
INET_FLAGS_AUTOFLOWLABEL_SET = 23,
|
||||
INET_FLAGS_AUTOFLOWLABEL = 24,
|
||||
INET_FLAGS_DONTFRAG = 25,
|
||||
};
|
||||
|
||||
/* cmsg flags for inet */
|
||||
|
|
|
@ -373,12 +373,12 @@ static inline void ipcm6_init(struct ipcm6_cookie *ipc6)
|
|||
}
|
||||
|
||||
static inline void ipcm6_init_sk(struct ipcm6_cookie *ipc6,
|
||||
const struct ipv6_pinfo *np)
|
||||
const struct sock *sk)
|
||||
{
|
||||
*ipc6 = (struct ipcm6_cookie) {
|
||||
.hlimit = -1,
|
||||
.tclass = np->tclass,
|
||||
.dontfrag = np->dontfrag,
|
||||
.tclass = inet6_sk(sk)->tclass,
|
||||
.dontfrag = inet6_test_bit(DONTFRAG, sk),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2166,7 +2166,7 @@ static inline bool xfrm6_local_dontfrag(const struct sock *sk)
|
|||
|
||||
proto = sk->sk_protocol;
|
||||
if (proto == IPPROTO_UDP || proto == IPPROTO_RAW)
|
||||
return inet6_sk(sk)->dontfrag;
|
||||
return inet6_test_bit(DONTFRAG, sk);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -588,7 +588,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
|
|||
else if (!fl6.flowi6_oif)
|
||||
fl6.flowi6_oif = np->ucast_oif;
|
||||
|
||||
ipcm6_init_sk(&ipc6, np);
|
||||
ipcm6_init_sk(&ipc6, sk);
|
||||
ipc6.sockc.mark = mark;
|
||||
fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
|
||||
|
||||
|
@ -791,7 +791,7 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb)
|
|||
msg.offset = 0;
|
||||
msg.type = type;
|
||||
|
||||
ipcm6_init_sk(&ipc6, np);
|
||||
ipcm6_init_sk(&ipc6, sk);
|
||||
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
|
||||
ipc6.tclass = ipv6_get_dsfield(ipv6_hdr(skb));
|
||||
ipc6.sockc.mark = mark;
|
||||
|
|
|
@ -2092,7 +2092,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
|||
return ERR_PTR(err);
|
||||
}
|
||||
if (ipc6->dontfrag < 0)
|
||||
ipc6->dontfrag = inet6_sk(sk)->dontfrag;
|
||||
ipc6->dontfrag = inet6_test_bit(DONTFRAG, sk);
|
||||
|
||||
err = __ip6_append_data(sk, &queue, cork, &v6_cork,
|
||||
¤t->task_frag, getfrag, from,
|
||||
|
|
|
@ -478,6 +478,9 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
|||
inet6_assign_bit(AUTOFLOWLABEL, sk, valbool);
|
||||
inet6_set_bit(AUTOFLOWLABEL_SET, sk);
|
||||
return 0;
|
||||
case IPV6_DONTFRAG:
|
||||
inet6_assign_bit(DONTFRAG, sk, valbool);
|
||||
return 0;
|
||||
}
|
||||
if (needs_rtnl)
|
||||
rtnl_lock();
|
||||
|
@ -970,10 +973,6 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
|||
goto e_inval;
|
||||
retv = __ip6_sock_set_addr_preferences(sk, val);
|
||||
break;
|
||||
case IPV6_DONTFRAG:
|
||||
np->dontfrag = valbool;
|
||||
retv = 0;
|
||||
break;
|
||||
case IPV6_RECVFRAGSIZE:
|
||||
np->rxopt.bits.recvfragsize = valbool;
|
||||
retv = 0;
|
||||
|
@ -1442,7 +1441,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
|||
break;
|
||||
|
||||
case IPV6_DONTFRAG:
|
||||
val = np->dontfrag;
|
||||
val = inet6_test_bit(DONTFRAG, sk);
|
||||
break;
|
||||
|
||||
case IPV6_AUTOFLOWLABEL:
|
||||
|
|
|
@ -118,7 +118,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
l3mdev_master_ifindex_by_index(sock_net(sk), oif) != sk->sk_bound_dev_if))
|
||||
return -EINVAL;
|
||||
|
||||
ipcm6_init_sk(&ipc6, np);
|
||||
ipcm6_init_sk(&ipc6, sk);
|
||||
ipc6.sockc.tsflags = READ_ONCE(sk->sk_tsflags);
|
||||
ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
|
||||
|
||||
|
|
|
@ -898,7 +898,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
|
||||
|
||||
if (ipc6.dontfrag < 0)
|
||||
ipc6.dontfrag = np->dontfrag;
|
||||
ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk);
|
||||
|
||||
if (msg->msg_flags&MSG_CONFIRM)
|
||||
goto do_confirm;
|
||||
|
|
|
@ -1595,7 +1595,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
|
||||
do_append_data:
|
||||
if (ipc6.dontfrag < 0)
|
||||
ipc6.dontfrag = np->dontfrag;
|
||||
ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk);
|
||||
up->len += ulen;
|
||||
err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr),
|
||||
&ipc6, fl6, (struct rt6_info *)dst,
|
||||
|
|
|
@ -621,7 +621,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
|
||||
|
||||
if (ipc6.dontfrag < 0)
|
||||
ipc6.dontfrag = np->dontfrag;
|
||||
ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk);
|
||||
|
||||
if (msg->msg_flags & MSG_CONFIRM)
|
||||
goto do_confirm;
|
||||
|
|
Loading…
Reference in a new issue