📄 bgp_damp.c
字号:
/* 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 itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING. If not, write to the FreeSoftware Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. */#include <zebra.h>#include <math.h>#include "prefix.h"#include "memory.h"#include "command.h"#include "log.h"#include "thread.h"#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;struct bgp_damp_config *damp = &bgp_damp_cfg;/* 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)/* Calculate reuse list index by penalty value. */static intbgp_reuse_index (int penalty){ int i; 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 voidbgp_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;} /* Return decayed penalty value. */int bgp_damp_decay (time_t tdiff, int penalty){ int i; 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. */intbgp_reuse_timer (struct thread *t){ struct bgp_damp_info *bdi; struct bgp_damp_info *next; time_t t_now, t_diff; struct bgp *bgp; int bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t); damp->t_reuse = NULL; damp->t_reuse = thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE); bgp = bgp_get_default (); if (! bgp) return 0; t_now = time (NULL); /* 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) { 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. */ UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED); bdi->suppress_time = 0; if (bdi->lastrecord == BGP_RECORD_UPDATE) { UNSET_FLAG (bdi->binfo->flags, BGP_INFO_HISTORY); 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). */intbgp_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; double last_penalty = 0; t_now = time (NULL); /* Processing Unreachable Messages. */ bdi = binfo->damp_info; 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; binfo->damp_info = bdi; 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++; } bdi->lastrecord = BGP_RECORD_WITHDRAW; bdi->t_updated = t_now; /* Make this route as historical status. */ SET_FLAG (binfo->flags, BGP_INFO_HISTORY); /* 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) { SET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED); bdi->suppress_time = t_now; BGP_DAMP_LIST_DEL (damp, bdi); bgp_reuse_list_add (bdi); } return BGP_DAMP_USED;}intbgp_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; bdi = binfo->damp_info; if (! bdi) return BGP_DAMP_USED; t_now = time (NULL); UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY); 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) ) { UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED); 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; t_now = time (NULL); bdi = binfo->damp_info; if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) { t_diff = t_now - bdi->suppress_time; if (t_diff >= damp->max_suppress_time) { UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED); 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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -