back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_damp.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 0 368 0.0 %
Date: 2023-02-24 19:38:44 Functions: 0 19 0.0 %

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

Generated by: LCOV version v1.16-topotato