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>
This commit is contained in:
parent
6559c0ff3b
commit
5121516b0c
@ -253,8 +253,6 @@ struct ipv6_pinfo {
|
||||
* 100: prefer care-of address
|
||||
*/
|
||||
dontfrag:1,
|
||||
autoflowlabel:1,
|
||||
autoflowlabel_set:1,
|
||||
rtalert_isolate:1;
|
||||
__u8 min_hopcount;
|
||||
__u8 tclass;
|
||||
|
@ -271,6 +271,8 @@ enum {
|
||||
INET_FLAGS_MC6_LOOP = 20,
|
||||
INET_FLAGS_RECVERR6_RFC4884 = 21,
|
||||
INET_FLAGS_MC6_ALL = 22,
|
||||
INET_FLAGS_AUTOFLOWLABEL_SET = 23,
|
||||
INET_FLAGS_AUTOFLOWLABEL = 24,
|
||||
};
|
||||
|
||||
/* cmsg flags for inet */
|
||||
|
@ -428,7 +428,7 @@ int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq,
|
||||
int flags);
|
||||
int ip6_flowlabel_init(void);
|
||||
void ip6_flowlabel_cleanup(void);
|
||||
bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np);
|
||||
bool ip6_autoflowlabel(struct net *net, const struct sock *sk);
|
||||
|
||||
static inline void fl6_sock_release(struct ip6_flowlabel *fl)
|
||||
{
|
||||
|
@ -232,12 +232,11 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
EXPORT_SYMBOL(ip6_output);
|
||||
|
||||
bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np)
|
||||
bool ip6_autoflowlabel(struct net *net, const struct sock *sk)
|
||||
{
|
||||
if (!np->autoflowlabel_set)
|
||||
if (!inet6_test_bit(AUTOFLOWLABEL_SET, sk))
|
||||
return ip6_default_np_autolabel(net);
|
||||
else
|
||||
return np->autoflowlabel;
|
||||
return inet6_test_bit(AUTOFLOWLABEL, sk);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -314,7 +313,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
|
||||
hlimit = ip6_dst_hoplimit(dst);
|
||||
|
||||
ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel,
|
||||
ip6_autoflowlabel(net, np), fl6));
|
||||
ip6_autoflowlabel(net, sk), fl6));
|
||||
|
||||
hdr->payload_len = htons(seg_len);
|
||||
hdr->nexthdr = proto;
|
||||
@ -1938,7 +1937,6 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||
struct sk_buff *skb, *tmp_skb;
|
||||
struct sk_buff **tail_skb;
|
||||
struct in6_addr *final_dst;
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct net *net = sock_net(sk);
|
||||
struct ipv6hdr *hdr;
|
||||
struct ipv6_txoptions *opt = v6_cork->opt;
|
||||
@ -1981,7 +1979,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||
|
||||
ip6_flow_hdr(hdr, v6_cork->tclass,
|
||||
ip6_make_flowlabel(net, skb, fl6->flowlabel,
|
||||
ip6_autoflowlabel(net, np), fl6));
|
||||
ip6_autoflowlabel(net, sk), fl6));
|
||||
hdr->hop_limit = v6_cork->hop_limit;
|
||||
hdr->nexthdr = proto;
|
||||
hdr->saddr = fl6->saddr;
|
||||
|
@ -474,6 +474,10 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
return -EINVAL;
|
||||
inet6_assign_bit(MC6_ALL, sk, valbool);
|
||||
return 0;
|
||||
case IPV6_AUTOFLOWLABEL:
|
||||
inet6_assign_bit(AUTOFLOWLABEL, sk, valbool);
|
||||
inet6_set_bit(AUTOFLOWLABEL_SET, sk);
|
||||
return 0;
|
||||
}
|
||||
if (needs_rtnl)
|
||||
rtnl_lock();
|
||||
@ -970,11 +974,6 @@ done:
|
||||
np->dontfrag = valbool;
|
||||
retv = 0;
|
||||
break;
|
||||
case IPV6_AUTOFLOWLABEL:
|
||||
np->autoflowlabel = valbool;
|
||||
np->autoflowlabel_set = 1;
|
||||
retv = 0;
|
||||
break;
|
||||
case IPV6_RECVFRAGSIZE:
|
||||
np->rxopt.bits.recvfragsize = valbool;
|
||||
retv = 0;
|
||||
@ -1447,7 +1446,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
break;
|
||||
|
||||
case IPV6_AUTOFLOWLABEL:
|
||||
val = ip6_autoflowlabel(sock_net(sk), np);
|
||||
val = ip6_autoflowlabel(sock_net(sk), sk);
|
||||
break;
|
||||
|
||||
case IPV6_RECVFRAGSIZE:
|
||||
|
Loading…
Reference in New Issue
Block a user