邻居子系统 之 状态定时器回调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 }