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

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

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