frr/bgpd/bgp_damp.c

661 lines
18 KiB
C
Raw Normal View History

2002-12-13 21:15:29 +01:00
/* BGP flap dampening
Copyright (C) 2001 IP Infusion Inc.
This file is part of GNU Zebra.
GNU Zebra is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
GNU Zebra is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Zebra; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include <zebra.h>
#include <math.h>
#include "prefix.h"
#include "memory.h"
#include "command.h"
#include "log.h"
#include "thread.h"
#include "queue.h"
2002-12-13 21:15:29 +01:00
#include "bgpd/bgpd.h"
#include "bgpd/bgp_damp.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_advertise.h"
/* Global variable to access damping configuration */
struct bgp_damp_config bgp_damp_cfg;
static struct bgp_damp_config *damp = &bgp_damp_cfg;
2002-12-13 21:15:29 +01:00
/* Utility macro to add and delete BGP dampening information to no
used list. */
#define BGP_DAMP_LIST_ADD(N,A) BGP_INFO_ADD(N,A,no_reuse_list)
#define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list)
2002-12-13 21:15:29 +01:00
/* Calculate reuse list index by penalty value. */
static int
bgp_reuse_index (int penalty)
{
unsigned int i;
2002-12-13 21:15:29 +01:00
int index;
i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor);
if ( i >= damp->reuse_index_size )
i = damp->reuse_index_size - 1;
index = damp->reuse_index[i] - damp->reuse_index[0];
return (damp->reuse_offset + index) % damp->reuse_list_size;
}
/* Add BGP dampening information to reuse list. */
static void
bgp_reuse_list_add (struct bgp_damp_info *bdi)
{
int index;
index = bdi->index = bgp_reuse_index (bdi->penalty);
bdi->prev = NULL;
bdi->next = damp->reuse_list[index];
if (damp->reuse_list[index])
damp->reuse_list[index]->prev = bdi;
damp->reuse_list[index] = bdi;
}
/* Delete BGP dampening information from reuse list. */
static void
bgp_reuse_list_delete (struct bgp_damp_info *bdi)
{
if (bdi->next)
bdi->next->prev = bdi->prev;
if (bdi->prev)
bdi->prev->next = bdi->next;
else
damp->reuse_list[bdi->index] = bdi->next;
}
2002-12-13 21:15:29 +01:00
/* Return decayed penalty value. */
int
bgp_damp_decay (time_t tdiff, int penalty)
{
unsigned int i;
2002-12-13 21:15:29 +01:00
i = (int) ((double) tdiff / DELTA_T);
if (i == 0)
return penalty;
if (i >= damp->decay_array_size)
return 0;
return (int) (penalty * damp->decay_array[i]);
}
/* Handler of reuse timer event. Each route in the current reuse-list
is evaluated. RFC2439 Section 4.8.7. */
static int
2002-12-13 21:15:29 +01:00
bgp_reuse_timer (struct thread *t)
{
struct bgp_damp_info *bdi;
struct bgp_damp_info *next;
time_t t_now, t_diff;
2002-12-13 21:15:29 +01:00
damp->t_reuse = NULL;
damp->t_reuse =
thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
t_now = bgp_clock ();
2002-12-13 21:15:29 +01:00
/* 1. save a pointer to the current zeroth queue head and zero the
list head entry. */
bdi = damp->reuse_list[damp->reuse_offset];
damp->reuse_list[damp->reuse_offset] = NULL;
/* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
rotating the circular queue of list-heads. */
damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
/* 3. if ( the saved list head pointer is non-empty ) */
for (; bdi; bdi = next)
{
struct bgp *bgp = bdi->binfo->peer->bgp;
2002-12-13 21:15:29 +01:00
next = bdi->next;
/* Set t-diff = t-now - t-updated. */
t_diff = t_now - bdi->t_updated;
/* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
/* Set t-updated = t-now. */
bdi->t_updated = t_now;
/* if (figure-of-merit < reuse). */
if (bdi->penalty < damp->reuse_limit)
{
/* Reuse the route. */
bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED);
2002-12-13 21:15:29 +01:00
bdi->suppress_time = 0;
if (bdi->lastrecord == BGP_RECORD_UPDATE)
{
bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY);
2002-12-13 21:15:29 +01:00
bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
bdi->afi, bdi->safi);
bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
}
if (bdi->penalty <= damp->reuse_limit / 2.0)
bgp_damp_info_free (bdi, 1);
else
BGP_DAMP_LIST_ADD (damp, bdi);
}
else
/* Re-insert into another list (See RFC2439 Section 4.8.6). */
bgp_reuse_list_add (bdi);
}
return 0;
}
/* A route becomes unreachable (RFC2439 Section 4.8.2). */
int
bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
afi_t afi, safi_t safi, int attr_change)
{
time_t t_now;
struct bgp_damp_info *bdi = NULL;
2002-12-13 21:15:29 +01:00
double last_penalty = 0;
t_now = bgp_clock ();
2002-12-13 21:15:29 +01:00
/* Processing Unreachable Messages. */
if (binfo->extra)
bdi = binfo->extra->damp_info;
2002-12-13 21:15:29 +01:00
if (bdi == NULL)
{
/* If there is no previous stability history. */
/* RFC2439 said:
1. allocate a damping structure.
2. set figure-of-merit = 1.
3. withdraw the route. */
bdi = XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
bdi->binfo = binfo;
bdi->rn = rn;
bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
bdi->flap = 1;
bdi->start_time = t_now;
bdi->suppress_time = 0;
bdi->index = -1;
bdi->afi = afi;
bdi->safi = safi;
(bgp_info_extra_get (binfo))->damp_info = bdi;
2002-12-13 21:15:29 +01:00
BGP_DAMP_LIST_ADD (damp, bdi);
}
else
{
last_penalty = bdi->penalty;
/* 1. Set t-diff = t-now - t-updated. */
bdi->penalty =
(bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty)
+ (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));
if (bdi->penalty > damp->ceiling)
bdi->penalty = damp->ceiling;
bdi->flap++;
}
assert ((rn == bdi->rn) && (binfo == bdi->binfo));
2002-12-13 21:15:29 +01:00
bdi->lastrecord = BGP_RECORD_WITHDRAW;
bdi->t_updated = t_now;
/* Make this route as historical status. */
bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY);
2002-12-13 21:15:29 +01:00
/* Remove the route from a reuse list if it is on one. */
if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
{
/* If decay rate isn't equal to 0, reinsert brn. */
if (bdi->penalty != last_penalty)
{
bgp_reuse_list_delete (bdi);
bgp_reuse_list_add (bdi);
}
return BGP_DAMP_SUPPRESSED;
}
/* If not suppressed before, do annonunce this withdraw and
insert into reuse_list. */
if (bdi->penalty >= damp->suppress_value)
{
bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED);
2002-12-13 21:15:29 +01:00
bdi->suppress_time = t_now;
BGP_DAMP_LIST_DEL (damp, bdi);
bgp_reuse_list_add (bdi);
}
return BGP_DAMP_USED;
}
int
bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
afi_t afi, safi_t safi)
{
time_t t_now;
struct bgp_damp_info *bdi;
int status;
if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
2002-12-13 21:15:29 +01:00
return BGP_DAMP_USED;
t_now = bgp_clock ();
bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);
2002-12-13 21:15:29 +01:00
bdi->lastrecord = BGP_RECORD_UPDATE;
bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);
if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
&& (bdi->penalty < damp->suppress_value))
status = BGP_DAMP_USED;
else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
&& (bdi->penalty < damp->reuse_limit) )
{
bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED);
2002-12-13 21:15:29 +01:00
bgp_reuse_list_delete (bdi);
BGP_DAMP_LIST_ADD (damp, bdi);
bdi->suppress_time = 0;
status = BGP_DAMP_USED;
}
else
status = BGP_DAMP_SUPPRESSED;
if (bdi->penalty > damp->reuse_limit / 2.0)
bdi->t_updated = t_now;
else
bgp_damp_info_free (bdi, 0);
return status;
}
/* Remove dampening information and history route. */
int
bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
{
time_t t_now, t_diff;
struct bgp_damp_info *bdi;
assert (binfo->extra && binfo->extra->damp_info);
t_now = bgp_clock ();
bdi = binfo->extra->damp_info;
2002-12-13 21:15:29 +01:00
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
{
t_diff = t_now - bdi->suppress_time;
if (t_diff >= damp->max_suppress_time)
{
bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED);
2002-12-13 21:15:29 +01:00
bgp_reuse_list_delete (bdi);
BGP_DAMP_LIST_ADD (damp, bdi);
bdi->penalty = damp->reuse_limit;
bdi->suppress_time = 0;
bdi->t_updated = t_now;
/* Need to announce UPDATE once this binfo is usable again. */
if (bdi->lastrecord == BGP_RECORD_UPDATE)
return 1;
else
return 0;
}
}
else
{
t_diff = t_now - bdi->t_updated;
bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
if (bdi->penalty <= damp->reuse_limit / 2.0)
{
/* release the bdi, bdi->binfo. */
bgp_damp_info_free (bdi, 1);
return 0;
}
else
bdi->t_updated = t_now;
}
return 0;
}
void
bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
{
struct bgp_info *binfo;
if (! bdi)
return;
binfo = bdi->binfo;
binfo->extra->damp_info = NULL;
2002-12-13 21:15:29 +01:00
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
bgp_reuse_list_delete (bdi);
else
BGP_DAMP_LIST_DEL (damp, bdi);
bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED);
2002-12-13 21:15:29 +01:00
if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
2005-06-01 Paul Jakma <paul.jakma@sun.com> * bgpd/(general) refcount struct peer and bgp_info, hence allowing us add work_queues for bgp_process. * bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount. Add bgp_info_{lock,unlock} helper functions. Add bgp_info_{add,delete} helpers, to remove need for users managing locking/freeing of bgp_info and bgp_node's. * bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of nodes. * bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock peer reference as appropriate. * bgpd/bgp_damp.c: Remove its internal prototypes for bgp_info_delete/free. Just use bgp_info_delete. * bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers. (struct peer) Add reference count 'lock' (peer_lock,peer_unlock) New helpers to take/release reference on struct peer. * bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting and balance how references are taken and released. (bgp_advertise_free) release bgp_info reference, if appropriate (bgp_adj_out_free) unlock peer (bgp_advertise_clean) leave the adv references alone, or else call bgp_advertise_free cant unlock them. (bgp_adj_out_set) lock the peer on new adj's, leave the reference alone otherwise. lock the new bgp_info reference. (bgp_adj_in_set) lock the peer reference (bgp_adj_in_remove) and unlock it here (bgp_sync_delete) make hash_free on peer conditional, just in case. * bgpd/bgp_fsm.c: (general) document that the timers depend on bgp_event to release a peer reference. (bgp_fsm_change_status) moved up the file, unchanged. (bgp_stop) Decrement peer lock as many times as cancel_event canceled - shouldnt be needed but just in case. stream_fifo_clean of obuf made conditional, just in case. (bgp_event) always unlock the peer, regardless of return value of bgp_fsm_change_status. * bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's. (bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs along with a comment on it. * bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup some of the resource management around bgp_info. Refcount peer. Add workqueues for bgp_process and clear_table. (bgp_info_new) make static (bgp_info_free) Ditto, and unlock the peer reference. (bgp_info_lock,bgp_info_unlock) new exported functions (bgp_info_add) Add a bgp_info to a bgp_node in correct fashion, taking care of reference counts. (bgp_info_delete) do the opposite of bgp_info_add. (bgp_process_rsclient) Converted into a work_queue work function. (bgp_process_main) ditto. (bgp_processq_del) process work queue item deconstructor (bgp_process_queue_init) process work queue init (bgp_process) call init function if required, set up queue item and add to queue, rather than calling process functions directly. (bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts (bgp_rib_withdraw) ditto (bgp_update_rsclient) let bgp_info_add manage refcounts (bgp_update_main) ditto (bgp_clear_route_node) clear_node_queue work function, does per-node aspects of what bgp_clear_route_table did previously (bgp_clear_node_queue_del) clear_node_queue item delete function (bgp_clear_node_complete) clear_node_queue completion function, it unplugs the process queues, which have to be blocked while clear_node_queue is being processed to prevent a race. (bgp_clear_node_queue_init) init function for clear_node_queue work queues (bgp_clear_route_table) Sets up items onto a workqueue now, rather than clearing each node directly. Plugs both process queues to avoid potential race. (bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage bgp_info refcounts. (bgp_static_update_rsclient) ditto (bgp_static_update_main) ditto (bgp_static_update_vpnv4) ditto, remove unneeded cast. (bgp_static_withdraw) see bgp_static_withdraw_rsclient (bgp_static_withdraw_vpnv4) ditto (bgp_aggregate_{route,add,delete}) ditto (bgp_redistribute_{add,delete,withdraw}) ditto * bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer reference (peer_rsclient_unset_vty) ditto, but unlock same reference * bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime of struct peer. (peer_lock,peer_unlock) peer refcount helpers (peer_new) add initial refcounts (peer_create,peer_create_accept) lock peer as appropriate (peer_delete) unlock as appropriate, move out some free's to peer_free. (peer_group_bind,peer_group_unbind) peer refcounting as appropriate. (bgp_create) check CALLOC return value. (bgp_terminate) free workqueues too. * lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
bgp_info_delete (bdi->rn, binfo);
2002-12-13 21:15:29 +01:00
XFREE (MTYPE_BGP_DAMP_INFO, bdi);
}
static void
2002-12-13 21:15:29 +01:00
bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
{
double reuse_max_ratio;
unsigned int i;
2002-12-13 21:15:29 +01:00
double j;
damp->suppress_value = sup;
damp->half_life = hlife;
damp->reuse_limit = reuse;
damp->max_suppress_time = maxsup;
/* Initialize params per bgp_damp_config. */
damp->reuse_index_size = REUSE_ARRAY_SIZE;
damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life)));
/* Decay-array computations */
damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T);
damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY,
sizeof(double) * (damp->decay_array_size));
damp->decay_array[0] = 1.0;
damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5));
/* Calculate decay values for all possible times */
for (i = 2; i < damp->decay_array_size; i++)
damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1];
/* Reuse-list computations */
i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1;
if (i > REUSE_LIST_SIZE || i == 0)
i = REUSE_LIST_SIZE;
damp->reuse_list_size = i;
damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
damp->reuse_list_size
* sizeof (struct bgp_reuse_node *));
/* Reuse-array computations */
damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
2002-12-13 21:15:29 +01:00
sizeof(int) * damp->reuse_index_size);
reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit;
j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0));
if ( reuse_max_ratio > j && j != 0 )
reuse_max_ratio = j;
damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1);
for (i = 0; i < damp->reuse_index_size; i++)
{
damp->reuse_index[i] =
(int)(((double)damp->half_life / DELTA_REUSE)
* log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5));
}
}
int
bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
unsigned int reuse, unsigned int suppress, time_t max)
2002-12-13 21:15:29 +01:00
{
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
{
if (damp->half_life == half
&& damp->reuse_limit == reuse
&& damp->suppress_value == suppress
&& damp->max_suppress_time == max)
return 0;
bgp_damp_disable (bgp, afi, safi);
}
SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
bgp_damp_parameter_set (half, reuse, suppress, max);
/* Register reuse timer. */
if (! damp->t_reuse)
damp->t_reuse =
thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
return 0;
}
static void
2002-12-13 21:15:29 +01:00
bgp_damp_config_clean (struct bgp_damp_config *damp)
{
/* Free decay array */
XFREE (MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
/* Free reuse index array */
XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
/* Free reuse list array. */
XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
}
/* Clean all the bgp_damp_info stored in reuse_list. */
void
bgp_damp_info_clean (void)
2002-12-13 21:15:29 +01:00
{
unsigned int i;
2002-12-13 21:15:29 +01:00
struct bgp_damp_info *bdi, *next;
damp->reuse_offset = 0;
for (i = 0; i < damp->reuse_list_size; i++)
{
if (! damp->reuse_list[i])
continue;
for (bdi = damp->reuse_list[i]; bdi; bdi = next)
{
next = bdi->next;
bgp_damp_info_free (bdi, 1);
}
damp->reuse_list[i] = NULL;
}
for (bdi = damp->no_reuse_list; bdi; bdi = next)
{
next = bdi->next;
bgp_damp_info_free (bdi, 1);
}
damp->no_reuse_list = NULL;
}
int
bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
{
/* If it wasn't enabled, there's nothing to do. */
if (! CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
return 0;
2002-12-13 21:15:29 +01:00
/* Cancel reuse thread. */
if (damp->t_reuse )
thread_cancel (damp->t_reuse);
damp->t_reuse = NULL;
/* Clean BGP dampening information. */
bgp_damp_info_clean ();
/* Clear configuration */
bgp_damp_config_clean (&bgp_damp_cfg);
UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
return 0;
}
void
2002-12-13 21:15:29 +01:00
bgp_config_write_damp (struct vty *vty)
{
if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60
&& bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
&& bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
&& bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
vty_out (vty, " bgp dampening%s", VTY_NEWLINE);
else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60
&& bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
&& bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
&& bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
vty_out (vty, " bgp dampening %ld%s",
bgp_damp_cfg.half_life/60,
VTY_NEWLINE);
else
vty_out (vty, " bgp dampening %ld %d %d %ld%s",
bgp_damp_cfg.half_life/60,
bgp_damp_cfg.reuse_limit,
bgp_damp_cfg.suppress_value,
bgp_damp_cfg.max_suppress_time/60,
VTY_NEWLINE);
2002-12-13 21:15:29 +01:00
}
static const char *
bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len)
2002-12-13 21:15:29 +01:00
{
time_t reuse_time = 0;
struct tm *tm = NULL;
if (penalty > damp->reuse_limit)
{
reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1]))));
if (reuse_time > damp->max_suppress_time)
reuse_time = damp->max_suppress_time;
tm = gmtime (&reuse_time);
}
else
reuse_time = 0;
/* Making formatted timer strings. */
#define ONE_DAY_SECOND 60*60*24
#define ONE_WEEK_SECOND 60*60*24*7
if (reuse_time == 0)
snprintf (buf, len, "00:00:00");
else if (reuse_time < ONE_DAY_SECOND)
snprintf (buf, len, "%02d:%02d:%02d",
tm->tm_hour, tm->tm_min, tm->tm_sec);
else if (reuse_time < ONE_WEEK_SECOND)
snprintf (buf, len, "%dd%02dh%02dm",
tm->tm_yday, tm->tm_hour, tm->tm_min);
else
snprintf (buf, len, "%02dw%dd%02dh",
tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
return buf;
}
void
bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
json_object *json_path)
2002-12-13 21:15:29 +01:00
{
struct bgp_damp_info *bdi;
time_t t_now, t_diff;
char timebuf[BGP_UPTIME_LEN];
int penalty;
if (!binfo->extra)
return;
2002-12-13 21:15:29 +01:00
/* BGP dampening information. */
bdi = binfo->extra->damp_info;
2002-12-13 21:15:29 +01:00
/* If dampening is not enabled or there is no dampening information,
return immediately. */
if (! damp || ! bdi)
return;
/* Calculate new penalty. */
t_now = bgp_clock ();
2002-12-13 21:15:29 +01:00
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay (t_diff, bdi->penalty);
if (json_path)
{
json_object_int_add(json_path, "dampeningPenalty", penalty);
json_object_int_add(json_path, "dampeningFlapCount", bdi->flap);
json_object_string_add(json_path, "dampeningFlapPeriod",
Key changes: - The aspath and community structures now have a json_object where we store the json representation. This is updated at the same time the "str" for aspath/community are updated. We do this so that we do not have to compute the json rep - Added a small wrappper to libjson0, the wrapper lives in quagga's lib/json.[ch]. - Added more structure to the json output. Sample output: show ip bgp summary json ------------------------ BGP router identifier 10.0.0.1, local AS number 10 BGP table version 2400 RIB entries 4799, using 562 KiB of memory Peers 17, using 284 KiB of memory Peer groups 4, using 224 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 1.1.1.1 4 10 0 0 0 0 0 never Active 10.0.0.2 4 10 104 7 0 0 0 00:02:29 600 10.0.0.3 4 10 104 7 0 0 0 00:02:29 600 10.0.0.4 4 10 204 7 0 0 0 00:02:29 1200 20.1.1.6 4 20 406 210 0 0 0 00:02:44 600 20.1.1.7 4 20 406 210 0 0 0 00:02:44 600 40.1.1.2 4 40 406 210 0 0 0 00:02:44 600 40.1.1.6 4 40 406 210 0 0 0 00:02:44 600 40.1.1.10 4 40 406 210 0 0 0 00:02:44 600 Total number of neighbors 9 { "as": 10, "dynamic-peers": 0, "peer-count": 17, "peer-group-count": 4, "peer-group-memory": 224, "peer-memory": 291312, "peers": { "1.1.1.1": { "inq": 0, "msgrcvd": 0, "msgsent": 0, "outq": 0, "prefix-advertised-count": 0, "prefix-received-count": 0, "remote-as": 10, "state": "Active", "table-version": 0, "uptime": "never", "version": 4 }, "10.0.0.2": { "hostname": "r2", "inq": 0, "msgrcvd": 104, "msgsent": 7, "outq": 0, "prefix-advertised-count": 1200, "prefix-received-count": 600, "remote-as": 10, "state": "Established", "table-version": 0, "uptime": "00:02:21", "version": 4 }, "10.0.0.3": { "hostname": "r3", "inq": 0, "msgrcvd": 104, "msgsent": 7, "outq": 0, "prefix-advertised-count": 1200, "prefix-received-count": 600, "remote-as": 10, "state": "Established", "table-version": 0, "uptime": "00:02:21", "version": 4 }, "10.0.0.4": { "hostname": "r4", "inq": 0, "msgrcvd": 204, "msgsent": 7, "outq": 0, "prefix-advertised-count": 1200, "prefix-received-count": 1200, "remote-as": 10, "state": "Established", "table-version": 0, "uptime": "00:02:21", "version": 4 }, "20.1.1.6": { "hostname": "r6", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 20, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "20.1.1.7": { "hostname": "r7", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 20, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "40.1.1.10": { "hostname": "r10", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 40, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "40.1.1.2": { "hostname": "r8", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 40, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "40.1.1.6": { "hostname": "r9", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 40, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 } }, "rib-count": 4799, "rib-memory": 575880, "router-id": "10.0.0.1", "table-version": 2400, "total-peers": 9 } show ip bgp json ---------------- *> 40.1.1.2 0 0 100 200 300 400 500 40 i * 40.3.88.0/24 40.1.1.6 0 0 100 200 300 400 500 40 i * 40.1.1.10 0 0 100 200 300 400 500 40 i *> 40.1.1.2 0 0 100 200 300 400 500 40 i * 40.3.89.0/24 40.1.1.6 0 0 100 200 300 400 500 40 i * 40.1.1.10 0 0 100 200 300 400 500 40 i *> 40.1.1.2 0 0 100 200 300 400 500 40 i "40.3.88.0/24": [ { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.6", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.10", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "bestpath": true, "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.2", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 } ], "40.3.89.0/24": [ { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.6", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.10", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "bestpath": true, "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.2", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 } ], show ip bgp x.x.x.x json ------------------------ BGP routing table entry for 40.3.86.0/24 Paths: (3 available, best #3, table Default-IP-Routing-Table) Advertised to non peer-group peers: 10.0.0.2 10.0.0.3 10.0.0.4 20.1.1.6 20.1.1.7 40.1.1.2 40.1.1.6 40.1.1.10 100 200 300 400 500 40 40.1.1.6 from 40.1.1.6 (40.0.0.9) Origin IGP, metric 0, localpref 100, valid, external Community: 1:1 2:2 3:3 4:4 10:10 20:20 Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66 Last update: Fri May 8 21:23:41 2015 100 200 300 400 500 40 40.1.1.10 from 40.1.1.10 (40.0.0.10) Origin IGP, metric 0, localpref 100, valid, external Community: 1:1 2:2 3:3 4:4 10:10 20:20 Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66 Last update: Fri May 8 21:23:41 2015 100 200 300 400 500 40 40.1.1.2 from 40.1.1.2 (40.0.0.8) Origin IGP, metric 0, localpref 100, valid, external, best Community: 1:1 2:2 3:3 4:4 10:10 20:20 Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66 Last update: Fri May 8 21:23:41 2015 { "advertised-to": { "10.0.0.2": { "hostname": "r2" }, "10.0.0.3": { "hostname": "r3" }, "10.0.0.4": { "hostname": "r4" }, "20.1.1.6": { "hostname": "r6" }, "20.1.1.7": { "hostname": "r7" }, "40.1.1.10": { "hostname": "r10" }, "40.1.1.2": { "hostname": "r8" }, "40.1.1.6": { "hostname": "r9" } }, "paths": [ { "aspath": { "length": 6, "segments": [ { "list": [ 100, 200, 300, 400, 500, 40 ], "type": "as-sequence" } ], "string": "100 200 300 400 500 40" }, "community": { "list": [ "1:1", "2:2", "3:3", "4:4", "10:10", "20:20" ], "string": "1:1 2:2 3:3 4:4 10:10 20:20" }, "extended-community": { "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66" }, "last-update": { "epoch": 1431120222, "string": "Fri May 8 21:23:42 2015\n" }, "localpref": 100, "med": 0, "nexthops": [ { "accessible": true, "afi": "ipv4", "ip": "40.1.1.6", "metric": 0, "used": true } ], "origin": "IGP", "peer": { "hostname": "r9", "peer-id": "40.1.1.6", "router-id": "40.0.0.9", "type": "external" }, "valid": true }, { "aspath": { "length": 6, "segments": [ { "list": [ 100, 200, 300, 400, 500, 40 ], "type": "as-sequence" } ], "string": "100 200 300 400 500 40" }, "community": { "list": [ "1:1", "2:2", "3:3", "4:4", "10:10", "20:20" ], "string": "1:1 2:2 3:3 4:4 10:10 20:20" }, "extended-community": { "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66" }, "last-update": { "epoch": 1431120222, "string": "Fri May 8 21:23:42 2015\n" }, "localpref": 100, "med": 0, "nexthops": [ { "accessible": true, "afi": "ipv4", "ip": "40.1.1.10", "metric": 0, "used": true } ], "origin": "IGP", "peer": { "hostname": "r10", "peer-id": "40.1.1.10", "router-id": "40.0.0.10", "type": "external" }, "valid": true }, { "aspath": { "length": 6, "segments": [ { "list": [ 100, 200, 300, 400, 500, 40 ], "type": "as-sequence" } ], "string": "100 200 300 400 500 40" }, "bestpath": { "overall": true }, "community": { "list": [ "1:1", "2:2", "3:3", "4:4", "10:10", "20:20" ], "string": "1:1 2:2 3:3 4:4 10:10 20:20" }, "extended-community": { "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66" }, "last-update": { "epoch": 1431120222, "string": "Fri May 8 21:23:42 2015\n" }, "localpref": 100, "med": 0, "nexthops": [ { "accessible": true, "afi": "ipv4", "ip": "40.1.1.2", "metric": 0, "used": true } ], "origin": "IGP", "peer": { "hostname": "r8", "peer-id": "40.1.1.2", "router-id": "40.0.0.8", "type": "external" }, "valid": true } ], "prefix": "40.3.86.0", "prefixlen": 24 }
2015-06-12 16:59:11 +02:00
peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
&& ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
{
json_object_string_add(json_path, "dampeningReuseIn",
Key changes: - The aspath and community structures now have a json_object where we store the json representation. This is updated at the same time the "str" for aspath/community are updated. We do this so that we do not have to compute the json rep - Added a small wrappper to libjson0, the wrapper lives in quagga's lib/json.[ch]. - Added more structure to the json output. Sample output: show ip bgp summary json ------------------------ BGP router identifier 10.0.0.1, local AS number 10 BGP table version 2400 RIB entries 4799, using 562 KiB of memory Peers 17, using 284 KiB of memory Peer groups 4, using 224 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 1.1.1.1 4 10 0 0 0 0 0 never Active 10.0.0.2 4 10 104 7 0 0 0 00:02:29 600 10.0.0.3 4 10 104 7 0 0 0 00:02:29 600 10.0.0.4 4 10 204 7 0 0 0 00:02:29 1200 20.1.1.6 4 20 406 210 0 0 0 00:02:44 600 20.1.1.7 4 20 406 210 0 0 0 00:02:44 600 40.1.1.2 4 40 406 210 0 0 0 00:02:44 600 40.1.1.6 4 40 406 210 0 0 0 00:02:44 600 40.1.1.10 4 40 406 210 0 0 0 00:02:44 600 Total number of neighbors 9 { "as": 10, "dynamic-peers": 0, "peer-count": 17, "peer-group-count": 4, "peer-group-memory": 224, "peer-memory": 291312, "peers": { "1.1.1.1": { "inq": 0, "msgrcvd": 0, "msgsent": 0, "outq": 0, "prefix-advertised-count": 0, "prefix-received-count": 0, "remote-as": 10, "state": "Active", "table-version": 0, "uptime": "never", "version": 4 }, "10.0.0.2": { "hostname": "r2", "inq": 0, "msgrcvd": 104, "msgsent": 7, "outq": 0, "prefix-advertised-count": 1200, "prefix-received-count": 600, "remote-as": 10, "state": "Established", "table-version": 0, "uptime": "00:02:21", "version": 4 }, "10.0.0.3": { "hostname": "r3", "inq": 0, "msgrcvd": 104, "msgsent": 7, "outq": 0, "prefix-advertised-count": 1200, "prefix-received-count": 600, "remote-as": 10, "state": "Established", "table-version": 0, "uptime": "00:02:21", "version": 4 }, "10.0.0.4": { "hostname": "r4", "inq": 0, "msgrcvd": 204, "msgsent": 7, "outq": 0, "prefix-advertised-count": 1200, "prefix-received-count": 1200, "remote-as": 10, "state": "Established", "table-version": 0, "uptime": "00:02:21", "version": 4 }, "20.1.1.6": { "hostname": "r6", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 20, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "20.1.1.7": { "hostname": "r7", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 20, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "40.1.1.10": { "hostname": "r10", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 40, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "40.1.1.2": { "hostname": "r8", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 40, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 }, "40.1.1.6": { "hostname": "r9", "inq": 0, "msgrcvd": 406, "msgsent": 210, "outq": 0, "prefix-advertised-count": 2400, "prefix-received-count": 600, "remote-as": 40, "state": "Established", "table-version": 0, "uptime": "00:02:36", "version": 4 } }, "rib-count": 4799, "rib-memory": 575880, "router-id": "10.0.0.1", "table-version": 2400, "total-peers": 9 } show ip bgp json ---------------- *> 40.1.1.2 0 0 100 200 300 400 500 40 i * 40.3.88.0/24 40.1.1.6 0 0 100 200 300 400 500 40 i * 40.1.1.10 0 0 100 200 300 400 500 40 i *> 40.1.1.2 0 0 100 200 300 400 500 40 i * 40.3.89.0/24 40.1.1.6 0 0 100 200 300 400 500 40 i * 40.1.1.10 0 0 100 200 300 400 500 40 i *> 40.1.1.2 0 0 100 200 300 400 500 40 i "40.3.88.0/24": [ { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.6", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.10", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "bestpath": true, "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.2", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 } ], "40.3.89.0/24": [ { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.6", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.10", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 }, { "aspath": "100 200 300 400 500 40", "bestpath": true, "med": 0, "nexthops": [ { "afi": "ipv4", "ip": "40.1.1.2", "used": true } ], "origin": "IGP", "path-from": "external", "valid": true, "weight": 0 } ], show ip bgp x.x.x.x json ------------------------ BGP routing table entry for 40.3.86.0/24 Paths: (3 available, best #3, table Default-IP-Routing-Table) Advertised to non peer-group peers: 10.0.0.2 10.0.0.3 10.0.0.4 20.1.1.6 20.1.1.7 40.1.1.2 40.1.1.6 40.1.1.10 100 200 300 400 500 40 40.1.1.6 from 40.1.1.6 (40.0.0.9) Origin IGP, metric 0, localpref 100, valid, external Community: 1:1 2:2 3:3 4:4 10:10 20:20 Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66 Last update: Fri May 8 21:23:41 2015 100 200 300 400 500 40 40.1.1.10 from 40.1.1.10 (40.0.0.10) Origin IGP, metric 0, localpref 100, valid, external Community: 1:1 2:2 3:3 4:4 10:10 20:20 Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66 Last update: Fri May 8 21:23:41 2015 100 200 300 400 500 40 40.1.1.2 from 40.1.1.2 (40.0.0.8) Origin IGP, metric 0, localpref 100, valid, external, best Community: 1:1 2:2 3:3 4:4 10:10 20:20 Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66 Last update: Fri May 8 21:23:41 2015 { "advertised-to": { "10.0.0.2": { "hostname": "r2" }, "10.0.0.3": { "hostname": "r3" }, "10.0.0.4": { "hostname": "r4" }, "20.1.1.6": { "hostname": "r6" }, "20.1.1.7": { "hostname": "r7" }, "40.1.1.10": { "hostname": "r10" }, "40.1.1.2": { "hostname": "r8" }, "40.1.1.6": { "hostname": "r9" } }, "paths": [ { "aspath": { "length": 6, "segments": [ { "list": [ 100, 200, 300, 400, 500, 40 ], "type": "as-sequence" } ], "string": "100 200 300 400 500 40" }, "community": { "list": [ "1:1", "2:2", "3:3", "4:4", "10:10", "20:20" ], "string": "1:1 2:2 3:3 4:4 10:10 20:20" }, "extended-community": { "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66" }, "last-update": { "epoch": 1431120222, "string": "Fri May 8 21:23:42 2015\n" }, "localpref": 100, "med": 0, "nexthops": [ { "accessible": true, "afi": "ipv4", "ip": "40.1.1.6", "metric": 0, "used": true } ], "origin": "IGP", "peer": { "hostname": "r9", "peer-id": "40.1.1.6", "router-id": "40.0.0.9", "type": "external" }, "valid": true }, { "aspath": { "length": 6, "segments": [ { "list": [ 100, 200, 300, 400, 500, 40 ], "type": "as-sequence" } ], "string": "100 200 300 400 500 40" }, "community": { "list": [ "1:1", "2:2", "3:3", "4:4", "10:10", "20:20" ], "string": "1:1 2:2 3:3 4:4 10:10 20:20" }, "extended-community": { "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66" }, "last-update": { "epoch": 1431120222, "string": "Fri May 8 21:23:42 2015\n" }, "localpref": 100, "med": 0, "nexthops": [ { "accessible": true, "afi": "ipv4", "ip": "40.1.1.10", "metric": 0, "used": true } ], "origin": "IGP", "peer": { "hostname": "r10", "peer-id": "40.1.1.10", "router-id": "40.0.0.10", "type": "external" }, "valid": true }, { "aspath": { "length": 6, "segments": [ { "list": [ 100, 200, 300, 400, 500, 40 ], "type": "as-sequence" } ], "string": "100 200 300 400 500 40" }, "bestpath": { "overall": true }, "community": { "list": [ "1:1", "2:2", "3:3", "4:4", "10:10", "20:20" ], "string": "1:1 2:2 3:3 4:4 10:10 20:20" }, "extended-community": { "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66" }, "last-update": { "epoch": 1431120222, "string": "Fri May 8 21:23:42 2015\n" }, "localpref": 100, "med": 0, "nexthops": [ { "accessible": true, "afi": "ipv4", "ip": "40.1.1.2", "metric": 0, "used": true } ], "origin": "IGP", "peer": { "hostname": "r8", "peer-id": "40.1.1.2", "router-id": "40.0.0.8", "type": "external" }, "valid": true } ], "prefix": "40.3.86.0", "prefixlen": 24 }
2015-06-12 16:59:11 +02:00
bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
}
}
else
{
vty_out (vty, " Dampinfo: penalty %d, flapped %d times in %s",
penalty, bdi->flap,
peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
2002-12-13 21:15:29 +01:00
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
&& ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, ", reuse in %s",
bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
2002-12-13 21:15:29 +01:00
vty_out (vty, "%s", VTY_NEWLINE);
}
2002-12-13 21:15:29 +01:00
}
const char *
bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
char *timebuf, size_t len)
2002-12-13 21:15:29 +01:00
{
struct bgp_damp_info *bdi;
time_t t_now, t_diff;
int penalty;
if (!binfo->extra)
return NULL;
2002-12-13 21:15:29 +01:00
/* BGP dampening information. */
bdi = binfo->extra->damp_info;
2002-12-13 21:15:29 +01:00
/* If dampening is not enabled or there is no dampening information,
return immediately. */
if (! damp || ! bdi)
return NULL;
/* Calculate new penalty. */
t_now = bgp_clock ();
2002-12-13 21:15:29 +01:00
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay (t_diff, bdi->penalty);
return bgp_get_reuse_time (penalty, timebuf, len);
2002-12-13 21:15:29 +01:00
}