mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
ipv4: Make neigh lookups directly in output packet path.
Do not use the dst cached neigh, we'll be getting rid of that. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
11604721a3
commit
a263b30936
@ -15,24 +15,34 @@ static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd
|
|||||||
return val * hash_rnd;
|
return val * hash_rnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
|
static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
|
||||||
{
|
{
|
||||||
struct neigh_hash_table *nht;
|
struct neigh_hash_table *nht = rcu_dereference_bh(arp_tbl.nht);
|
||||||
struct neighbour *n;
|
struct neighbour *n;
|
||||||
u32 hash_val;
|
u32 hash_val;
|
||||||
|
|
||||||
rcu_read_lock_bh();
|
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
|
||||||
nht = rcu_dereference_bh(arp_tbl.nht);
|
key = 0;
|
||||||
|
|
||||||
hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
|
hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
|
||||||
for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
|
for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
|
||||||
n != NULL;
|
n != NULL;
|
||||||
n = rcu_dereference_bh(n->next)) {
|
n = rcu_dereference_bh(n->next)) {
|
||||||
if (n->dev == dev && *(u32 *)n->primary_key == key) {
|
if (n->dev == dev && *(u32 *)n->primary_key == key)
|
||||||
if (!atomic_inc_not_zero(&n->refcnt))
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
|
||||||
|
{
|
||||||
|
struct neighbour *n;
|
||||||
|
|
||||||
|
rcu_read_lock_bh();
|
||||||
|
n = __ipv4_neigh_lookup_noref(dev, key);
|
||||||
|
if (n && !atomic_inc_not_zero(&n->refcnt))
|
||||||
n = NULL;
|
n = NULL;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
|
@ -202,9 +202,16 @@ extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
|
|||||||
extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl,
|
extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl,
|
||||||
struct net *net,
|
struct net *net,
|
||||||
const void *pkey);
|
const void *pkey);
|
||||||
extern struct neighbour * neigh_create(struct neigh_table *tbl,
|
extern struct neighbour * __neigh_create(struct neigh_table *tbl,
|
||||||
const void *pkey,
|
const void *pkey,
|
||||||
struct net_device *dev);
|
struct net_device *dev,
|
||||||
|
bool want_ref);
|
||||||
|
static inline struct neighbour *neigh_create(struct neigh_table *tbl,
|
||||||
|
const void *pkey,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
return __neigh_create(tbl, pkey, dev, true);
|
||||||
|
}
|
||||||
extern void neigh_destroy(struct neighbour *neigh);
|
extern void neigh_destroy(struct neighbour *neigh);
|
||||||
extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
|
extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
|
||||||
extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
|
extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
|
||||||
|
@ -474,8 +474,8 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(neigh_lookup_nodev);
|
EXPORT_SYMBOL(neigh_lookup_nodev);
|
||||||
|
|
||||||
struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
|
struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
|
||||||
struct net_device *dev)
|
struct net_device *dev, bool want_ref)
|
||||||
{
|
{
|
||||||
u32 hash_val;
|
u32 hash_val;
|
||||||
int key_len = tbl->key_len;
|
int key_len = tbl->key_len;
|
||||||
@ -535,6 +535,7 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
|
|||||||
n1 = rcu_dereference_protected(n1->next,
|
n1 = rcu_dereference_protected(n1->next,
|
||||||
lockdep_is_held(&tbl->lock))) {
|
lockdep_is_held(&tbl->lock))) {
|
||||||
if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
|
if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
|
||||||
|
if (want_ref)
|
||||||
neigh_hold(n1);
|
neigh_hold(n1);
|
||||||
rc = n1;
|
rc = n1;
|
||||||
goto out_tbl_unlock;
|
goto out_tbl_unlock;
|
||||||
@ -542,6 +543,7 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
n->dead = 0;
|
n->dead = 0;
|
||||||
|
if (want_ref)
|
||||||
neigh_hold(n);
|
neigh_hold(n);
|
||||||
rcu_assign_pointer(n->next,
|
rcu_assign_pointer(n->next,
|
||||||
rcu_dereference_protected(nht->hash_buckets[hash_val],
|
rcu_dereference_protected(nht->hash_buckets[hash_val],
|
||||||
@ -558,7 +560,7 @@ out_neigh_release:
|
|||||||
neigh_release(n);
|
neigh_release(n);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(neigh_create);
|
EXPORT_SYMBOL(__neigh_create);
|
||||||
|
|
||||||
static u32 pneigh_hash(const void *pkey, int key_len)
|
static u32 pneigh_hash(const void *pkey, int key_len)
|
||||||
{
|
{
|
||||||
|
@ -170,6 +170,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
|
|||||||
struct net_device *dev = dst->dev;
|
struct net_device *dev = dst->dev;
|
||||||
unsigned int hh_len = LL_RESERVED_SPACE(dev);
|
unsigned int hh_len = LL_RESERVED_SPACE(dev);
|
||||||
struct neighbour *neigh;
|
struct neighbour *neigh;
|
||||||
|
u32 nexthop;
|
||||||
|
|
||||||
if (rt->rt_type == RTN_MULTICAST) {
|
if (rt->rt_type == RTN_MULTICAST) {
|
||||||
IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
|
IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
|
||||||
@ -191,15 +192,18 @@ static inline int ip_finish_output2(struct sk_buff *skb)
|
|||||||
skb = skb2;
|
skb = skb2;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock_bh();
|
||||||
neigh = dst_get_neighbour_noref(dst);
|
nexthop = rt->rt_gateway ? rt->rt_gateway : ip_hdr(skb)->daddr;
|
||||||
|
neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
|
||||||
|
if (unlikely(!neigh))
|
||||||
|
neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
|
||||||
if (neigh) {
|
if (neigh) {
|
||||||
int res = neigh_output(neigh, skb);
|
int res = neigh_output(neigh, skb);
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock_bh();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock_bh();
|
||||||
|
|
||||||
net_dbg_ratelimited("%s: No header cache and no neighbour!\n",
|
net_dbg_ratelimited("%s: No header cache and no neighbour!\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
@ -1098,17 +1098,13 @@ static int slow_chain_length(const struct rtable *head)
|
|||||||
|
|
||||||
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
|
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
|
||||||
{
|
{
|
||||||
static const __be32 inaddr_any = 0;
|
|
||||||
struct net_device *dev = dst->dev;
|
struct net_device *dev = dst->dev;
|
||||||
const __be32 *pkey = daddr;
|
const __be32 *pkey = daddr;
|
||||||
const struct rtable *rt;
|
const struct rtable *rt;
|
||||||
struct neighbour *n;
|
struct neighbour *n;
|
||||||
|
|
||||||
rt = (const struct rtable *) dst;
|
rt = (const struct rtable *) dst;
|
||||||
|
if (rt->rt_gateway)
|
||||||
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
|
|
||||||
pkey = &inaddr_any;
|
|
||||||
else if (rt->rt_gateway)
|
|
||||||
pkey = (const __be32 *) &rt->rt_gateway;
|
pkey = (const __be32 *) &rt->rt_gateway;
|
||||||
|
|
||||||
n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
|
n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user