]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Rework BGP dampening to be per AFI/SAFI
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Sun, 10 Nov 2019 18:13:20 +0000 (20:13 +0200)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Thu, 14 Nov 2019 17:56:49 +0000 (19:56 +0200)
Before we had:

!
router bgp 65031
 bgp dampening 1 2 3 4
!

exit2-debian-9(config)# router bgp 65031
exit2-debian-9(config-router)# address-family ipv4 multicast
exit2-debian-9(config-router-af)# bgp dampening 5 6 7 8
exit2-debian-9(config-router-af)# end
exit2-debian-9# show running-config

!
router bgp 65031
 bgp dampening 1 2 3 4
!

After fix:

!
router bgp 65031
 neighbor 192.168.1.2 remote-as 100
 !
 address-family ipv4 unicast
  bgp dampening 1 2 3 4
 exit-address-family
 !
 address-family ipv4 multicast
  bgp dampening 5 6 7 8
 exit-address-family
!

exit2-debian-9# show ip bgp ipv4 unicast dampening parameters
Half-life time: 1 min
Reuse penalty: 2
Suppress penalty: 3
Max suppress time: 4 min
Max suppress penalty: 32

exit2-debian-9# show ip bgp ipv4 multicast dampening parameters
Half-life time: 5 min
Reuse penalty: 6
Suppress penalty: 7
Max suppress time: 8 min
Max suppress penalty: 18

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
bgpd/bgp_damp.c
bgpd/bgp_damp.h
bgpd/bgp_route.c
bgpd/bgpd.c

index cf085e46fb1f1eaacc66d38217f85951b0d51d71..b0fee079d16d29f479c157e6f2ec31fabd27869a 100644 (file)
@@ -37,8 +37,7 @@
 #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;
+static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
 
 /* Utility macro to add and delete BGP dampening information to no
    used list.  */
@@ -46,49 +45,51 @@ static struct bgp_damp_config *damp = &bgp_damp_cfg;
 #define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
 
 /* Calculate reuse list index by penalty value.  */
-static int bgp_reuse_index(int penalty)
+static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
 {
        unsigned int i;
        int index;
 
-       i = (int)(((double)penalty / damp->reuse_limit - 1.0)
-                 * damp->scale_factor);
+       i = (int)(((double)penalty / bdc->reuse_limit - 1.0)
+                 * bdc->scale_factor);
 
-       if (i >= damp->reuse_index_size)
-               i = damp->reuse_index_size - 1;
+       if (i >= bdc->reuse_index_size)
+               i = bdc->reuse_index_size - 1;
 
-       index = damp->reuse_index[i] - damp->reuse_index[0];
+       index = bdc->reuse_index[i] - bdc->reuse_index[0];
 
-       return (damp->reuse_offset + index) % damp->reuse_list_size;
+       return (bdc->reuse_offset + index) % bdc->reuse_list_size;
 }
 
 /* Add BGP dampening information to reuse list.  */
-static void bgp_reuse_list_add(struct bgp_damp_info *bdi)
+static void bgp_reuse_list_add(struct bgp_damp_info *bdi,
+                              struct bgp_damp_config *bdc)
 {
        int index;
 
-       index = bdi->index = bgp_reuse_index(bdi->penalty);
+       index = bdi->index = bgp_reuse_index(bdi->penalty, bdc);
 
        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;
+       bdi->next = bdc->reuse_list[index];
+       if (bdc->reuse_list[index])
+               bdc->reuse_list[index]->prev = bdi;
+       bdc->reuse_list[index] = bdi;
 }
 
 /* Delete BGP dampening information from reuse list.  */
-static void bgp_reuse_list_delete(struct bgp_damp_info *bdi)
+static void bgp_reuse_list_delete(struct bgp_damp_info *bdi,
+                                 struct bgp_damp_config *bdc)
 {
        if (bdi->next)
                bdi->next->prev = bdi->prev;
        if (bdi->prev)
                bdi->prev->next = bdi->next;
        else
-               damp->reuse_list[bdi->index] = bdi->next;
+               bdc->reuse_list[bdi->index] = bdi->next;
 }
 
 /* Return decayed penalty value.  */
-int bgp_damp_decay(time_t tdiff, int penalty)
+int bgp_damp_decay(time_t tdiff, int penalty, struct bgp_damp_config *bdc)
 {
        unsigned int i;
 
@@ -97,10 +98,10 @@ int bgp_damp_decay(time_t tdiff, int penalty)
        if (i == 0)
                return penalty;
 
-       if (i >= damp->decay_array_size)
+       if (i >= bdc->decay_array_size)
                return 0;
 
-       return (int)(penalty * damp->decay_array[i]);
+       return (int)(penalty * bdc->decay_array[i]);
 }
 
 /* Handler of reuse timer event.  Each route in the current reuse-list
@@ -111,20 +112,22 @@ static int bgp_reuse_timer(struct thread *t)
        struct bgp_damp_info *next;
        time_t t_now, t_diff;
 
-       damp->t_reuse = NULL;
-       thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
-                        &damp->t_reuse);
+       struct bgp_damp_config *bdc = THREAD_ARG(t);
+
+       bdc->t_reuse = NULL;
+       thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
+                        &bdc->t_reuse);
 
        t_now = bgp_clock();
 
        /* 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;
+       bdi = bdc->reuse_list[bdc->reuse_offset];
+       bdc->reuse_list[bdc->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;
+       bdc->reuse_offset = (bdc->reuse_offset + 1) % bdc->reuse_list_size;
 
        /* 3. if ( the saved list head pointer is non-empty ) */
        for (; bdi; bdi = next) {
@@ -137,13 +140,13 @@ static int bgp_reuse_timer(struct thread *t)
 
                /* Set figure-of-merit = figure-of-merit * decay-array-ok
                 * [t-diff] */
-               bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty);
+               bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
 
                /* Set t-updated = t-now.  */
                bdi->t_updated = t_now;
 
                /* if (figure-of-merit < reuse).  */
-               if (bdi->penalty < damp->reuse_limit) {
+               if (bdi->penalty < bdc->reuse_limit) {
                        /* Reuse the route.  */
                        bgp_path_info_unset_flag(bdi->rn, bdi->path,
                                                 BGP_PATH_DAMPED);
@@ -158,14 +161,14 @@ static int bgp_reuse_timer(struct thread *t)
                                bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi);
                        }
 
-                       if (bdi->penalty <= damp->reuse_limit / 2.0)
-                               bgp_damp_info_free(bdi, 1);
+                       if (bdi->penalty <= bdc->reuse_limit / 2.0)
+                               bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi);
                        else
-                               BGP_DAMP_LIST_ADD(damp, bdi);
+                               BGP_DAMP_LIST_ADD(bdc, bdi);
                } else
                        /* Re-insert into another list (See RFC2439 Section
                         * 4.8.6).  */
-                       bgp_reuse_list_add(bdi);
+                       bgp_reuse_list_add(bdi, bdc);
        }
 
        return 0;
@@ -178,6 +181,7 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
        time_t t_now;
        struct bgp_damp_info *bdi = NULL;
        unsigned int last_penalty = 0;
+       struct bgp_damp_config *bdc = &damp[afi][safi];
 
        t_now = bgp_clock();
 
@@ -206,18 +210,18 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
                bdi->afi = afi;
                bdi->safi = safi;
                (bgp_path_info_extra_get(path))->damp_info = bdi;
-               BGP_DAMP_LIST_ADD(damp, bdi);
+               BGP_DAMP_LIST_ADD(bdc, 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));
+               bdi->penalty = (bgp_damp_decay(t_now - bdi->t_updated,
+                                              bdi->penalty, bdc)
+                               + (attr_change ? DEFAULT_PENALTY / 2
+                                              : DEFAULT_PENALTY));
 
-               if (bdi->penalty > damp->ceiling)
-                       bdi->penalty = damp->ceiling;
+               if (bdi->penalty > bdc->ceiling)
+                       bdi->penalty = bdc->ceiling;
 
                bdi->flap++;
        }
@@ -234,19 +238,19 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
        if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) {
                /* If decay rate isn't equal to 0, reinsert brn. */
                if (bdi->penalty != last_penalty && bdi->index >= 0) {
-                       bgp_reuse_list_delete(bdi);
-                       bgp_reuse_list_add(bdi);
+                       bgp_reuse_list_delete(bdi, bdc);
+                       bgp_reuse_list_add(bdi, bdc);
                }
                return BGP_DAMP_SUPPRESSED;
        }
 
        /* If not suppressed before, do annonunce this withdraw and
           insert into reuse_list.  */
-       if (bdi->penalty >= damp->suppress_value) {
+       if (bdi->penalty >= bdc->suppress_value) {
                bgp_path_info_set_flag(rn, path, BGP_PATH_DAMPED);
                bdi->suppress_time = t_now;
-               BGP_DAMP_LIST_DEL(damp, bdi);
-               bgp_reuse_list_add(bdi);
+               BGP_DAMP_LIST_DEL(bdc, bdi);
+               bgp_reuse_list_add(bdi, bdc);
        }
 
        return BGP_DAMP_USED;
@@ -258,6 +262,7 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, afi_t afi,
        time_t t_now;
        struct bgp_damp_info *bdi;
        int status;
+       struct bgp_damp_config *bdc = &damp[afi][safi];
 
        if (!path->extra || !((bdi = path->extra->damp_info)))
                return BGP_DAMP_USED;
@@ -266,76 +271,35 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, afi_t afi,
        bgp_path_info_unset_flag(rn, path, BGP_PATH_HISTORY);
 
        bdi->lastrecord = BGP_RECORD_UPDATE;
-       bdi->penalty = bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty);
+       bdi->penalty =
+               bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty, bdc);
 
        if (!CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
-           && (bdi->penalty < damp->suppress_value))
+           && (bdi->penalty < bdc->suppress_value))
                status = BGP_DAMP_USED;
        else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
-                && (bdi->penalty < damp->reuse_limit)) {
+                && (bdi->penalty < bdc->reuse_limit)) {
                bgp_path_info_unset_flag(rn, path, BGP_PATH_DAMPED);
-               bgp_reuse_list_delete(bdi);
-               BGP_DAMP_LIST_ADD(damp, bdi);
+               bgp_reuse_list_delete(bdi, bdc);
+               BGP_DAMP_LIST_ADD(bdc, bdi);
                bdi->suppress_time = 0;
                status = BGP_DAMP_USED;
        } else
                status = BGP_DAMP_SUPPRESSED;
 
-       if (bdi->penalty > damp->reuse_limit / 2.0)
+       if (bdi->penalty > bdc->reuse_limit / 2.0)
                bdi->t_updated = t_now;
        else
-               bgp_damp_info_free(bdi, 0);
+               bgp_damp_info_free(bdi, 0, afi, safi);
 
        return status;
 }
 
-/* Remove dampening information and history route.  */
-int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi)
-{
-       time_t t_now, t_diff;
-       struct bgp_damp_info *bdi;
-
-       assert(path->extra && path->extra->damp_info);
-
-       t_now = bgp_clock();
-       bdi = path->extra->damp_info;
-
-       if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
-               t_diff = t_now - bdi->suppress_time;
-
-               if (t_diff >= damp->max_suppress_time) {
-                       bgp_path_info_unset_flag(bdi->rn, path,
-                                                BGP_PATH_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 path 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->path. */
-                       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)
+void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
+                       safi_t safi)
 {
        struct bgp_path_info *path;
+       struct bgp_damp_config *bdc = &damp[afi][safi];
 
        if (!bdi)
                return;
@@ -344,9 +308,9 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
        path->extra->damp_info = NULL;
 
        if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
-               bgp_reuse_list_delete(bdi);
+               bgp_reuse_list_delete(bdi, bdc);
        else
-               BGP_DAMP_LIST_DEL(damp, bdi);
+               BGP_DAMP_LIST_DEL(bdc, bdi);
 
        bgp_path_info_unset_flag(bdi->rn, path,
                                 BGP_PATH_HISTORY | BGP_PATH_DAMPED);
@@ -357,68 +321,67 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
        XFREE(MTYPE_BGP_DAMP_INFO, bdi);
 }
 
-static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup)
+static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup,
+                                  struct bgp_damp_config *bdc)
 {
        double reuse_max_ratio;
        unsigned int i;
        double j;
 
-       damp->suppress_value = sup;
-       damp->half_life = hlife;
-       damp->reuse_limit = reuse;
-       damp->max_suppress_time = maxsup;
+       bdc->suppress_value = sup;
+       bdc->half_life = hlife;
+       bdc->reuse_limit = reuse;
+       bdc->max_suppress_time = maxsup;
 
        /* Initialize params per bgp_damp_config. */
-       damp->reuse_index_size = REUSE_ARRAY_SIZE;
+       bdc->reuse_index_size = REUSE_ARRAY_SIZE;
 
-       damp->ceiling =
-               (int)(damp->reuse_limit * (pow(2,
-                                              (double)damp->max_suppress_time
-                                                      / damp->half_life)));
+       bdc->ceiling = (int)(bdc->reuse_limit
+                            * (pow(2, (double)bdc->max_suppress_time
+                                              / bdc->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));
+       bdc->decay_array_size = ceil((double)bdc->max_suppress_time / DELTA_T);
+       bdc->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY,
+                                  sizeof(double) * (bdc->decay_array_size));
+       bdc->decay_array[0] = 1.0;
+       bdc->decay_array[1] =
+               exp((1.0 / ((double)bdc->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];
+       for (i = 2; i < bdc->decay_array_size; i++)
+               bdc->decay_array[i] =
+                       bdc->decay_array[i - 1] * bdc->decay_array[1];
 
        /* Reuse-list computations */
-       i = ceil((double)damp->max_suppress_time / DELTA_REUSE) + 1;
+       i = ceil((double)bdc->max_suppress_time / DELTA_REUSE) + 1;
        if (i > REUSE_LIST_SIZE || i == 0)
                i = REUSE_LIST_SIZE;
-       damp->reuse_list_size = i;
+       bdc->reuse_list_size = i;
 
-       damp->reuse_list = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
-                                  damp->reuse_list_size
-                                          * sizeof(struct bgp_reuse_node *));
+       bdc->reuse_list =
+               XCALLOC(MTYPE_BGP_DAMP_ARRAY,
+                       bdc->reuse_list_size * sizeof(struct bgp_reuse_node *));
 
        /* Reuse-array computations */
-       damp->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
-                                   sizeof(int) * damp->reuse_index_size);
+       bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
+                                  sizeof(int) * bdc->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));
+       reuse_max_ratio = (double)bdc->ceiling / bdc->reuse_limit;
+       j = (exp((double)bdc->max_suppress_time / bdc->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);
+       bdc->scale_factor =
+               (double)bdc->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))))
+       for (i = 0; i < bdc->reuse_index_size; i++) {
+               bdc->reuse_index[i] =
+                       (int)(((double)bdc->half_life / DELTA_REUSE)
+                             * log10(1.0
+                                     / (bdc->reuse_limit
+                                        * (1.0
+                                           + ((double)i / bdc->scale_factor))))
                              / log10(0.5));
        }
 }
@@ -426,122 +389,129 @@ static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup)
 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)
 {
+       struct bgp_damp_config *bdc = &damp[afi][safi];
+
        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)
+               if (bdc->half_life == half && bdc->reuse_limit == reuse
+                   && bdc->suppress_value == suppress
+                   && bdc->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);
+       bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
 
        /* Register reuse timer.  */
-       thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
-                        &damp->t_reuse);
+       thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
+                        &bdc->t_reuse);
 
        return 0;
 }
 
-static void bgp_damp_config_clean(struct bgp_damp_config *damp)
+static void bgp_damp_config_clean(struct bgp_damp_config *bdc)
 {
        /* Free decay array */
-       XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
-       damp->decay_array_size = 0;
+       XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array);
+       bdc->decay_array_size = 0;
 
        /* Free reuse index array */
-       XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
-       damp->reuse_index_size = 0;
+       XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index);
+       bdc->reuse_index_size = 0;
 
        /* Free reuse list array. */
-       XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
-       damp->reuse_list_size = 0;
+       XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list);
+       bdc->reuse_list_size = 0;
 }
 
 /* Clean all the bgp_damp_info stored in reuse_list. */
-void bgp_damp_info_clean(void)
+void bgp_damp_info_clean(afi_t afi, safi_t safi)
 {
        unsigned int i;
        struct bgp_damp_info *bdi, *next;
+       struct bgp_damp_config *bdc = &damp[afi][safi];
 
-       damp->reuse_offset = 0;
+       bdc->reuse_offset = 0;
 
-       for (i = 0; i < damp->reuse_list_size; i++) {
-               if (!damp->reuse_list[i])
+       for (i = 0; i < bdc->reuse_list_size; i++) {
+               if (!bdc->reuse_list[i])
                        continue;
 
-               for (bdi = damp->reuse_list[i]; bdi; bdi = next) {
+               for (bdi = bdc->reuse_list[i]; bdi; bdi = next) {
                        next = bdi->next;
-                       bgp_damp_info_free(bdi, 1);
+                       bgp_damp_info_free(bdi, 1, afi, safi);
                }
-               damp->reuse_list[i] = NULL;
+               bdc->reuse_list[i] = NULL;
        }
 
-       for (bdi = damp->no_reuse_list; bdi; bdi = next) {
+       for (bdi = bdc->no_reuse_list; bdi; bdi = next) {
                next = bdi->next;
-               bgp_damp_info_free(bdi, 1);
+               bgp_damp_info_free(bdi, 1, afi, safi);
        }
-       damp->no_reuse_list = NULL;
+       bdc->no_reuse_list = NULL;
 }
 
 int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
 {
+       struct bgp_damp_config *bdc = &damp[afi][safi];
        /* If it wasn't enabled, there's nothing to do. */
        if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
                return 0;
 
        /* Cancel reuse thread. */
-       if (damp->t_reuse)
-               thread_cancel(damp->t_reuse);
-       damp->t_reuse = NULL;
+       if (bdc->t_reuse)
+               thread_cancel(bdc->t_reuse);
+       bdc->t_reuse = NULL;
 
        /* Clean BGP dampening information.  */
-       bgp_damp_info_clean();
+       bgp_damp_info_clean(afi, safi);
 
        /* Clear configuration */
-       bgp_damp_config_clean(&bgp_damp_cfg);
+       bgp_damp_config_clean(bdc);
 
        UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
        return 0;
 }
 
-void bgp_config_write_damp(struct vty *vty)
+void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi)
 {
-       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\n");
-       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 %lld\n",
-                       bgp_damp_cfg.half_life / 60LL);
+       if (damp[afi][safi].half_life == DEFAULT_HALF_LIFE * 60
+           && damp[afi][safi].reuse_limit == DEFAULT_REUSE
+           && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
+           && damp[afi][safi].max_suppress_time
+                      == damp[afi][safi].half_life * 4)
+               vty_out(vty, "  bgp dampening\n");
+       else if (damp[afi][safi].half_life != DEFAULT_HALF_LIFE * 60
+                && damp[afi][safi].reuse_limit == DEFAULT_REUSE
+                && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
+                && damp[afi][safi].max_suppress_time
+                           == damp[afi][safi].half_life * 4)
+               vty_out(vty, "  bgp dampening %lld\n",
+                       damp[afi][safi].half_life / 60LL);
        else
-               vty_out(vty, " bgp dampening %lld %d %d %lld\n",
-                       bgp_damp_cfg.half_life / 60LL, bgp_damp_cfg.reuse_limit,
-                       bgp_damp_cfg.suppress_value,
-                       bgp_damp_cfg.max_suppress_time / 60LL);
+               vty_out(vty, "  bgp dampening %lld %d %d %lld\n",
+                       damp[afi][safi].half_life / 60LL,
+                       damp[afi][safi].reuse_limit,
+                       damp[afi][safi].suppress_value,
+                       damp[afi][safi].max_suppress_time / 60LL);
 }
 
 static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
-                                     size_t len, bool use_json,
-                                     json_object *json)
+                                     size_t len, afi_t afi, safi_t safi,
+                                     bool use_json, json_object *json)
 {
        time_t reuse_time = 0;
        struct tm *tm = NULL;
        int time_store = 0;
 
-       if (penalty > damp->reuse_limit) {
+       if (penalty > damp[afi][safi].reuse_limit) {
                reuse_time = (int)(DELTA_T
-                                  * ((log((double)damp->reuse_limit / penalty))
-                                     / (log(damp->decay_array[1]))));
+                                  * ((log((double)damp[afi][safi].reuse_limit
+                                          / penalty))
+                                     / (log(damp[afi][safi].decay_array[1]))));
 
-               if (reuse_time > damp->max_suppress_time)
-                       reuse_time = damp->max_suppress_time;
+               if (reuse_time > damp[afi][safi].max_suppress_time)
+                       reuse_time = damp[afi][safi].max_suppress_time;
 
                tm = gmtime(&reuse_time);
        } else
@@ -593,13 +563,14 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
        return buf;
 }
 
-void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
-                      json_object *json_path)
+void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
+                      safi_t safi, json_object *json_path)
 {
        struct bgp_damp_info *bdi;
        time_t t_now, t_diff;
        char timebuf[BGP_UPTIME_LEN];
        int penalty;
+       struct bgp_damp_config *bdc = &damp[afi][safi];
 
        if (!path->extra)
                return;
@@ -609,13 +580,13 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
 
        /* If dampening is not enabled or there is no dampening information,
           return immediately.  */
-       if (!damp || !bdi)
+       if (!bdc || !bdi)
                return;
 
        /* Calculate new penalty.  */
        t_now = bgp_clock();
        t_diff = t_now - bdi->t_updated;
-       penalty = bgp_damp_decay(t_diff, bdi->penalty);
+       penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
 
        if (json_path) {
                json_object_int_add(json_path, "dampeningPenalty", penalty);
@@ -625,8 +596,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
 
                if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
                    && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
-                       bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, 1,
-                                          json_path);
+                       bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN,
+                                          afi, safi, 1, json_path);
        } else {
                vty_out(vty,
                        "      Dampinfo: penalty %d, flapped %d times in %s",
@@ -638,7 +609,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
                    && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
                        vty_out(vty, ", reuse in %s",
                                bgp_get_reuse_time(penalty, timebuf,
-                                                  BGP_UPTIME_LEN, 0,
+                                                  BGP_UPTIME_LEN, afi, safi, 0,
                                                   json_path));
 
                vty_out(vty, "\n");
@@ -646,12 +617,14 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
 }
 
 const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
-                                   char *timebuf, size_t len, bool use_json,
+                                   char *timebuf, size_t len, afi_t afi,
+                                   safi_t safi, bool use_json,
                                    json_object *json)
 {
        struct bgp_damp_info *bdi;
        time_t t_now, t_diff;
        int penalty;
+       struct bgp_damp_config *bdc = &damp[afi][safi];
 
        if (!path->extra)
                return NULL;
@@ -661,15 +634,16 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
 
        /* If dampening is not enabled or there is no dampening information,
           return immediately.  */
-       if (!damp || !bdi)
+       if (!bdc || !bdi)
                return NULL;
 
        /* Calculate new penalty.  */
        t_now = bgp_clock();
        t_diff = t_now - bdi->t_updated;
-       penalty = bgp_damp_decay(t_diff, bdi->penalty);
+       penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
 
-       return bgp_get_reuse_time(penalty, timebuf, len, use_json, json);
+       return bgp_get_reuse_time(penalty, timebuf, len, afi, safi, use_json,
+                                 json);
 }
 
 int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
@@ -684,12 +658,15 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
 
        if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
                vty_out(vty, "Half-life time: %lld min\n",
-                       (long long)damp->half_life / 60);
-               vty_out(vty, "Reuse penalty: %d\n", damp->reuse_limit);
-               vty_out(vty, "Suppress penalty: %d\n", damp->suppress_value);
+                       (long long)damp[afi][safi].half_life / 60);
+               vty_out(vty, "Reuse penalty: %d\n",
+                       damp[afi][safi].reuse_limit);
+               vty_out(vty, "Suppress penalty: %d\n",
+                       damp[afi][safi].suppress_value);
                vty_out(vty, "Max suppress time: %lld min\n",
-                       (long long)damp->max_suppress_time / 60);
-               vty_out(vty, "Max suppress penalty: %u\n", damp->ceiling);
+                       (long long)damp[afi][safi].max_suppress_time / 60);
+               vty_out(vty, "Max suppress penalty: %u\n",
+                       damp[afi][safi].ceiling);
                vty_out(vty, "\n");
        } else
                vty_out(vty, "dampening not enabled for %s\n",
index 18bf561c477c83114a9db5a73a4645916d96c28f..3dd860a29d64a0a928dd9266c0436148b0f35197 100644 (file)
@@ -106,6 +106,9 @@ struct bgp_damp_config {
 
        /* Reuse timer thread per-set base. */
        struct thread *t_reuse;
+
+       afi_t afi;
+       safi_t safi;
 };
 
 #define BGP_DAMP_NONE           0
@@ -134,17 +137,18 @@ extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
                             afi_t afi, safi_t safi, int attr_change);
 extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn,
                           afi_t afi, safi_t saff);
-extern int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi);
-extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw);
-extern void bgp_damp_info_clean(void);
-extern int bgp_damp_decay(time_t, int);
-extern void bgp_config_write_damp(struct vty *);
+extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw,
+                              afi_t afi, safi_t safi);
+extern void bgp_damp_info_clean(afi_t afi, safi_t safi);
+extern int bgp_damp_decay(time_t, int, struct bgp_damp_config *damp);
+extern void bgp_config_write_damp(struct vty *, afi_t afi, safi_t safi);
 extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
-                             json_object *json_path);
+                             afi_t afi, safi_t safi, json_object *json_path);
 extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
                                           struct bgp_path_info *path,
-                                          char *timebuf, size_t len,
-                                          bool use_json, json_object *json);
+                                          char *timebuf, size_t len, afi_t afi,
+                                          safi_t safi, bool use_json,
+                                          json_object *json);
 extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t);
 
 #endif /* _QUAGGA_BGP_DAMP_H */
index ee5f41d165d125e5d8a36a243afc1a8f6da9cea0..9d5348f07964586a84c411890ae75d073da0f72a 100644 (file)
@@ -189,7 +189,8 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
 
        e = *extra;
        if (e->damp_info)
-               bgp_damp_info_free(e->damp_info, 0);
+               bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
+                                  e->damp_info->safi);
 
        e->damp_info = NULL;
        if (e->parent) {
@@ -7644,7 +7645,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
 
 /* dampening route */
 static void damp_route_vty_out(struct vty *vty, struct prefix *p,
-                              struct bgp_path_info *path, int display,
+                              struct bgp_path_info *path, int display, afi_t afi,
                               safi_t safi, bool use_json, json_object *json)
 {
        struct attr *attr;
@@ -7675,13 +7676,13 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
        }
 
        if (use_json)
-               bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
-                                       use_json, json);
+               bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
+                                       safi, use_json, json);
        else
                vty_out(vty, "%s ",
                        bgp_damp_reuse_time_vty(vty, path, timebuf,
-                                               BGP_UPTIME_LEN, use_json,
-                                               json));
+                                               BGP_UPTIME_LEN, afi, safi,
+                                               use_json, json));
 
        /* Print attribute */
        attr = path->attr;
@@ -7708,7 +7709,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
 
 /* flap route */
 static void flap_route_vty_out(struct vty *vty, struct prefix *p,
-                              struct bgp_path_info *path, int display,
+                              struct bgp_path_info *path, int display, afi_t afi,
                               safi_t safi, bool use_json, json_object *json)
 {
        struct attr *attr;
@@ -7767,12 +7768,13 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p,
            && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
                if (use_json)
                        bgp_damp_reuse_time_vty(vty, path, timebuf,
-                                               BGP_UPTIME_LEN, use_json, json);
+                                               BGP_UPTIME_LEN, afi, safi,
+                                               use_json, json);
                else
                        vty_out(vty, "%s ",
                                bgp_damp_reuse_time_vty(vty, path, timebuf,
-                                                       BGP_UPTIME_LEN,
-                                                       use_json, json));
+                                                       BGP_UPTIME_LEN, afi,
+                                                       safi, use_json, json));
        } else {
                if (!use_json)
                        vty_out(vty, "%*s ", 8, " ");
@@ -8612,7 +8614,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                }
 
                if (path->extra && path->extra->damp_info)
-                       bgp_damp_info_vty(vty, path, json_path);
+                       bgp_damp_info_vty(vty, path, afi, safi, json_path);
 
                /* Remote Label */
                if (path->extra && bgp_is_valid_label(&path->extra->label[0])
@@ -9022,11 +9024,11 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                        }
                        if (type == bgp_show_type_dampend_paths
                            || type == bgp_show_type_damp_neighbor)
-                               damp_route_vty_out(vty, &rn->p, pi, display,
+                               damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
                                                   safi, use_json, json_paths);
                        else if (type == bgp_show_type_flap_statistics
                                 || type == bgp_show_type_flap_neighbor)
-                               flap_route_vty_out(vty, &rn->p, pi, display,
+                               flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
                                                   safi, use_json, json_paths);
                        else
                                route_vty_out(vty, &rn->p, pi, display, safi,
@@ -11896,7 +11898,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
                                                pi_temp = pi->next;
                                                bgp_damp_info_free(
                                                        pi->extra->damp_info,
-                                                       1);
+                                                       1, afi, safi);
                                                pi = pi_temp;
                                        } else
                                                pi = pi->next;
@@ -11916,7 +11918,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
                                                pi_temp = pi->next;
                                                bgp_damp_info_free(
                                                        pi->extra->damp_info,
-                                                       1);
+                                                       1, afi, safi);
                                                pi = pi_temp;
                                        } else
                                                pi = pi->next;
@@ -11938,7 +11940,7 @@ DEFUN (clear_ip_bgp_dampening,
        BGP_STR
        "Clear route flap dampening information\n")
 {
-       bgp_damp_info_clean();
+       bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
        return CMD_SUCCESS;
 }
 
index 66c1e623a08305526a817e094c26013d0ad7a433..f0130c976865e800aceee4179c210a9d442c16b0 100644 (file)
@@ -7265,6 +7265,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                vty_out(vty, "\n");
        }
 
+       /* BGP flag dampening. */
+       if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                      BGP_CONFIG_DAMPENING))
+               bgp_config_write_damp(vty, afi, safi);
+
        /* Route reflector client. */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_REFLECTOR_CLIENT)) {
@@ -7804,11 +7809,6 @@ int bgp_config_write(struct vty *vty)
                                        ? ""
                                        : "no ");
 
-               /* BGP flag dampening. */
-               if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST],
-                              BGP_CONFIG_DAMPENING))
-                       bgp_config_write_damp(vty);
-
                /* BGP timers configuration. */
                if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
                    && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)