zoukankan      html  css  js  c++  java
  • 邻居子系统 之 状态定时器回调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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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 }
  • 相关阅读:
    crt中文乱码
    idea使用git版本控制忽略部分文件
    Springboot配置redis连接池参数
    redis通过lua脚本实现分布式锁
    jodaTime的使用
    jmap的使用
    代理服务器没有响应解决方案
    C/C/C++中暂停调试的三种方法C++中暂停调试的三种方法
    C/C/C++中暂停调试的三种方法C++中暂停调试的三种方法
    四种常见的post请求中的参数形式
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11755403.html
Copyright © 2011-2022 走看看