Skip to content

Commit e804bd8

Browse files
q2venkuba-moo
authored andcommitted
neighbour: Split pneigh_lookup().
pneigh_lookup() has ASSERT_RTNL() in the middle of the function, which is confusing. When called with the last argument, creat, 0, pneigh_lookup() literally looks up a proxy neighbour entry. This is the case of the reader path as the fast path and RTM_GETNEIGH. pneigh_lookup(), however, creates a pneigh_entry when called with creat 1 from RTM_NEWNEIGH and SIOCSARP, which require RTNL. Let's split pneigh_lookup() into two functions. We will convert all the reader paths to RCU, and read_lock_bh(&tbl->lock) in the new pneigh_lookup() will be dropped. Signed-off-by: Kuniyuki Iwashima <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 0e5ac19 commit e804bd8

File tree

5 files changed

+36
-16
lines changed

5 files changed

+36
-16
lines changed

include/net/neighbour.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,11 @@ unsigned long neigh_rand_reach_time(unsigned long base);
376376
void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
377377
struct sk_buff *skb);
378378
struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net,
379-
const void *key, struct net_device *dev,
380-
int creat);
379+
const void *key, struct net_device *dev);
381380
struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, struct net *net,
382381
const void *key, struct net_device *dev);
382+
struct pneigh_entry *pneigh_create(struct neigh_table *tbl, struct net *net,
383+
const void *key, struct net_device *dev);
383384
int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key,
384385
struct net_device *dev);
385386

net/core/neighbour.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <net/neighbour.h>
2929
#include <net/arp.h>
3030
#include <net/dst.h>
31+
#include <net/ip.h>
3132
#include <net/sock.h>
3233
#include <net/netevent.h>
3334
#include <net/netlink.h>
@@ -746,24 +747,44 @@ struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
746747
}
747748
EXPORT_SYMBOL_GPL(__pneigh_lookup);
748749

749-
struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
750-
struct net *net, const void *pkey,
751-
struct net_device *dev, int creat)
750+
struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl,
751+
struct net *net, const void *pkey,
752+
struct net_device *dev)
753+
{
754+
struct pneigh_entry *n;
755+
unsigned int key_len;
756+
u32 hash_val;
757+
758+
key_len = tbl->key_len;
759+
hash_val = pneigh_hash(pkey, key_len);
760+
761+
read_lock_bh(&tbl->lock);
762+
n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
763+
net, pkey, key_len, dev);
764+
read_unlock_bh(&tbl->lock);
765+
766+
return n;
767+
}
768+
EXPORT_IPV6_MOD(pneigh_lookup);
769+
770+
struct pneigh_entry *pneigh_create(struct neigh_table *tbl,
771+
struct net *net, const void *pkey,
772+
struct net_device *dev)
752773
{
753774
struct pneigh_entry *n;
754775
unsigned int key_len = tbl->key_len;
755776
u32 hash_val = pneigh_hash(pkey, key_len);
756777

778+
ASSERT_RTNL();
779+
757780
read_lock_bh(&tbl->lock);
758781
n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
759782
net, pkey, key_len, dev);
760783
read_unlock_bh(&tbl->lock);
761784

762-
if (n || !creat)
785+
if (n)
763786
goto out;
764787

765-
ASSERT_RTNL();
766-
767788
n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL);
768789
if (!n)
769790
goto out;
@@ -787,8 +808,6 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
787808
out:
788809
return n;
789810
}
790-
EXPORT_SYMBOL(pneigh_lookup);
791-
792811

793812
int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
794813
struct net_device *dev)
@@ -2007,7 +2026,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
20072026
}
20082027

20092028
err = -ENOBUFS;
2010-
pn = pneigh_lookup(tbl, net, dst, dev, 1);
2029+
pn = pneigh_create(tbl, net, dst, dev);
20112030
if (pn) {
20122031
pn->flags = ndm_flags;
20132032
pn->permanent = !!(ndm->ndm_state & NUD_PERMANENT);
@@ -3036,7 +3055,7 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
30363055
if (ndm->ndm_flags & NTF_PROXY) {
30373056
struct pneigh_entry *pn;
30383057

3039-
pn = pneigh_lookup(tbl, net, dst, dev, 0);
3058+
pn = pneigh_lookup(tbl, net, dst, dev);
30403059
if (!pn) {
30413060
NL_SET_ERR_MSG(extack, "Proxy neighbour entry not found");
30423061
err = -ENOENT;

net/ipv4/arp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
864864
(arp_fwd_proxy(in_dev, dev, rt) ||
865865
arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
866866
(rt->dst.dev != dev &&
867-
pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
867+
pneigh_lookup(&arp_tbl, net, &tip, dev)))) {
868868
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
869869
if (n)
870870
neigh_release(n);
@@ -1089,7 +1089,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
10891089
if (mask) {
10901090
__be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
10911091

1092-
if (!pneigh_lookup(&arp_tbl, net, &ip, dev, 1))
1092+
if (!pneigh_create(&arp_tbl, net, &ip, dev))
10931093
return -ENOBUFS;
10941094
return 0;
10951095
}

net/ipv6/ip6_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ int ip6_forward(struct sk_buff *skb)
563563

564564
/* XXX: idev->cnf.proxy_ndp? */
565565
if (READ_ONCE(net->ipv6.devconf_all->proxy_ndp) &&
566-
pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
566+
pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev)) {
567567
int proxied = ip6_forward_proxy_check(skb);
568568
if (proxied > 0) {
569569
/* It's tempting to decrease the hop limit

net/ipv6/ndisc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
11001100
if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
11011101
READ_ONCE(net->ipv6.devconf_all->forwarding) &&
11021102
READ_ONCE(net->ipv6.devconf_all->proxy_ndp) &&
1103-
pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
1103+
pneigh_lookup(&nd_tbl, net, &msg->target, dev)) {
11041104
/* XXX: idev->cnf.proxy_ndp */
11051105
goto out;
11061106
}

0 commit comments

Comments
 (0)