Commit 5121516b authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv6: lockless IPV6_AUTOFLOWLABEL implementation

Move np->autoflowlabel and np->autoflowlabel_set in inet->inet_flags,
to fix data-races.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6559c0ff
...@@ -253,8 +253,6 @@ struct ipv6_pinfo { ...@@ -253,8 +253,6 @@ struct ipv6_pinfo {
* 100: prefer care-of address * 100: prefer care-of address
*/ */
dontfrag:1, dontfrag:1,
autoflowlabel:1,
autoflowlabel_set:1,
rtalert_isolate:1; rtalert_isolate:1;
__u8 min_hopcount; __u8 min_hopcount;
__u8 tclass; __u8 tclass;
......
...@@ -271,6 +271,8 @@ enum { ...@@ -271,6 +271,8 @@ enum {
INET_FLAGS_MC6_LOOP = 20, INET_FLAGS_MC6_LOOP = 20,
INET_FLAGS_RECVERR6_RFC4884 = 21, INET_FLAGS_RECVERR6_RFC4884 = 21,
INET_FLAGS_MC6_ALL = 22, INET_FLAGS_MC6_ALL = 22,
INET_FLAGS_AUTOFLOWLABEL_SET = 23,
INET_FLAGS_AUTOFLOWLABEL = 24,
}; };
/* cmsg flags for inet */ /* cmsg flags for inet */
......
...@@ -428,7 +428,7 @@ int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, ...@@ -428,7 +428,7 @@ int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq,
int flags); int flags);
int ip6_flowlabel_init(void); int ip6_flowlabel_init(void);
void ip6_flowlabel_cleanup(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) 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) ...@@ -232,12 +232,11 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
} }
EXPORT_SYMBOL(ip6_output); 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); return ip6_default_np_autolabel(net);
else return inet6_test_bit(AUTOFLOWLABEL, sk);
return np->autoflowlabel;
} }
/* /*
...@@ -314,7 +313,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, ...@@ -314,7 +313,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
hlimit = ip6_dst_hoplimit(dst); hlimit = ip6_dst_hoplimit(dst);
ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel, 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->payload_len = htons(seg_len);
hdr->nexthdr = proto; hdr->nexthdr = proto;
...@@ -1938,7 +1937,6 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, ...@@ -1938,7 +1937,6 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
struct sk_buff *skb, *tmp_skb; struct sk_buff *skb, *tmp_skb;
struct sk_buff **tail_skb; struct sk_buff **tail_skb;
struct in6_addr *final_dst; struct in6_addr *final_dst;
struct ipv6_pinfo *np = inet6_sk(sk);
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
struct ipv6_txoptions *opt = v6_cork->opt; struct ipv6_txoptions *opt = v6_cork->opt;
...@@ -1981,7 +1979,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, ...@@ -1981,7 +1979,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
ip6_flow_hdr(hdr, v6_cork->tclass, ip6_flow_hdr(hdr, v6_cork->tclass,
ip6_make_flowlabel(net, skb, fl6->flowlabel, 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->hop_limit = v6_cork->hop_limit;
hdr->nexthdr = proto; hdr->nexthdr = proto;
hdr->saddr = fl6->saddr; hdr->saddr = fl6->saddr;
......
...@@ -474,6 +474,10 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -474,6 +474,10 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
return -EINVAL; return -EINVAL;
inet6_assign_bit(MC6_ALL, sk, valbool); inet6_assign_bit(MC6_ALL, sk, valbool);
return 0; return 0;
case IPV6_AUTOFLOWLABEL:
inet6_assign_bit(AUTOFLOWLABEL, sk, valbool);
inet6_set_bit(AUTOFLOWLABEL_SET, sk);
return 0;
} }
if (needs_rtnl) if (needs_rtnl)
rtnl_lock(); rtnl_lock();
...@@ -970,11 +974,6 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -970,11 +974,6 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
np->dontfrag = valbool; np->dontfrag = valbool;
retv = 0; retv = 0;
break; break;
case IPV6_AUTOFLOWLABEL:
np->autoflowlabel = valbool;
np->autoflowlabel_set = 1;
retv = 0;
break;
case IPV6_RECVFRAGSIZE: case IPV6_RECVFRAGSIZE:
np->rxopt.bits.recvfragsize = valbool; np->rxopt.bits.recvfragsize = valbool;
retv = 0; retv = 0;
...@@ -1447,7 +1446,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname, ...@@ -1447,7 +1446,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
break; break;
case IPV6_AUTOFLOWLABEL: case IPV6_AUTOFLOWLABEL:
val = ip6_autoflowlabel(sock_net(sk), np); val = ip6_autoflowlabel(sock_net(sk), sk);
break; break;
case IPV6_RECVFRAGSIZE: case IPV6_RECVFRAGSIZE:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment