加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[九]:邻居表

发布时间:2016-05-28 22:17:43 所属栏目:Linux 来源:网络整理
导读:内核版本:2.6.34 这部分的重点是三个核心的数据结构-邻居表、邻居缓存、代理邻居表,以及NUD状态转移图。 总的来说,要成功添加一条邻居表项,需要满足两个条

neigh_event_send

当主机需要解析地址,会调用neigh_resolve_output,主机引用表项明显会涉及到表项的NUD状 态迁移,NUD_NONE->NUD_INCOMPLETE,NUD_STALE->NUD_DELAY。

neigh_event_send -> __neigh_event_send

只 处理nud_state在NUD_NONE, NUD_STALE, NUD_INCOMPLETE状态时的情况:

if (neigh->nud_state & 

(NUD_CONNECTED | NUD_DELAY | NUD_PROBE))     
  goto out_unlock_bh;

不处于NUD_STALE和NUD_INCOMPLETE状态,则只能是NUD_NONE。此时主机要用到该邻居表项(注 意是通过neigh_resolve_output进入的),但还没有,因此要通过ARP进行解析,并且此时没有收到对方发来的任何报文,要进行 的ARP是广播形式。

在发送ARP报文时有3个参数- ucast_probes, mcast_probes, app_probes,分别代表单播次数,广播次数 ,app_probes比较特殊,一般情况下为0,当使用了arpd守护进程时才会设置它的值。如果已经收到过对方的报文,即知道了对 方的MAC-IP,ARP解析会使用单播形式,次数由ucast_probes决定;如果未收到过对方报文,此时ARP解析只能使用广播形式,次 数由mcasat_probes决定。

当mcast_probes有值时,neigh进入NUD_INCOMPLETE状态,设置定时器,注意此时neigh_probes(表 示已经进行探测的次数)初始化为ucast_probes,目的是只进行mcast_probes次广播;当mcast_probes值为0时(表明当前配置不 允许解析),neigh进入NUD_FAILED状态,被清除。

if (!(neigh->nud_state & (NUD_STALE | 

NUD_INCOMPLETE))) {     
 if (neigh->parms->mcast_probes + neigh->parms->app_probes) {     
  atomic_set(&neigh->probes, neigh->parms->ucast_probes);     
  neigh->nud_state     = NUD_INCOMPLETE;     
  neigh->updated = jiffies;     
  neigh_add_timer(neigh, now + 1);     
 } else {     
  neigh->nud_state = NUD_FAILED;     
  neigh->updated = jiffies;     
  write_unlock_bh(&neigh->lock);     
         
  kfree_skb(skb);     
  return 1;     
 }     
}

当neigh处于NUD_STALE状态时,根据NUD的状态转移图,主机引用到了该邻居表项,neigh转移至NUD_DELAY状态,设 置定时器。

else if (neigh->nud_state & NUD_STALE) {
 NEIGH_PRINTK2("neigh %p is delayed.n", neigh);
 neigh->nud_state = NUD_DELAY;
 neigh->updated = jiffies;
 neigh_add_timer(neigh, jiffies + neigh->parms->delay_probe_time);
}

当neigh处于NUD_INCOMPLETE状态时,需要发送ARP报文进行地址解析,__skb_queue_tail(&neigh->arp_queue, skb) 的作用就是先把要发送的报文缓存起来,放到neigh->arp_queue链表中,当完成地址解析,再从neigh->arp_queue取出报 文,并发送出去。

if (neigh->nud_state == NUD_INCOMPLETE) {     
 if (skb) {     
  if (skb_queue_len(&neigh->arp_queue) >= neigh->parms->queue_len) {     
   struct sk_buff *buff;     
   buff = __skb_dequeue(&neigh->arp_queue);     
   kfree_skb(buff);     
   NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);     
  }     
  __skb_queue_tail(&neigh->arp_queue, skb);     
 }     
 rc = 1;     
}

邻居表的操作

neigh_create 创建邻居表项

首先为新的邻居表项struct neighbour分配空间,并做一些初始化 。传入的参数tbl就是全局量arp_tbl,分配空间的大小是tbl->entry_size,而这个值在声明arp_tbl时初始化为sizeof (struct neighbour) + 4,多出的4个字节就是key值存放的地方。

n = neigh_alloc(tbl);

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读