File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_damp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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: #include "filter.h"
   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)
   46: 
   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: }   
   90: 
   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 =
  119:     thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);
  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 = 
  451:       thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);
  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: {
  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: 
  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)
  533:     vty_out (vty, " bgp dampening %lld%s",
  534: 	     bgp_damp_cfg.half_life/60LL,
  535: 	     VTY_NEWLINE);
  536:   else
  537:     vty_out (vty, " bgp dampening %lld %d %d %lld%s",
  538: 	     bgp_damp_cfg.half_life/60LL,
  539: 	     bgp_damp_cfg.reuse_limit,
  540: 	     bgp_damp_cfg.suppress_value,
  541: 	     bgp_damp_cfg.max_suppress_time/60LL,
  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);
  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;
  675: }

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