邻居子系统 之 状态定时器回调neigh_timer_handler

概述

在分配邻居子系统之后,会设置定时器来处理那些需要定时器处理的状态,定时器回调函数为neigh_timer_handler;函数会根据状态机变换规则对状态进行切换,切换状态后,如果需要更新输出函数则更新,并更新定时器下一次超时时间;其中NUD_INCOMPLETE | NUD_PROBE状态需要发送邻居请求,如果超过最大次数,则释放缓存中的数据包;

源码分析
  1 /* 邻居项各个状态的定时器处理回调 */
  2 static void neigh_timer_handler(unsigned long arg)
  3 {
  4     unsigned long now, next;
  5     struct neighbour *neigh = (struct neighbour *)arg;
  6     unsigned int state;
  7     int notify = 0;
  8 
  9     write_lock(&neigh->lock);
 10 
 11     state = neigh->nud_state;
 12     now = jiffies;
 13     next = now + HZ;
 14 
 15     /* 无定时器状态 */
 16     if (!(state & NUD_IN_TIMER))
 17         goto out;
 18 
 19     /* REACHABLE状态 */
 20     if (state & NUD_REACHABLE) {
 21         /* 确认时间未超时,设置下次超时时间 */
 22         if (time_before_eq(now,
 23                    neigh->confirmed + neigh->parms->reachable_time)) {
 24             neigh_dbg(2, "neigh %p is still alive\n", neigh);
 25             next = neigh->confirmed + neigh->parms->reachable_time;
 26         } 
 27         /* 确认时间已经超时了,但是闲置时间未达到 */
 28         else if (time_before_eq(now,
 29                       neigh->used +
 30                       NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
 31             neigh_dbg(2, "neigh %p is delayed\n", neigh);
 32             /* 进入DELAY状态 */
 33             neigh->nud_state = NUD_DELAY;
 34             neigh->updated = jiffies;
 35 
 36             /* 更新output函数 */
 37             neigh_suspect(neigh);
 38             next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
 39         } 
 40         /* 确认时间和闲置时间都超时了 */
 41         else {
 42             neigh_dbg(2, "neigh %p is suspected\n", neigh);
 43             /* 进入STALE状态 */
 44             neigh->nud_state = NUD_STALE;
 45             neigh->updated = jiffies;
 46             /* 更新输出函数 */
 47             neigh_suspect(neigh);
 48             notify = 1;
 49         }
 50     } 
 51     /* DELAY状态 */
 52     else if (state & NUD_DELAY) {
 53         /* 最后一次确认时间没达到超时时间 */
 54         if (time_before_eq(now,
 55                    neigh->confirmed +
 56                    NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
 57             neigh_dbg(2, "neigh %p is now reachable\n", neigh);
 58 
 59             /* 进入REACHABLE状态,更新输出函数 */
 60             neigh->nud_state = NUD_REACHABLE;
 61             neigh->updated = jiffies;
 62             neigh_connect(neigh);
 63             notify = 1;
 64             next = neigh->confirmed + neigh->parms->reachable_time;
 65         } 
 66         /* 最后确认时间已经达到了超时时间,进入PROBE状态 */
 67         else {
 68             neigh_dbg(2, "neigh %p is probed\n", neigh);
 69             neigh->nud_state = NUD_PROBE;
 70             neigh->updated = jiffies;
 71             atomic_set(&neigh->probes, 0);
 72             notify = 1;
 73             next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
 74         }
 75     }
 76     /* NUD_PROBE|NUD_INCOMPLETE */
 77     else {
 78         /* NUD_PROBE|NUD_INCOMPLETE */
 79         next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
 80     }
 81 
 82     /* NUD_PROBE|NUD_INCOMPLETE状态,达到了最大尝试次数 */
 83     if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
 84         atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
 85         /* 进入FAILED状态,清空缓存包队列 */
 86         neigh->nud_state = NUD_FAILED;
 87         notify = 1;
 88         neigh_invalidate(neigh);
 89         goto out;
 90     }
 91 
 92     /* 定时器处理状态,则更新定时器 */
 93     if (neigh->nud_state & NUD_IN_TIMER) {
 94         if (time_before(next, jiffies + HZ/2))
 95             next = jiffies + HZ/2;
 96         if (!mod_timer(&neigh->timer, next))
 97             neigh_hold(neigh);
 98     }
 99 
100     /* NUD_PROBE|NUD_INCOMPLETE状态,发送请求包 */
101     if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
102         neigh_probe(neigh);
103     } else {
104 out:
105         write_unlock(&neigh->lock);
106     }
107 
108     /* 通知关心的模块 */
109     if (notify)
110         neigh_update_notify(neigh, 0);
111 
112     neigh_release(neigh);
113 }

 

posted @ 2019-10-28 20:44  AlexAlex  阅读(890)  评论(0编辑  收藏  举报