linux内核的邻居表,linux路由内核实现分析(一)----邻居子节点(2)

邻居节点相关的操作:

查找到路由后,会调用arp_bind_neighbour绑定一个邻居项

int

arp_bind_neighbour(struct dst_entry *dst)

{

struct net_device *dev = dst->dev;

struct neighbour *n = dst->neighbour;

if (dev == NULL)

return -EINVAL;

//如果这个邻居不存在,则执行__neigh_lookup_errno

if (n == NULL) {

__be32 nexthop = ((struct

rtable*)dst)->rt_gateway;

if

(dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))

nexthop = 0;

n = __neigh_lookup_errno(

//ATM网络和以太网络调用了不同的neigh_table,作为以太网络将调用&arp_tbl作为neigh_table的入口

#if

defined(CONFIG_ATM_CLIP) ||

defined(CONFIG_ATM_CLIP_MODULE)

dev->type == ARPHRD_ATM ? clip_tbl_hook :

#endif

&arp_tbl, &nexthop,

dev);

if (IS_ERR(n))

return PTR_ERR(n);

dst->neighbour = n;

}

return 0;

}

__neigh_lookup_errno函数

static

inline struct neighbour *

__neigh_lookup_errno(struct neigh_table *tbl, const void

*pkey,

struct net_device

*dev)

{

//在邻居表中查找邻居项,如果不存在,则新建一项

struct neighbour *n = neigh_lookup(tbl, pkey, dev);

if (n)

return n;

//新建邻居项

return neigh_create(tbl, pkey, dev);

}

neigh_lookup函数

struct neighbour *neigh_lookup(struct neigh_table

*tbl, const void *pkey,

struct net_device *dev)

{

struct neighbour *n;

int key_len = tbl->key_len;

u32 hash_val = tbl->hash(pkey, dev);

NEIGH_CACHE_STAT_INC(tbl, lookups);

read_lock_bh(&tbl->lock);

//以下代码可以看出,通过指定的neigh_table入口,找到hash_buckets,

//因为所有的neighbour链表是经过哈希的,所以再通过传入的哈希值作为

//下标最后找到链表头,然后在往下遍历,直到找到相对应的neighbour结构

//为止

for (n = tbl->hash_buckets[hash_val

& tbl->hash_mask]; n; n =

n->next) {

if (dev == n->dev &&

!memcmp(n->primary_key, pkey, key_len)) {

neigh_hold(n);

NEIGH_CACHE_STAT_INC(tbl, hits);

break;

}

}

read_unlock_bh(&tbl->lock);

return n;

}

如果到邻居表中寻找对应的邻居项,如果不存在,则新建一项。继续跟进调用neigh_create函数

struct

neighbour *neigh_create(struct neigh_table *tbl, const void

*pkey,

struct net_device *dev)

{

u32 hash_val;

int key_len = tbl->key_len;

int error;

struct neighbour *n1, *rc, *n = neigh_alloc(tbl);

if (!n) {

rc = ERR_PTR(-ENOBUFS);

goto out;

}

//每个neighbour的哈希就是在这里计算的,实际上我们可以看出,

//所谓的哈希值就是目的IP

memcpy(n->primary_key, pkey, key_len);

n->dev = dev;

dev_hold(dev);

if (tbl->constructor

&& (error =

tbl->constructor(n)) < 0)

{

rc = ERR_PTR(error);

goto out_neigh_release;

}

if (n->parms->neigh_setup

&&

(error = n->parms->neigh_setup(n))

< 0) {

rc = ERR_PTR(error);

goto out_neigh_release;

}

n->confirmed = jiffies -

(n->parms->base_reachable_time

<< 1);

write_lock_bh(&tbl->lock);

if (atomic_read(&tbl->entries)

> (tbl->hash_mask + 1))

neigh_hash_grow(tbl, (tbl->hash_mask + 1)

<< 1);

hash_val = tbl->hash(pkey, dev) &

tbl->hash_mask;

if (n->parms->dead) {

rc = ERR_PTR(-EINVAL);

goto out_tbl_unlock;

}

//查找所添加的邻居是否已经存在

for (n1 = tbl->hash_buckets[hash_val]; n1; n1 =

n1->next) {

if (dev == n1->dev

&&

!memcmp(n1->primary_key, pkey, key_len))

{

neigh_hold(n1);

rc = n1;

goto out_tbl_unlock;

}

}

n->next =

tbl->hash_buckets[hash_val];

tbl->hash_buckets[hash_val] = n;

n->dead = 0;

neigh_hold(n);

write_unlock_bh(&tbl->lock);

NEIGH_PRINTK2("neigh %p is created.\n", n);

rc = n;

out:

return rc;

out_tbl_unlock:

write_unlock_bh(&tbl->lock);

out_neigh_release:

neigh_release(n);

goto out;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值