概述
邻居项查找是通过neigh_lookup相关函数来进行的;
___neigh_lookup_noref,该函数根据输出设备和主键值(IPv4为下一跳ip地址)在邻居项hash表中查找,找到则返回该项;
neigh_lookup,该函数调用了___neigh_lookup_noref函数,并且在找到邻居项之后,进行引用计数的递增,然后返回该项;
源码分析
1 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, 2 struct net_device *dev) 3 { 4 struct neighbour *n; 5 6 NEIGH_CACHE_STAT_INC(tbl, lookups); 7 8 rcu_read_lock_bh(); 9 10 /* 非引用查找邻居项 */ 11 n = __neigh_lookup_noref(tbl, pkey, dev); 12 13 /* 增加引用计数 */ 14 if (n) { 15 if (!atomic_inc_not_zero(&n->refcnt)) 16 n = NULL; 17 NEIGH_CACHE_STAT_INC(tbl, hits); 18 } 19 20 rcu_read_unlock_bh(); 21 22 /* 返回邻居项 */ 23 return n; 24 }
1 static inline struct neighbour *__neigh_lookup_noref(struct neigh_table *tbl, 2 const void *pkey, 3 struct net_device *dev) 4 { 5 return ___neigh_lookup_noref(tbl, tbl->key_eq, tbl->hash, pkey, dev); 6 }
1 static inline struct neighbour *___neigh_lookup_noref( 2 struct neigh_table *tbl, 3 bool (*key_eq)(const struct neighbour *n, const void *pkey), 4 __u32 (*hash)(const void *pkey, 5 const struct net_device *dev, 6 __u32 *hash_rnd), 7 const void *pkey, 8 struct net_device *dev) 9 { 10 /* 获取hash */ 11 struct neigh_hash_table *nht = rcu_dereference_bh(tbl->nht); 12 struct neighbour *n; 13 u32 hash_val; 14 15 /* 计算hash值 */ 16 hash_val = hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); 17 18 /* 遍历hash表项 */ 19 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); 20 n != NULL; 21 n = rcu_dereference_bh(n->next)) { 22 /* 找到则返回该项 */ 23 if (n->dev == dev && key_eq(n, pkey)) 24 return n; 25 } 26 27 /* 未找到则返回NULL */ 28 return NULL; 29 }