mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-17 10:26:09 +00:00
neighbour: annotate lockless accesses to n->nud_state
We have many lockless accesses to n->nud_state. Before adding another one in the following patch, add annotations to readers and writers. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Reviewed-by: Martin KaFai Lau <martin.lau@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
68a84a127b
commit
b071af5235
@ -1863,7 +1863,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|||||||
struct vxlan_fdb *f;
|
struct vxlan_fdb *f;
|
||||||
struct sk_buff *reply;
|
struct sk_buff *reply;
|
||||||
|
|
||||||
if (!(n->nud_state & NUD_CONNECTED)) {
|
if (!(READ_ONCE(n->nud_state) & NUD_CONNECTED)) {
|
||||||
neigh_release(n);
|
neigh_release(n);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2027,7 +2027,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|||||||
struct vxlan_fdb *f;
|
struct vxlan_fdb *f;
|
||||||
struct sk_buff *reply;
|
struct sk_buff *reply;
|
||||||
|
|
||||||
if (!(n->nud_state & NUD_CONNECTED)) {
|
if (!(READ_ONCE(n->nud_state) & NUD_CONNECTED)) {
|
||||||
neigh_release(n);
|
neigh_release(n);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ static __always_inline int neigh_event_send_probe(struct neighbour *neigh,
|
|||||||
|
|
||||||
if (READ_ONCE(neigh->used) != now)
|
if (READ_ONCE(neigh->used) != now)
|
||||||
WRITE_ONCE(neigh->used, now);
|
WRITE_ONCE(neigh->used, now);
|
||||||
if (!(neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE)))
|
if (!(READ_ONCE(neigh->nud_state) & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE)))
|
||||||
return __neigh_event_send(neigh, skb, immediate_ok);
|
return __neigh_event_send(neigh, skb, immediate_ok);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
|
|||||||
if (n) {
|
if (n) {
|
||||||
struct net_bridge_fdb_entry *f;
|
struct net_bridge_fdb_entry *f;
|
||||||
|
|
||||||
if (!(n->nud_state & NUD_VALID)) {
|
if (!(READ_ONCE(n->nud_state) & NUD_VALID)) {
|
||||||
neigh_release(n);
|
neigh_release(n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -452,7 +452,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
|
|||||||
if (n) {
|
if (n) {
|
||||||
struct net_bridge_fdb_entry *f;
|
struct net_bridge_fdb_entry *f;
|
||||||
|
|
||||||
if (!(n->nud_state & NUD_VALID)) {
|
if (!(READ_ONCE(n->nud_state) & NUD_VALID)) {
|
||||||
neigh_release(n);
|
neigh_release(n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,8 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
|
|||||||
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
|
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) {
|
if ((READ_ONCE(neigh->nud_state) & NUD_CONNECTED) &&
|
||||||
|
READ_ONCE(neigh->hh.hh_len)) {
|
||||||
neigh_hh_bridge(&neigh->hh, skb);
|
neigh_hh_bridge(&neigh->hh, skb);
|
||||||
skb->dev = nf_bridge->physindev;
|
skb->dev = nf_bridge->physindev;
|
||||||
ret = br_handle_frame_finish(net, sk, skb);
|
ret = br_handle_frame_finish(net, sk, skb);
|
||||||
|
@ -5871,7 +5871,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
|
|||||||
else
|
else
|
||||||
neigh = __ipv6_neigh_lookup_noref_stub(dev, params->ipv6_dst);
|
neigh = __ipv6_neigh_lookup_noref_stub(dev, params->ipv6_dst);
|
||||||
|
|
||||||
if (!neigh || !(neigh->nud_state & NUD_VALID))
|
if (!neigh || !(READ_ONCE(neigh->nud_state) & NUD_VALID))
|
||||||
return BPF_FIB_LKUP_RET_NO_NEIGH;
|
return BPF_FIB_LKUP_RET_NO_NEIGH;
|
||||||
memcpy(params->dmac, neigh->ha, ETH_ALEN);
|
memcpy(params->dmac, neigh->ha, ETH_ALEN);
|
||||||
memcpy(params->smac, dev->dev_addr, ETH_ALEN);
|
memcpy(params->smac, dev->dev_addr, ETH_ALEN);
|
||||||
@ -5992,7 +5992,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
|
|||||||
* not needed here.
|
* not needed here.
|
||||||
*/
|
*/
|
||||||
neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
|
neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
|
||||||
if (!neigh || !(neigh->nud_state & NUD_VALID))
|
if (!neigh || !(READ_ONCE(neigh->nud_state) & NUD_VALID))
|
||||||
return BPF_FIB_LKUP_RET_NO_NEIGH;
|
return BPF_FIB_LKUP_RET_NO_NEIGH;
|
||||||
memcpy(params->dmac, neigh->ha, ETH_ALEN);
|
memcpy(params->dmac, neigh->ha, ETH_ALEN);
|
||||||
memcpy(params->smac, dev->dev_addr, ETH_ALEN);
|
memcpy(params->smac, dev->dev_addr, ETH_ALEN);
|
||||||
|
@ -1093,13 +1093,13 @@ static void neigh_timer_handler(struct timer_list *t)
|
|||||||
neigh->used +
|
neigh->used +
|
||||||
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
|
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
|
||||||
neigh_dbg(2, "neigh %p is delayed\n", neigh);
|
neigh_dbg(2, "neigh %p is delayed\n", neigh);
|
||||||
neigh->nud_state = NUD_DELAY;
|
WRITE_ONCE(neigh->nud_state, NUD_DELAY);
|
||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
neigh_suspect(neigh);
|
neigh_suspect(neigh);
|
||||||
next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
|
next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
|
||||||
} else {
|
} else {
|
||||||
neigh_dbg(2, "neigh %p is suspected\n", neigh);
|
neigh_dbg(2, "neigh %p is suspected\n", neigh);
|
||||||
neigh->nud_state = NUD_STALE;
|
WRITE_ONCE(neigh->nud_state, NUD_STALE);
|
||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
neigh_suspect(neigh);
|
neigh_suspect(neigh);
|
||||||
notify = 1;
|
notify = 1;
|
||||||
@ -1109,14 +1109,14 @@ static void neigh_timer_handler(struct timer_list *t)
|
|||||||
neigh->confirmed +
|
neigh->confirmed +
|
||||||
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
|
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
|
||||||
neigh_dbg(2, "neigh %p is now reachable\n", neigh);
|
neigh_dbg(2, "neigh %p is now reachable\n", neigh);
|
||||||
neigh->nud_state = NUD_REACHABLE;
|
WRITE_ONCE(neigh->nud_state, NUD_REACHABLE);
|
||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
neigh_connect(neigh);
|
neigh_connect(neigh);
|
||||||
notify = 1;
|
notify = 1;
|
||||||
next = neigh->confirmed + neigh->parms->reachable_time;
|
next = neigh->confirmed + neigh->parms->reachable_time;
|
||||||
} else {
|
} else {
|
||||||
neigh_dbg(2, "neigh %p is probed\n", neigh);
|
neigh_dbg(2, "neigh %p is probed\n", neigh);
|
||||||
neigh->nud_state = NUD_PROBE;
|
WRITE_ONCE(neigh->nud_state, NUD_PROBE);
|
||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
atomic_set(&neigh->probes, 0);
|
atomic_set(&neigh->probes, 0);
|
||||||
notify = 1;
|
notify = 1;
|
||||||
@ -1130,7 +1130,7 @@ static void neigh_timer_handler(struct timer_list *t)
|
|||||||
|
|
||||||
if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
|
if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
|
||||||
atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
|
atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
|
||||||
neigh->nud_state = NUD_FAILED;
|
WRITE_ONCE(neigh->nud_state, NUD_FAILED);
|
||||||
notify = 1;
|
notify = 1;
|
||||||
neigh_invalidate(neigh);
|
neigh_invalidate(neigh);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1179,7 +1179,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb,
|
|||||||
atomic_set(&neigh->probes,
|
atomic_set(&neigh->probes,
|
||||||
NEIGH_VAR(neigh->parms, UCAST_PROBES));
|
NEIGH_VAR(neigh->parms, UCAST_PROBES));
|
||||||
neigh_del_timer(neigh);
|
neigh_del_timer(neigh);
|
||||||
neigh->nud_state = NUD_INCOMPLETE;
|
WRITE_ONCE(neigh->nud_state, NUD_INCOMPLETE);
|
||||||
neigh->updated = now;
|
neigh->updated = now;
|
||||||
if (!immediate_ok) {
|
if (!immediate_ok) {
|
||||||
next = now + 1;
|
next = now + 1;
|
||||||
@ -1191,7 +1191,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
neigh_add_timer(neigh, next);
|
neigh_add_timer(neigh, next);
|
||||||
} else {
|
} else {
|
||||||
neigh->nud_state = NUD_FAILED;
|
WRITE_ONCE(neigh->nud_state, NUD_FAILED);
|
||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
write_unlock_bh(&neigh->lock);
|
write_unlock_bh(&neigh->lock);
|
||||||
|
|
||||||
@ -1201,7 +1201,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb,
|
|||||||
} else if (neigh->nud_state & NUD_STALE) {
|
} else if (neigh->nud_state & NUD_STALE) {
|
||||||
neigh_dbg(2, "neigh %p is delayed\n", neigh);
|
neigh_dbg(2, "neigh %p is delayed\n", neigh);
|
||||||
neigh_del_timer(neigh);
|
neigh_del_timer(neigh);
|
||||||
neigh->nud_state = NUD_DELAY;
|
WRITE_ONCE(neigh->nud_state, NUD_DELAY);
|
||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
neigh_add_timer(neigh, jiffies +
|
neigh_add_timer(neigh, jiffies +
|
||||||
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
|
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
|
||||||
@ -1313,7 +1313,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
|
|||||||
neigh_update_flags(neigh, flags, ¬ify, &gc_update, &managed_update);
|
neigh_update_flags(neigh, flags, ¬ify, &gc_update, &managed_update);
|
||||||
if (flags & (NEIGH_UPDATE_F_USE | NEIGH_UPDATE_F_MANAGED)) {
|
if (flags & (NEIGH_UPDATE_F_USE | NEIGH_UPDATE_F_MANAGED)) {
|
||||||
new = old & ~NUD_PERMANENT;
|
new = old & ~NUD_PERMANENT;
|
||||||
neigh->nud_state = new;
|
WRITE_ONCE(neigh->nud_state, new);
|
||||||
err = 0;
|
err = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1322,7 +1322,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
|
|||||||
neigh_del_timer(neigh);
|
neigh_del_timer(neigh);
|
||||||
if (old & NUD_CONNECTED)
|
if (old & NUD_CONNECTED)
|
||||||
neigh_suspect(neigh);
|
neigh_suspect(neigh);
|
||||||
neigh->nud_state = new;
|
WRITE_ONCE(neigh->nud_state, new);
|
||||||
err = 0;
|
err = 0;
|
||||||
notify = old & NUD_VALID;
|
notify = old & NUD_VALID;
|
||||||
if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
|
if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
|
||||||
@ -1401,7 +1401,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
|
|||||||
((new & NUD_REACHABLE) ?
|
((new & NUD_REACHABLE) ?
|
||||||
neigh->parms->reachable_time :
|
neigh->parms->reachable_time :
|
||||||
0)));
|
0)));
|
||||||
neigh->nud_state = new;
|
WRITE_ONCE(neigh->nud_state, new);
|
||||||
notify = 1;
|
notify = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1488,7 +1488,7 @@ void __neigh_set_probe_once(struct neighbour *neigh)
|
|||||||
neigh->updated = jiffies;
|
neigh->updated = jiffies;
|
||||||
if (!(neigh->nud_state & NUD_FAILED))
|
if (!(neigh->nud_state & NUD_FAILED))
|
||||||
return;
|
return;
|
||||||
neigh->nud_state = NUD_INCOMPLETE;
|
WRITE_ONCE(neigh->nud_state, NUD_INCOMPLETE);
|
||||||
atomic_set(&neigh->probes, neigh_max_probes(neigh));
|
atomic_set(&neigh->probes, neigh_max_probes(neigh));
|
||||||
neigh_add_timer(neigh,
|
neigh_add_timer(neigh,
|
||||||
jiffies + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
|
jiffies + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
|
||||||
@ -3198,7 +3198,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
|
|||||||
}
|
}
|
||||||
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
|
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
|
||||||
break;
|
break;
|
||||||
if (n->nud_state & ~NUD_NOARP)
|
if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
|
||||||
break;
|
break;
|
||||||
next:
|
next:
|
||||||
n = rcu_dereference_bh(n->next);
|
n = rcu_dereference_bh(n->next);
|
||||||
@ -3240,7 +3240,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
|
|||||||
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
|
if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (n->nud_state & ~NUD_NOARP)
|
if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
|
||||||
break;
|
break;
|
||||||
next:
|
next:
|
||||||
n = rcu_dereference_bh(n->next);
|
n = rcu_dereference_bh(n->next);
|
||||||
|
@ -375,7 +375,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
|
|||||||
|
|
||||||
probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
|
probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
|
||||||
if (probes < 0) {
|
if (probes < 0) {
|
||||||
if (!(neigh->nud_state & NUD_VALID))
|
if (!(READ_ONCE(neigh->nud_state) & NUD_VALID))
|
||||||
pr_debug("trying to ucast probe in NUD_INVALID\n");
|
pr_debug("trying to ucast probe in NUD_INVALID\n");
|
||||||
neigh_ha_snapshot(dst_ha, neigh, dev);
|
neigh_ha_snapshot(dst_ha, neigh, dev);
|
||||||
dst_hw = dst_ha;
|
dst_hw = dst_ha;
|
||||||
@ -1123,7 +1123,7 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
|
|||||||
|
|
||||||
neigh = neigh_lookup(&arp_tbl, &ip, dev);
|
neigh = neigh_lookup(&arp_tbl, &ip, dev);
|
||||||
if (neigh) {
|
if (neigh) {
|
||||||
if (!(neigh->nud_state & NUD_NOARP)) {
|
if (!(READ_ONCE(neigh->nud_state) & NUD_NOARP)) {
|
||||||
read_lock_bh(&neigh->lock);
|
read_lock_bh(&neigh->lock);
|
||||||
memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
|
memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
|
||||||
r->arp_flags = arp_state_to_flags(neigh);
|
r->arp_flags = arp_state_to_flags(neigh);
|
||||||
@ -1144,12 +1144,12 @@ int arp_invalidate(struct net_device *dev, __be32 ip, bool force)
|
|||||||
struct neigh_table *tbl = &arp_tbl;
|
struct neigh_table *tbl = &arp_tbl;
|
||||||
|
|
||||||
if (neigh) {
|
if (neigh) {
|
||||||
if ((neigh->nud_state & NUD_VALID) && !force) {
|
if ((READ_ONCE(neigh->nud_state) & NUD_VALID) && !force) {
|
||||||
neigh_release(neigh);
|
neigh_release(neigh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (neigh->nud_state & ~NUD_NOARP)
|
if (READ_ONCE(neigh->nud_state) & ~NUD_NOARP)
|
||||||
err = neigh_update(neigh, NULL, NUD_FAILED,
|
err = neigh_update(neigh, NULL, NUD_FAILED,
|
||||||
NEIGH_UPDATE_F_OVERRIDE|
|
NEIGH_UPDATE_F_OVERRIDE|
|
||||||
NEIGH_UPDATE_F_ADMIN, 0);
|
NEIGH_UPDATE_F_ADMIN, 0);
|
||||||
|
@ -563,7 +563,7 @@ static int fib_detect_death(struct fib_info *fi, int order,
|
|||||||
n = NULL;
|
n = NULL;
|
||||||
|
|
||||||
if (n) {
|
if (n) {
|
||||||
state = n->nud_state;
|
state = READ_ONCE(n->nud_state);
|
||||||
neigh_release(n);
|
neigh_release(n);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@ -2202,7 +2202,7 @@ static bool fib_good_nh(const struct fib_nh *nh)
|
|||||||
else
|
else
|
||||||
n = NULL;
|
n = NULL;
|
||||||
if (n)
|
if (n)
|
||||||
state = n->nud_state;
|
state = READ_ONCE(n->nud_state);
|
||||||
|
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
}
|
}
|
||||||
|
@ -1128,7 +1128,7 @@ static bool ipv6_good_nh(const struct fib6_nh *nh)
|
|||||||
|
|
||||||
n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6);
|
n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6);
|
||||||
if (n)
|
if (n)
|
||||||
state = n->nud_state;
|
state = READ_ONCE(n->nud_state);
|
||||||
|
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
|
|
||||||
@ -1145,7 +1145,7 @@ static bool ipv4_good_nh(const struct fib_nh *nh)
|
|||||||
n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev,
|
n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev,
|
||||||
(__force u32)nh->fib_nh_gw4);
|
(__force u32)nh->fib_nh_gw4);
|
||||||
if (n)
|
if (n)
|
||||||
state = n->nud_state;
|
state = READ_ONCE(n->nud_state);
|
||||||
|
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
|
|
||||||
|
@ -784,7 +784,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
|
|||||||
if (!n)
|
if (!n)
|
||||||
n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev);
|
n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev);
|
||||||
if (!IS_ERR(n)) {
|
if (!IS_ERR(n)) {
|
||||||
if (!(n->nud_state & NUD_VALID)) {
|
if (!(READ_ONCE(n->nud_state) & NUD_VALID)) {
|
||||||
neigh_event_send(n, NULL);
|
neigh_event_send(n, NULL);
|
||||||
} else {
|
} else {
|
||||||
if (fib_lookup(net, fl4, &res, 0) == 0) {
|
if (fib_lookup(net, fl4, &res, 0) == 0) {
|
||||||
|
@ -1153,7 +1153,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
|
|||||||
rcu_read_lock_bh();
|
rcu_read_lock_bh();
|
||||||
n = __ipv6_neigh_lookup_noref(rt->dst.dev,
|
n = __ipv6_neigh_lookup_noref(rt->dst.dev,
|
||||||
rt6_nexthop(rt, &fl6->daddr));
|
rt6_nexthop(rt, &fl6->daddr));
|
||||||
err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0;
|
err = n && !(READ_ONCE(n->nud_state) & NUD_VALID) ? -EINVAL : 0;
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -745,7 +745,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
|
|||||||
saddr = &ipv6_hdr(skb)->saddr;
|
saddr = &ipv6_hdr(skb)->saddr;
|
||||||
probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
|
probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
|
||||||
if (probes < 0) {
|
if (probes < 0) {
|
||||||
if (!(neigh->nud_state & NUD_VALID)) {
|
if (!(READ_ONCE(neigh->nud_state) & NUD_VALID)) {
|
||||||
ND_PRINTK(1, dbg,
|
ND_PRINTK(1, dbg,
|
||||||
"%s: trying to ucast probe in NUD_INVALID: %pI6\n",
|
"%s: trying to ucast probe in NUD_INVALID: %pI6\n",
|
||||||
__func__, target);
|
__func__, target);
|
||||||
@ -1090,7 +1090,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
|
|||||||
u8 old_flags = neigh->flags;
|
u8 old_flags = neigh->flags;
|
||||||
struct net *net = dev_net(dev);
|
struct net *net = dev_net(dev);
|
||||||
|
|
||||||
if (neigh->nud_state & NUD_FAILED)
|
if (READ_ONCE(neigh->nud_state) & NUD_FAILED)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -638,7 +638,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh)
|
|||||||
idev = __in6_dev_get(dev);
|
idev = __in6_dev_get(dev);
|
||||||
neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
|
neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
|
||||||
if (neigh) {
|
if (neigh) {
|
||||||
if (neigh->nud_state & NUD_VALID)
|
if (READ_ONCE(neigh->nud_state) & NUD_VALID)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
write_lock(&neigh->lock);
|
write_lock(&neigh->lock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user