Linux内核分析 - 网络[九]:邻居表
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); (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |