File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_damp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_20_1, v0_99_20, HEAD
quagga

    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>