mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
neighbour: Update pneigh_entry in pneigh_create().
neigh_add() updates pneigh_entry() found or created by pneigh_create(). This update is serialised by RTNL, but we will remove it. Let's move the update part to pneigh_create() and make it return errno instead of a pointer of pneigh_entry. Now, the pneigh code is RTNL free. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20250716221221.442239-16-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
13a936bb99
commit
dc2a27e524
|
|
@ -382,8 +382,9 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net,
|
struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net,
|
||||||
const void *key, struct net_device *dev);
|
const void *key, struct net_device *dev);
|
||||||
struct pneigh_entry *pneigh_create(struct neigh_table *tbl, struct net *net,
|
int pneigh_create(struct neigh_table *tbl, struct net *net, const void *key,
|
||||||
const void *key, struct net_device *dev);
|
struct net_device *dev, u32 flags, u8 protocol,
|
||||||
|
bool permanent);
|
||||||
int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key,
|
int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -747,24 +747,27 @@ struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl,
|
||||||
}
|
}
|
||||||
EXPORT_IPV6_MOD(pneigh_lookup);
|
EXPORT_IPV6_MOD(pneigh_lookup);
|
||||||
|
|
||||||
struct pneigh_entry *pneigh_create(struct neigh_table *tbl,
|
int pneigh_create(struct neigh_table *tbl, struct net *net,
|
||||||
struct net *net, const void *pkey,
|
const void *pkey, struct net_device *dev,
|
||||||
struct net_device *dev)
|
u32 flags, u8 protocol, bool permanent)
|
||||||
{
|
{
|
||||||
struct pneigh_entry *n;
|
struct pneigh_entry *n;
|
||||||
unsigned int key_len;
|
unsigned int key_len;
|
||||||
u32 hash_val;
|
u32 hash_val;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
mutex_lock(&tbl->phash_lock);
|
mutex_lock(&tbl->phash_lock);
|
||||||
|
|
||||||
n = pneigh_lookup(tbl, net, pkey, dev);
|
n = pneigh_lookup(tbl, net, pkey, dev);
|
||||||
if (n)
|
if (n)
|
||||||
goto out;
|
goto update;
|
||||||
|
|
||||||
key_len = tbl->key_len;
|
key_len = tbl->key_len;
|
||||||
n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL);
|
n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL);
|
||||||
if (!n)
|
if (!n) {
|
||||||
|
err = -ENOBUFS;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
write_pnet(&n->net, net);
|
write_pnet(&n->net, net);
|
||||||
memcpy(n->key, pkey, key_len);
|
memcpy(n->key, pkey, key_len);
|
||||||
|
|
@ -774,16 +777,20 @@ struct pneigh_entry *pneigh_create(struct neigh_table *tbl,
|
||||||
if (tbl->pconstructor && tbl->pconstructor(n)) {
|
if (tbl->pconstructor && tbl->pconstructor(n)) {
|
||||||
netdev_put(dev, &n->dev_tracker);
|
netdev_put(dev, &n->dev_tracker);
|
||||||
kfree(n);
|
kfree(n);
|
||||||
n = NULL;
|
err = -ENOBUFS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_val = pneigh_hash(pkey, key_len);
|
hash_val = pneigh_hash(pkey, key_len);
|
||||||
n->next = tbl->phash_buckets[hash_val];
|
n->next = tbl->phash_buckets[hash_val];
|
||||||
rcu_assign_pointer(tbl->phash_buckets[hash_val], n);
|
rcu_assign_pointer(tbl->phash_buckets[hash_val], n);
|
||||||
|
update:
|
||||||
|
WRITE_ONCE(n->flags, flags);
|
||||||
|
n->permanent = permanent;
|
||||||
|
WRITE_ONCE(n->protocol, protocol);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&tbl->phash_lock);
|
mutex_unlock(&tbl->phash_lock);
|
||||||
return n;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pneigh_destroy(struct rcu_head *rcu)
|
static void pneigh_destroy(struct rcu_head *rcu)
|
||||||
|
|
@ -2015,22 +2022,13 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
if (tb[NDA_PROTOCOL])
|
if (tb[NDA_PROTOCOL])
|
||||||
protocol = nla_get_u8(tb[NDA_PROTOCOL]);
|
protocol = nla_get_u8(tb[NDA_PROTOCOL]);
|
||||||
if (ndm_flags & NTF_PROXY) {
|
if (ndm_flags & NTF_PROXY) {
|
||||||
struct pneigh_entry *pn;
|
|
||||||
|
|
||||||
if (ndm_flags & (NTF_MANAGED | NTF_EXT_VALIDATED)) {
|
if (ndm_flags & (NTF_MANAGED | NTF_EXT_VALIDATED)) {
|
||||||
NL_SET_ERR_MSG(extack, "Invalid NTF_* flag combination");
|
NL_SET_ERR_MSG(extack, "Invalid NTF_* flag combination");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = -ENOBUFS;
|
err = pneigh_create(tbl, net, dst, dev, ndm_flags, protocol,
|
||||||
pn = pneigh_create(tbl, net, dst, dev);
|
!!(ndm->ndm_state & NUD_PERMANENT));
|
||||||
if (pn) {
|
|
||||||
WRITE_ONCE(pn->flags, ndm_flags);
|
|
||||||
pn->permanent = !!(ndm->ndm_state & NUD_PERMANENT);
|
|
||||||
if (protocol)
|
|
||||||
WRITE_ONCE(pn->protocol, protocol);
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1089,9 +1089,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
|
||||||
if (mask) {
|
if (mask) {
|
||||||
__be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
|
__be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
|
||||||
|
|
||||||
if (!pneigh_create(&arp_tbl, net, &ip, dev))
|
return pneigh_create(&arp_tbl, net, &ip, dev, 0, 0, false);
|
||||||
return -ENOBUFS;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return arp_req_set_proxy(net, dev, 1);
|
return arp_req_set_proxy(net, dev, 1);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user