Annotation of embedaddon/quagga/bgpd/bgp_damp.c, revision 1.1.1.2

1.1       misho       1: /* BGP flap dampening
                      2:    Copyright (C) 2001 IP Infusion Inc.
                      3: 
                      4: This file is part of GNU Zebra.
                      5: 
                      6: GNU Zebra is free software; you can redistribute it and/or modify it
                      7: under the terms of the GNU General Public License as published by the
                      8: Free Software Foundation; either version 2, or (at your option) any
                      9: later version.
                     10: 
                     11: GNU Zebra is distributed in the hope that it will be useful, but
                     12: WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14: General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     19: 02111-1307, USA.  */
                     20: 
                     21: #include <zebra.h>
                     22: #include <math.h>
                     23: 
                     24: #include "prefix.h"
                     25: #include "memory.h"
                     26: #include "command.h"
                     27: #include "log.h"
                     28: #include "thread.h"
                     29: 
                     30: #include "bgpd/bgpd.h"
                     31: #include "bgpd/bgp_damp.h"
                     32: #include "bgpd/bgp_table.h"
                     33: #include "bgpd/bgp_route.h"
                     34: #include "bgpd/bgp_attr.h" 
                     35: #include "bgpd/bgp_advertise.h"
                     36: 
                     37: /* Global variable to access damping configuration */
                     38: struct bgp_damp_config bgp_damp_cfg;
                     39: static struct bgp_damp_config *damp = &bgp_damp_cfg;
                     40: 
                     41: /* Utility macro to add and delete BGP dampening information to no
                     42:    used list.  */
                     43: #define BGP_DAMP_LIST_ADD(N,A)  BGP_INFO_ADD(N,A,no_reuse_list)
                     44: #define BGP_DAMP_LIST_DEL(N,A)  BGP_INFO_DEL(N,A,no_reuse_list)
                     45: 
                     46: /* Calculate reuse list index by penalty value.  */
                     47: static int
                     48: bgp_reuse_index (int penalty)
                     49: {
                     50:   unsigned int i;
                     51:   int index;
                     52: 
                     53:   i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor);
                     54:   
                     55:   if ( i >= damp->reuse_index_size )
                     56:     i = damp->reuse_index_size - 1;
                     57: 
                     58:   index = damp->reuse_index[i] - damp->reuse_index[0];
                     59: 
                     60:   return (damp->reuse_offset + index) % damp->reuse_list_size;  
                     61: }
                     62: 
                     63: /* Add BGP dampening information to reuse list.  */
                     64: static void 
                     65: bgp_reuse_list_add (struct bgp_damp_info *bdi)
                     66: {
                     67:   int index;
                     68: 
                     69:   index = bdi->index = bgp_reuse_index (bdi->penalty);
                     70: 
                     71:   bdi->prev = NULL;
                     72:   bdi->next = damp->reuse_list[index];
                     73:   if (damp->reuse_list[index])
                     74:     damp->reuse_list[index]->prev = bdi;
                     75:   damp->reuse_list[index] = bdi;
                     76: }
                     77: 
                     78: /* Delete BGP dampening information from reuse list.  */
                     79: static void
                     80: bgp_reuse_list_delete (struct bgp_damp_info *bdi)
                     81: {
                     82:   if (bdi->next)
                     83:     bdi->next->prev = bdi->prev;
                     84:   if (bdi->prev)
                     85:     bdi->prev->next = bdi->next;
                     86:   else
                     87:     damp->reuse_list[bdi->index] = bdi->next;
                     88: }   
                     89: 
                     90: /* Return decayed penalty value.  */
                     91: int 
                     92: bgp_damp_decay (time_t tdiff, int penalty)
                     93: {
                     94:   unsigned int i;
                     95: 
                     96:   i = (int) ((double) tdiff / DELTA_T);
                     97: 
                     98:   if (i == 0)
                     99:     return penalty; 
                    100:   
                    101:   if (i >= damp->decay_array_size)
                    102:     return 0;
                    103: 
                    104:   return (int) (penalty * damp->decay_array[i]);
                    105: }
                    106: 
                    107: /* Handler of reuse timer event.  Each route in the current reuse-list
                    108:    is evaluated.  RFC2439 Section 4.8.7.  */
                    109: static int
                    110: bgp_reuse_timer (struct thread *t)
                    111: {
                    112:   struct bgp_damp_info *bdi;
                    113:   struct bgp_damp_info *next;
                    114:   time_t t_now, t_diff;
                    115:     
                    116:   damp->t_reuse = NULL;
                    117:   damp->t_reuse =
                    118:     thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
                    119: 
                    120:   t_now = bgp_clock ();
                    121: 
                    122:   /* 1.  save a pointer to the current zeroth queue head and zero the
                    123:      list head entry.  */
                    124:   bdi = damp->reuse_list[damp->reuse_offset];
                    125:   damp->reuse_list[damp->reuse_offset] = NULL;
                    126: 
                    127:   /* 2.  set offset = modulo reuse-list-size ( offset + 1 ), thereby
                    128:      rotating the circular queue of list-heads.  */
                    129:   damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
                    130: 
                    131:   /* 3. if ( the saved list head pointer is non-empty ) */
                    132:   for (; bdi; bdi = next)
                    133:     {
                    134:       struct bgp *bgp = bdi->binfo->peer->bgp;
                    135:       
                    136:       next = bdi->next;
                    137: 
                    138:       /* Set t-diff = t-now - t-updated.  */
                    139:       t_diff = t_now - bdi->t_updated;
                    140: 
                    141:       /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
                    142:       bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);   
                    143: 
                    144:       /* Set t-updated = t-now.  */
                    145:       bdi->t_updated = t_now;
                    146: 
                    147:       /* if (figure-of-merit < reuse).  */
                    148:       if (bdi->penalty < damp->reuse_limit)
                    149:        {
                    150:          /* Reuse the route.  */
                    151:          bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED);
                    152:          bdi->suppress_time = 0;
                    153: 
                    154:          if (bdi->lastrecord == BGP_RECORD_UPDATE)
                    155:            {
                    156:              bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY);
                    157:              bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
                    158:                                       bdi->afi, bdi->safi);   
                    159:              bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
                    160:            }
                    161: 
                    162:          if (bdi->penalty <= damp->reuse_limit / 2.0)
                    163:            bgp_damp_info_free (bdi, 1);
                    164:          else
                    165:            BGP_DAMP_LIST_ADD (damp, bdi);
                    166:        }
                    167:       else
                    168:        /* Re-insert into another list (See RFC2439 Section 4.8.6).  */
                    169:        bgp_reuse_list_add (bdi);
                    170:     }
                    171: 
                    172:   return 0;
                    173: }
                    174: 
                    175: /* A route becomes unreachable (RFC2439 Section 4.8.2).  */
                    176: int
                    177: bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
                    178:                   afi_t afi, safi_t safi, int attr_change)
                    179: {
                    180:   time_t t_now;
                    181:   struct bgp_damp_info *bdi = NULL;
                    182:   double last_penalty = 0;
                    183:   
                    184:   t_now = bgp_clock ();
                    185: 
                    186:   /* Processing Unreachable Messages.  */
                    187:   if (binfo->extra)
                    188:     bdi = binfo->extra->damp_info;
                    189:   
                    190:   if (bdi == NULL)
                    191:     {
                    192:       /* If there is no previous stability history. */
                    193: 
                    194:       /* RFC2439 said:
                    195:         1. allocate a damping structure.
                    196:          2. set figure-of-merit = 1.
                    197:          3. withdraw the route.  */
                    198: 
                    199:       bdi =  XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
                    200:       bdi->binfo = binfo;
                    201:       bdi->rn = rn;
                    202:       bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
                    203:       bdi->flap = 1;
                    204:       bdi->start_time = t_now;
                    205:       bdi->suppress_time = 0;
                    206:       bdi->index = -1;
                    207:       bdi->afi = afi;
                    208:       bdi->safi = safi;
                    209:       (bgp_info_extra_get (binfo))->damp_info = bdi;
                    210:       BGP_DAMP_LIST_ADD (damp, bdi);
                    211:     }
                    212:   else
                    213:     {
                    214:       last_penalty = bdi->penalty;
                    215: 
                    216:       /* 1. Set t-diff = t-now - t-updated.  */
                    217:       bdi->penalty = 
                    218:        (bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty) 
                    219:         + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));
                    220: 
                    221:       if (bdi->penalty > damp->ceiling)
                    222:        bdi->penalty = damp->ceiling;
                    223: 
                    224:       bdi->flap++;
                    225:     }
                    226:   
                    227:   assert ((rn == bdi->rn) && (binfo == bdi->binfo));
                    228:   
                    229:   bdi->lastrecord = BGP_RECORD_WITHDRAW;
                    230:   bdi->t_updated = t_now;
                    231: 
                    232:   /* Make this route as historical status.  */
                    233:   bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY);
                    234: 
                    235:   /* Remove the route from a reuse list if it is on one.  */
                    236:   if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
                    237:     {
                    238:       /* If decay rate isn't equal to 0, reinsert brn. */  
                    239:       if (bdi->penalty != last_penalty)
                    240:        {
                    241:          bgp_reuse_list_delete (bdi);
                    242:          bgp_reuse_list_add (bdi);  
                    243:        }
                    244:       return BGP_DAMP_SUPPRESSED; 
                    245:     }
                    246: 
                    247:   /* If not suppressed before, do annonunce this withdraw and
                    248:      insert into reuse_list.  */
                    249:   if (bdi->penalty >= damp->suppress_value)
                    250:     {
                    251:       bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED);
                    252:       bdi->suppress_time = t_now;
                    253:       BGP_DAMP_LIST_DEL (damp, bdi);
                    254:       bgp_reuse_list_add (bdi);
                    255:     }
                    256: 
                    257:   return BGP_DAMP_USED;
                    258: }
                    259: 
                    260: int
                    261: bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, 
                    262:                 afi_t afi, safi_t safi)
                    263: {
                    264:   time_t t_now;
                    265:   struct bgp_damp_info *bdi;
                    266:   int status;
                    267: 
                    268:   if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
                    269:     return BGP_DAMP_USED;
                    270: 
                    271:   t_now = bgp_clock ();
                    272:   bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);
                    273: 
                    274:   bdi->lastrecord = BGP_RECORD_UPDATE;
                    275:   bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);
                    276: 
                    277:   if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
                    278:       && (bdi->penalty < damp->suppress_value))
                    279:     status = BGP_DAMP_USED;
                    280:   else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
                    281:           && (bdi->penalty < damp->reuse_limit) )
                    282:     {
                    283:       bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED);
                    284:       bgp_reuse_list_delete (bdi);
                    285:       BGP_DAMP_LIST_ADD (damp, bdi);
                    286:       bdi->suppress_time = 0;
                    287:       status = BGP_DAMP_USED;
                    288:     }
                    289:   else
                    290:     status = BGP_DAMP_SUPPRESSED;  
                    291: 
                    292:   if (bdi->penalty > damp->reuse_limit / 2.0)
                    293:     bdi->t_updated = t_now;
                    294:   else
                    295:     bgp_damp_info_free (bdi, 0);
                    296:        
                    297:   return status;
                    298: }
                    299: 
                    300: /* Remove dampening information and history route.  */
                    301: int 
                    302: bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
                    303: {
                    304:   time_t t_now, t_diff;
                    305:   struct bgp_damp_info *bdi;
                    306:   
                    307:   assert (binfo->extra && binfo->extra->damp_info);
                    308:   
                    309:   t_now = bgp_clock ();
                    310:   bdi = binfo->extra->damp_info;
                    311:  
                    312:   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
                    313:     {
                    314:       t_diff = t_now - bdi->suppress_time;
                    315: 
                    316:       if (t_diff >= damp->max_suppress_time)
                    317:         {
                    318:           bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED);
                    319:           bgp_reuse_list_delete (bdi);
                    320:          BGP_DAMP_LIST_ADD (damp, bdi);
                    321:           bdi->penalty = damp->reuse_limit;
                    322:           bdi->suppress_time = 0;
                    323:           bdi->t_updated = t_now;
                    324:           
                    325:           /* Need to announce UPDATE once this binfo is usable again. */
                    326:           if (bdi->lastrecord == BGP_RECORD_UPDATE)
                    327:             return 1;
                    328:           else
                    329:             return 0;
                    330:         }
                    331:     }
                    332:   else
                    333:     {
                    334:       t_diff = t_now - bdi->t_updated;
                    335:       bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
                    336: 
                    337:       if (bdi->penalty <= damp->reuse_limit / 2.0)
                    338:         {
                    339:           /* release the bdi, bdi->binfo. */  
                    340:           bgp_damp_info_free (bdi, 1);
                    341:           return 0;
                    342:         }            
                    343:       else
                    344:         bdi->t_updated = t_now;
                    345:     }       
                    346:   return 0;
                    347: }
                    348: 
                    349: void
                    350: bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
                    351: {
                    352:   struct bgp_info *binfo;
                    353: 
                    354:   if (! bdi)
                    355:     return;
                    356: 
                    357:   binfo = bdi->binfo;
                    358:   binfo->extra->damp_info = NULL;
                    359: 
                    360:   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
                    361:     bgp_reuse_list_delete (bdi);
                    362:   else
                    363:     BGP_DAMP_LIST_DEL (damp, bdi);
                    364: 
                    365:   bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED);
                    366: 
                    367:   if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
                    368:     bgp_info_delete (bdi->rn, binfo);
                    369:   
                    370:   XFREE (MTYPE_BGP_DAMP_INFO, bdi);
                    371: }
                    372: 
                    373: static void
                    374: bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
                    375: {
                    376:   double reuse_max_ratio;
                    377:   unsigned int i;
                    378:   double j;
                    379:        
                    380:   damp->suppress_value = sup;
                    381:   damp->half_life = hlife;
                    382:   damp->reuse_limit = reuse;
                    383:   damp->max_suppress_time = maxsup;
                    384: 
                    385:   /* Initialize params per bgp_damp_config. */
                    386:   damp->reuse_index_size = REUSE_ARRAY_SIZE;
                    387: 
                    388:   damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life))); 
                    389: 
                    390:   /* Decay-array computations */
                    391:   damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T);
                    392:   damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY,
                    393:                               sizeof(double) * (damp->decay_array_size));
                    394:   damp->decay_array[0] = 1.0;
                    395:   damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5));
                    396: 
                    397:   /* Calculate decay values for all possible times */
                    398:   for (i = 2; i < damp->decay_array_size; i++)
                    399:     damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1];
                    400:        
                    401:   /* Reuse-list computations */
                    402:   i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1;
                    403:   if (i > REUSE_LIST_SIZE || i == 0)
                    404:     i = REUSE_LIST_SIZE;
                    405:   damp->reuse_list_size = i; 
                    406: 
                    407:   damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY, 
                    408:                              damp->reuse_list_size 
                    409:                              * sizeof (struct bgp_reuse_node *));
                    410: 
                    411:   /* Reuse-array computations */
                    412:   damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
                    413:                               sizeof(int) * damp->reuse_index_size);
                    414: 
                    415:   reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit;
                    416:   j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0));
                    417:   if ( reuse_max_ratio > j && j != 0 )
                    418:     reuse_max_ratio = j;
                    419: 
                    420:   damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1);
                    421: 
                    422:   for (i = 0; i < damp->reuse_index_size; i++)
                    423:     {
                    424:       damp->reuse_index[i] = 
                    425:        (int)(((double)damp->half_life / DELTA_REUSE)
                    426:              * log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5));
                    427:     }
                    428: }
                    429: 
                    430: int
                    431: bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
                    432:                 unsigned int reuse, unsigned int suppress, time_t max)
                    433: {
                    434:   if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
                    435:     {
                    436:       if (damp->half_life == half
                    437:          && damp->reuse_limit == reuse
                    438:          && damp->suppress_value == suppress
                    439:          && damp->max_suppress_time == max)
                    440:        return 0;
                    441:       bgp_damp_disable (bgp, afi, safi);
                    442:     }
                    443: 
                    444:   SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
                    445:   bgp_damp_parameter_set (half, reuse, suppress, max);
                    446: 
                    447:   /* Register reuse timer.  */
                    448:   if (! damp->t_reuse)
                    449:     damp->t_reuse = 
                    450:       thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
                    451: 
                    452:   return 0;
                    453: }
                    454: 
                    455: static void
                    456: bgp_damp_config_clean (struct bgp_damp_config *damp)
                    457: {
                    458:   /* Free decay array */
                    459:   XFREE (MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
                    460: 
                    461:   /* Free reuse index array */
                    462:   XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
                    463: 
                    464:   /* Free reuse list array. */
                    465:   XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
                    466: }
                    467: 
                    468: /* Clean all the bgp_damp_info stored in reuse_list. */
                    469: void
                    470: bgp_damp_info_clean (void)
                    471: {
                    472:   unsigned int i;
                    473:   struct bgp_damp_info *bdi, *next;
                    474: 
                    475:   damp->reuse_offset = 0;
                    476: 
                    477:   for (i = 0; i < damp->reuse_list_size; i++)
                    478:     {
                    479:       if (! damp->reuse_list[i])
                    480:        continue;
                    481: 
                    482:       for (bdi = damp->reuse_list[i]; bdi; bdi = next)
                    483:        {
                    484:          next = bdi->next;
                    485:          bgp_damp_info_free (bdi, 1);
                    486:        }
                    487:       damp->reuse_list[i] = NULL;
                    488:     }
                    489: 
                    490:   for (bdi = damp->no_reuse_list; bdi; bdi = next)
                    491:     {
                    492:       next = bdi->next;
                    493:       bgp_damp_info_free (bdi, 1);
                    494:     }
                    495:   damp->no_reuse_list = NULL;
                    496: }
                    497: 
                    498: int
                    499: bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
                    500: {
1.1.1.2 ! misho     501:   /* If it wasn't enabled, there's nothing to do. */
        !           502:   if (! CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
        !           503:     return 0;
        !           504: 
1.1       misho     505:   /* Cancel reuse thread. */
                    506:   if (damp->t_reuse )
                    507:     thread_cancel (damp->t_reuse);
                    508:   damp->t_reuse = NULL;
                    509: 
                    510:   /* Clean BGP dampening information.  */
                    511:   bgp_damp_info_clean ();
                    512: 
                    513:   /* Clear configuration */
                    514:   bgp_damp_config_clean (&bgp_damp_cfg);
                    515: 
                    516:   UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
                    517:   return 0;
                    518: }
                    519: 
                    520: void
                    521: bgp_config_write_damp (struct vty *vty)
                    522: {
                    523:   if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60
                    524:       && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
                    525:       && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
                    526:       && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
                    527:     vty_out (vty, " bgp dampening%s", VTY_NEWLINE);
                    528:   else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60
                    529:           && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
                    530:           && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
                    531:           && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
                    532:     vty_out (vty, " bgp dampening %ld%s",
                    533:             bgp_damp_cfg.half_life/60,
                    534:             VTY_NEWLINE);
                    535:   else
                    536:     vty_out (vty, " bgp dampening %ld %d %d %ld%s",
                    537:             bgp_damp_cfg.half_life/60,
                    538:             bgp_damp_cfg.reuse_limit,
                    539:             bgp_damp_cfg.suppress_value,
                    540:             bgp_damp_cfg.max_suppress_time/60,
                    541:             VTY_NEWLINE);
                    542: }
                    543: 
                    544: static const char *
                    545: bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len)
                    546: {
                    547:   time_t reuse_time = 0;
                    548:   struct tm *tm = NULL;
                    549: 
                    550:   if (penalty > damp->reuse_limit)
                    551:     {
                    552:       reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1])))); 
                    553: 
                    554:       if (reuse_time > damp->max_suppress_time)
                    555:        reuse_time = damp->max_suppress_time;
                    556: 
                    557:       tm = gmtime (&reuse_time);
                    558:     }
                    559:   else 
                    560:     reuse_time = 0;
                    561: 
                    562:   /* Making formatted timer strings. */
                    563: #define ONE_DAY_SECOND 60*60*24
                    564: #define ONE_WEEK_SECOND 60*60*24*7
                    565:   if (reuse_time == 0)
                    566:     snprintf (buf, len, "00:00:00");
                    567:   else if (reuse_time < ONE_DAY_SECOND)
                    568:     snprintf (buf, len, "%02d:%02d:%02d", 
                    569:               tm->tm_hour, tm->tm_min, tm->tm_sec);
                    570:   else if (reuse_time < ONE_WEEK_SECOND)
                    571:     snprintf (buf, len, "%dd%02dh%02dm", 
                    572:               tm->tm_yday, tm->tm_hour, tm->tm_min);
                    573:   else
                    574:     snprintf (buf, len, "%02dw%dd%02dh", 
                    575:               tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); 
                    576: 
                    577:   return buf;
                    578: }
                    579:  
                    580: void
                    581: bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)  
                    582: {
                    583:   struct bgp_damp_info *bdi;
                    584:   time_t t_now, t_diff;
                    585:   char timebuf[BGP_UPTIME_LEN];
                    586:   int penalty;
                    587: 
                    588:   if (!binfo->extra)
                    589:     return;
                    590:   
                    591:   /* BGP dampening information.  */
                    592:   bdi = binfo->extra->damp_info;
                    593: 
                    594:   /* If dampening is not enabled or there is no dampening information,
                    595:      return immediately.  */
                    596:   if (! damp || ! bdi)
                    597:     return;
                    598: 
                    599:   /* Calculate new penalty.  */
                    600:   t_now = bgp_clock ();
                    601:   t_diff = t_now - bdi->t_updated;
                    602:   penalty = bgp_damp_decay (t_diff, bdi->penalty);
                    603: 
                    604:   vty_out (vty, "      Dampinfo: penalty %d, flapped %d times in %s",
                    605:            penalty, bdi->flap,
                    606:           peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
                    607: 
                    608:   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
                    609:       && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
                    610:     vty_out (vty, ", reuse in %s",
                    611:             bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
                    612: 
                    613:   vty_out (vty, "%s", VTY_NEWLINE);
                    614: }
                    615: 
                    616: const char *
                    617: bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
                    618:                          char *timebuf, size_t len)
                    619: {
                    620:   struct bgp_damp_info *bdi;
                    621:   time_t t_now, t_diff;
                    622:   int penalty;
                    623:   
                    624:   if (!binfo->extra)
                    625:     return NULL;
                    626:   
                    627:   /* BGP dampening information.  */
                    628:   bdi = binfo->extra->damp_info;
                    629: 
                    630:   /* If dampening is not enabled or there is no dampening information,
                    631:      return immediately.  */
                    632:   if (! damp || ! bdi)
                    633:     return NULL;
                    634: 
                    635:   /* Calculate new penalty.  */
                    636:   t_now = bgp_clock ();
                    637:   t_diff = t_now - bdi->t_updated;
                    638:   penalty = bgp_damp_decay (t_diff, bdi->penalty);
                    639: 
                    640:   return  bgp_get_reuse_time (penalty, timebuf, len);
                    641: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>