加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Linux ARP cache状态转换分析

(2012-10-31 15:04:19)
标签:

it

分类: network

一 linux ARP cache状态图

http://s15/mw690/694f2ae7gcd5589d509be&690ARP cache状态转换分析" TITLE="Linux ARP cache状态转换分析" />

各个状态的含义如下:

NUD_INCOMPLETE: ARP包已经发出,还没有收到回复

NUD_REACHABLE: ARP缓存有效,可达。

NUD_FAILED:  不可达,请求返回失败

NUD_STALE: 缓存存在,not confirmed for a certain amount of time

NUD_DELAY:  当NUD_STALE状态进行用户发包,进入此状态

NUD_PROBE: NUD_DELAY 查询包无包回应的时候,进入PROBE

 

二 ARP CACHE 状态机流程

         最简单的就是表的从NONE到有,如果有回应就进入REACHABLE,如果无回应就FAILED,被回收掉。

         比较复杂的是当REACHABLE 经过”not used for more than reachable_time“后,就进入了STALE,这个状态比较复杂。下面重点介绍一下STALE状态。具体的linux 代码如下:

在一个arp表创建的时候启动如下的定时器:

static void neigh_timer_handler(unsigned long arg)

{

if (state & NUD_REACHABLE) {

                   if (time_before_eq(now,

                                        neigh->confirmed + neigh->parms->reachable_time)) {

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

                            next = neigh->confirmed + neigh->parms->reachable_time;

                   } else if (time_before_eq(now,

                                                 neigh->used + neigh->parms->delay_probe_time)) {

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

                            neigh->nud_state = NUD_DELAY;

                            neigh->updated = jiffies;

                            neigh_suspect(neigh);

                            next = now + neigh->parms->delay_probe_time;

                   } else {

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

                            neigh->nud_state = NUD_STALE;

                            neigh->updated = jiffies;

                            neigh_suspect(neigh);

                            notify = 1;

                   }

在特殊的状态转换的时候,定时器被定时的开启。

#define NUD_IN_TIMER (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)

         if (neigh->nud_state & NUD_IN_TIMER) {

                   if (time_before(next, jiffies + HZ/2))

                            next = jiffies + HZ/2;

                   if (!mod_timer(&neigh->timer, next))

                            neigh_hold(neigh);

         }

}

 

三 STALE状态机的转换

   除了neigh_timer_handler 定时器,还有一个定时器neigh_periodic_timer,这个timer就是对于缓存gc的回收处理。

当STALE状态有发送的时候:

int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)

{

if (neigh->nud_state & NUD_STALE) {

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

                   neigh_hold(neigh);

                   neigh->nud_state = NUD_DELAY;

                   neigh->updated = jiffies;

                   neigh_add_timer(neigh,

                                     jiffies + neigh->parms->delay_probe_time);

         }

}

 

static void neigh_periodic_timer(unsigned long arg)

{

                  

                  if (time_after(now, tbl->last_rand + 300 * HZ)) {

                   struct neigh_parms *p;

                   tbl->last_rand = now;

                   for (p = &tbl->parms; p; p = p->next)

                            p->reachable_time =

                                     neigh_rand_reach_time(p->base_reachable_time);

         }

 

                   if (atomic_read(&n->refcnt) == 1 &&

                       (state == NUD_FAILED ||

                        time_after(now, n->used + n->parms->gc_staletime))) {

                            *np = n->next;

                            n->dead = 1;

                            write_unlock(&n->lock);

                            if (n->parms->neigh_cleanup)

                                     n->parms->neigh_cleanup(n);

                            neigh_release(n);

                            continue;

                   }

 

         过期的时间,expire 根据base_reachable_time,当时间过期之后,就会执行上面的代码,将cache进行回收。

expire = tbl->parms.base_reachable_time >> 1;

         expire /= (tbl->hash_mask + 1);

         if (!expire)

                   expire = 1;

 

         if (expire>HZ)

                   mod_timer(&tbl->gc_timer, round_jiffies(now + expire));

         else

                   mod_timer(&tbl->gc_timer, now + expire);

 

 

}

四 ARP缓存老化时间

         实际使用中,ARP的老化缓存时间。默认情况下reachable的持续时间的base_reachable_time,一般默认值是30s,等30s过后在发现没有包的交互后,相应的表状态转化为STALE,注意有一个gc_stale_time,这个就是STALE维持的时间,在gc_stale_time时间没有得到使用的话,就会被删除掉。具体在要经过多少时间删除此表呢。那就从neigh_periodic_timer在经过base_reachable_time时间的timer后,发现gc_stale_time的时间已经超过,那么就会将此表删除掉。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有