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

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: {
        !           501:   /* Cancel reuse thread. */
        !           502:   if (damp->t_reuse )
        !           503:     thread_cancel (damp->t_reuse);
        !           504:   damp->t_reuse = NULL;
        !           505: 
        !           506:   /* Clean BGP dampening information.  */
        !           507:   bgp_damp_info_clean ();
        !           508: 
        !           509:   /* Clear configuration */
        !           510:   bgp_damp_config_clean (&bgp_damp_cfg);
        !           511: 
        !           512:   UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
        !           513:   return 0;
        !           514: }
        !           515: 
        !           516: void
        !           517: bgp_config_write_damp (struct vty *vty)
        !           518: {
        !           519:   if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60
        !           520:       && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
        !           521:       && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
        !           522:       && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
        !           523:     vty_out (vty, " bgp dampening%s", VTY_NEWLINE);
        !           524:   else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60
        !           525:           && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
        !           526:           && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
        !           527:           && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
        !           528:     vty_out (vty, " bgp dampening %ld%s",
        !           529:             bgp_damp_cfg.half_life/60,
        !           530:             VTY_NEWLINE);
        !           531:   else
        !           532:     vty_out (vty, " bgp dampening %ld %d %d %ld%s",
        !           533:             bgp_damp_cfg.half_life/60,
        !           534:             bgp_damp_cfg.reuse_limit,
        !           535:             bgp_damp_cfg.suppress_value,
        !           536:             bgp_damp_cfg.max_suppress_time/60,
        !           537:             VTY_NEWLINE);
        !           538: }
        !           539: 
        !           540: static const char *
        !           541: bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len)
        !           542: {
        !           543:   time_t reuse_time = 0;
        !           544:   struct tm *tm = NULL;
        !           545: 
        !           546:   if (penalty > damp->reuse_limit)
        !           547:     {
        !           548:       reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1])))); 
        !           549: 
        !           550:       if (reuse_time > damp->max_suppress_time)
        !           551:        reuse_time = damp->max_suppress_time;
        !           552: 
        !           553:       tm = gmtime (&reuse_time);
        !           554:     }
        !           555:   else 
        !           556:     reuse_time = 0;
        !           557: 
        !           558:   /* Making formatted timer strings. */
        !           559: #define ONE_DAY_SECOND 60*60*24
        !           560: #define ONE_WEEK_SECOND 60*60*24*7
        !           561:   if (reuse_time == 0)
        !           562:     snprintf (buf, len, "00:00:00");
        !           563:   else if (reuse_time < ONE_DAY_SECOND)
        !           564:     snprintf (buf, len, "%02d:%02d:%02d", 
        !           565:               tm->tm_hour, tm->tm_min, tm->tm_sec);
        !           566:   else if (reuse_time < ONE_WEEK_SECOND)
        !           567:     snprintf (buf, len, "%dd%02dh%02dm", 
        !           568:               tm->tm_yday, tm->tm_hour, tm->tm_min);
        !           569:   else
        !           570:     snprintf (buf, len, "%02dw%dd%02dh", 
        !           571:               tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); 
        !           572: 
        !           573:   return buf;
        !           574: }
        !           575:  
        !           576: void
        !           577: bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)  
        !           578: {
        !           579:   struct bgp_damp_info *bdi;
        !           580:   time_t t_now, t_diff;
        !           581:   char timebuf[BGP_UPTIME_LEN];
        !           582:   int penalty;
        !           583: 
        !           584:   if (!binfo->extra)
        !           585:     return;
        !           586:   
        !           587:   /* BGP dampening information.  */
        !           588:   bdi = binfo->extra->damp_info;
        !           589: 
        !           590:   /* If dampening is not enabled or there is no dampening information,
        !           591:      return immediately.  */
        !           592:   if (! damp || ! bdi)
        !           593:     return;
        !           594: 
        !           595:   /* Calculate new penalty.  */
        !           596:   t_now = bgp_clock ();
        !           597:   t_diff = t_now - bdi->t_updated;
        !           598:   penalty = bgp_damp_decay (t_diff, bdi->penalty);
        !           599: 
        !           600:   vty_out (vty, "      Dampinfo: penalty %d, flapped %d times in %s",
        !           601:            penalty, bdi->flap,
        !           602:           peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
        !           603: 
        !           604:   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
        !           605:       && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
        !           606:     vty_out (vty, ", reuse in %s",
        !           607:             bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
        !           608: 
        !           609:   vty_out (vty, "%s", VTY_NEWLINE);
        !           610: }
        !           611: 
        !           612: const char *
        !           613: bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
        !           614:                          char *timebuf, size_t len)
        !           615: {
        !           616:   struct bgp_damp_info *bdi;
        !           617:   time_t t_now, t_diff;
        !           618:   int penalty;
        !           619:   
        !           620:   if (!binfo->extra)
        !           621:     return NULL;
        !           622:   
        !           623:   /* BGP dampening information.  */
        !           624:   bdi = binfo->extra->damp_info;
        !           625: 
        !           626:   /* If dampening is not enabled or there is no dampening information,
        !           627:      return immediately.  */
        !           628:   if (! damp || ! bdi)
        !           629:     return NULL;
        !           630: 
        !           631:   /* Calculate new penalty.  */
        !           632:   t_now = bgp_clock ();
        !           633:   t_diff = t_now - bdi->t_updated;
        !           634:   penalty = bgp_damp_decay (t_diff, bdi->penalty);
        !           635: 
        !           636:   return  bgp_get_reuse_time (penalty, timebuf, len);
        !           637: }

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