OSPF SPF计算的避让算法

4 篇文章 2 订阅

OSPF在计算SPF时,为了防止震荡以及连续收到LSA时多次计算SPF,某些代码里实现了避让算法。代码如下:

#define OSPF_SPF_INCREMENT_VALUE 2
#define ONE_SEC_MICROSECOND      1000000
void ospf_spf_calculate_timer_add (struct ospf_area *area)
{
    struct ospf_master *om = area->top->om;
    struct ospf *top = area->top;
    timeval now, delta, delay, hold;
    time_tzcurrent (&now, NULL);
    delta = TV_SUB (now, area->tv_spf);
    if ((TV_CMP (delta, area->tv_spf_curr)) < 0) {
        delay = TV_SUB (area->tv_spf_curr, delta);
        /* Change the value of tv_spf_curr to 5 times its value */
        area->tv_spf_curr.tv_sec *= OSPF_SPF_INCREMENT_VALUE;
        area->tv_spf_curr.tv_sec += ((OSPF_SPF_INCREMENT_VALUE *
                                      area->tv_spf_curr.tv_usec) / ONE_SEC_MICROSECOND);
        area->tv_spf_curr.tv_usec = (OSPF_SPF_INCREMENT_VALUE *
                                     area->tv_spf_curr.tv_usec) % ONE_SEC_MICROSECOND;
    }
    else {
        delay.tv_sec = delay.tv_usec = 0;
        hold = area->tv_spf_curr;
        hold.tv_sec *= OSPF_SPF_INCREMENT_VALUE;
        hold.tv_sec += ((OSPF_SPF_INCREMENT_VALUE * hold.tv_usec) / ONE_SEC_MICROSECOND);
        hold.tv_usec = (OSPF_SPF_INCREMENT_VALUE * hold.tv_usec) % ONE_SEC_MICROSECOND;
        if (TV_CMP (top->spf_max_delay, hold) < 0)
            hold = top->spf_max_delay;
        if ((TV_CMP (hold, delta)) < 0) {
            area->tv_spf_curr = top->spf_min_delay;
        }
    }
    /* If delay < start delay , delay for another start_delay period */
    if ((TV_CMP (top->spf_start_delay, delay)) > 0) {
        delay = top->spf_start_delay;
    }
    if ((TV_CMP (top->spf_max_delay, area->tv_spf_curr)) < 0) {
        /* Should not be more than max value */
        area->tv_spf_curr = top->spf_max_delay;
    }
    /* Now schedule SPF timer.  */
    OSPF_TV_TIMER_ON (area->t_spf_calc, ospf_spf_calculate_timer, area, delay);
}

Tv_spf:SPF计算完毕后更新此变量

Tv_spf_cur:SPF本次需要延迟的时间,初始值为spf_min_delay

spf_max_delay:SPF最大延迟时间,设定为50s

spf_min_delay:SPF最小延迟时间,设定为500ms

spf_start_delay:SPF开始的延迟时间,设定为spf_min_delay,即500ms

 

1) 获取当前的系统时间,并计算当前时间和上一次SPF计算完的差值delta

2) 判断delta和spf_cur的差值,如果delta大于spf_cur,进入到a流程,否则进入到b流程

a) 设置delay时间为0,并计算hold值,hold=2*spf_cur,hold最大不能超过spf_max_delay,同时比较hold和delta,如果hold比delta小(即当前需要spf计算的时间超过了2倍的记录的延迟时间)就把spf_cur重新设置为spf_min_delay【即认为不再震荡,重新恢复spf_cur为初始值】

b) 设置delay时间为spf_cur和delta的差值,即认为还没有到设置的延迟时间,需要继续延迟delay的时间再触发。并且,认为发生了震荡,将spf_cur的时间设置为当前的2倍。

3) 判断spf_start_delay和delay的差值,如果大于零,进入a流程,否则b

a) 设置delay为spf_start_delay,即至少要延迟spf_start_delay的时间。

b) 不做任何设置

4) 判断spf_cur是否超过spf_max_delay,如果超过,进入(a),如果不超过进入(b)

a) Spf_cur = spf_max_delay

b) 不做任何处理

5) 开启定时器,超时时间为delay。

 

根据以上流程,可以看出,如果不是频繁震荡,那么流程总是1->2(a)->3(a)->4(b)->5。这个时候,SPF计算总是在spf_min_delay时间后触发,即500ms。

如果频繁震荡,那么流程会进入1->2(b)->3(b)->4(b)->5,此时设置的定时器将会是一个spf_cur-delta的差值,并且由于spf_cur会被更新为当前的2倍,这个延迟将会越来越大,直至50s。

如果震荡中恢复到稳态,就进入1->2(a),此时又会把spf_cur更新为最小值。

通过以上分析,可以看出无论是否震荡,系统总是延迟spf_min_delay才进行SPF计算,那么当某次接口down,需要快速收敛时,将会有很大的延迟。因此可以把spf_min_delay设置为更小的值来提高收敛速度。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值