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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值