bgpd: fix incorrect usage of slist in dampening

Current code is a complete misuse of SLIST structure. Instead of just
adding a SLIST_ENTRY to struct bgp_damp_info, it allocates a separate
structure to be a node in the list.

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
Igor Ryzhov 2021-07-29 01:17:50 +03:00 committed by Donatas Abraitis
parent 4c500d6952
commit 1d37871588
2 changed files with 27 additions and 90 deletions

View File

@ -24,72 +24,32 @@
static void bgp_reuselist_add(struct reuselist *list, struct bgp_damp_info *info) static void bgp_reuselist_add(struct reuselist *list, struct bgp_damp_info *info)
{ {
struct reuselist_node *new_node;
assert(info); assert(info);
new_node = XCALLOC(MTYPE_BGP_DAMP_REUSELIST, sizeof(*new_node)); SLIST_INSERT_HEAD(list, info, entry);
new_node->info = info;
SLIST_INSERT_HEAD(list, new_node, entry);
} }
static void bgp_reuselist_del(struct reuselist *list, static void bgp_reuselist_del(struct reuselist *list, struct bgp_damp_info *info)
struct reuselist_node **node)
{ {
if ((*node) == NULL) assert(info);
return; SLIST_REMOVE(list, info, bgp_damp_info, entry);
assert(list && node && *node);
SLIST_REMOVE(list, (*node), reuselist_node, entry);
XFREE(MTYPE_BGP_DAMP_REUSELIST, (*node));
*node = NULL;
} }
static void bgp_reuselist_switch(struct reuselist *source, static void bgp_reuselist_switch(struct reuselist *source,
struct reuselist_node *node, struct bgp_damp_info *info,
struct reuselist *target) struct reuselist *target)
{ {
assert(source && target && node); assert(source && target && info);
SLIST_REMOVE(source, node, reuselist_node, entry); SLIST_REMOVE(source, info, bgp_damp_info, entry);
SLIST_INSERT_HEAD(target, node, entry); SLIST_INSERT_HEAD(target, info, entry);
}
static void bgp_reuselist_free(struct reuselist *list)
{
struct reuselist_node *rn;
assert(list);
while ((rn = SLIST_FIRST(list)) != NULL)
bgp_reuselist_del(list, &rn);
}
static struct reuselist_node *bgp_reuselist_find(struct reuselist *list,
struct bgp_damp_info *info)
{
struct reuselist_node *rn;
assert(list && info);
SLIST_FOREACH (rn, list, entry) {
if (rn->info == info)
return rn;
}
return NULL;
} }
static void bgp_damp_info_unclaim(struct bgp_damp_info *bdi) static void bgp_damp_info_unclaim(struct bgp_damp_info *bdi)
{ {
struct reuselist_node *node;
assert(bdi && bdi->config); assert(bdi && bdi->config);
if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX) { if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX)
node = bgp_reuselist_find(&bdi->config->no_reuse_list, bdi); bgp_reuselist_del(&bdi->config->no_reuse_list, bdi);
if (node) else
bgp_reuselist_del(&bdi->config->no_reuse_list, &node); bgp_reuselist_del(&bdi->config->reuse_list[bdi->index], bdi);
} else {
node = bgp_reuselist_find(&bdi->config->reuse_list[bdi->index],
bdi);
if (node)
bgp_reuselist_del(&bdi->config->reuse_list[bdi->index],
&node);
}
bdi->config = NULL; bdi->config = NULL;
} }
@ -170,19 +130,9 @@ static void bgp_no_reuse_list_add(struct bgp_damp_info *bdi,
bgp_reuselist_add(&bdc->no_reuse_list, bdi); bgp_reuselist_add(&bdc->no_reuse_list, bdi);
} }
static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi, static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi)
struct bgp_damp_config *bdc)
{ {
struct reuselist_node *rn;
assert(bdc && bdi);
if (bdi->config == NULL) {
bgp_damp_info_unclaim(bdi); bgp_damp_info_unclaim(bdi);
return;
}
bdi->config = NULL;
rn = bgp_reuselist_find(&bdc->no_reuse_list, bdi);
bgp_reuselist_del(&bdc->no_reuse_list, &rn);
} }
/* Return decayed penalty value. */ /* Return decayed penalty value. */
@ -207,7 +157,6 @@ static void bgp_reuse_timer(struct event *t)
{ {
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
struct reuselist plist; struct reuselist plist;
struct reuselist_node *node;
struct bgp *bgp; struct bgp *bgp;
time_t t_now, t_diff; time_t t_now, t_diff;
struct bgp_damp_config *bdc = EVENT_ARG(t); struct bgp_damp_config *bdc = EVENT_ARG(t);
@ -230,8 +179,7 @@ static void bgp_reuse_timer(struct event *t)
assert(bdc->reuse_offset < bdc->reuse_list_size); assert(bdc->reuse_offset < bdc->reuse_list_size);
/* 3. if ( the saved list head pointer is non-empty ) */ /* 3. if ( the saved list head pointer is non-empty ) */
while ((node = SLIST_FIRST(&plist)) != NULL) { while ((bdi = SLIST_FIRST(&plist)) != NULL) {
bdi = node->info;
bgp = bdi->path->peer->bgp; bgp = bdi->path->peer->bgp;
/* Set t-diff = t-now - t-updated. */ /* Set t-diff = t-now - t-updated. */
@ -262,20 +210,19 @@ static void bgp_reuse_timer(struct event *t)
} }
if (bdi->penalty <= bdc->reuse_limit / 2.0) { if (bdi->penalty <= bdc->reuse_limit / 2.0) {
bgp_reuselist_del(&plist, bdi);
bgp_damp_info_free(bdi, bdc, 1, bdi->afi, bgp_damp_info_free(bdi, bdc, 1, bdi->afi,
bdi->safi); bdi->safi);
bgp_reuselist_del(&plist, &node);
} else { } else {
node->info->index = bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
BGP_DAMP_NO_REUSE_LIST_INDEX; bgp_reuselist_switch(&plist, bdi,
bgp_reuselist_switch(&plist, node,
&bdc->no_reuse_list); &bdc->no_reuse_list);
} }
} else { } else {
/* Re-insert into another list (See RFC2439 Section /* Re-insert into another list (See RFC2439 Section
* 4.8.6). */ * 4.8.6). */
bdi->index = bgp_reuse_index(bdi->penalty, bdc); bdi->index = bgp_reuse_index(bdi->penalty, bdc);
bgp_reuselist_switch(&plist, node, bgp_reuselist_switch(&plist, bdi,
&bdc->reuse_list[bdi->index]); &bdc->reuse_list[bdi->index]);
} }
} }
@ -369,7 +316,7 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
if (bdi->penalty >= bdc->suppress_value) { if (bdi->penalty >= bdc->suppress_value) {
bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED); bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED);
bdi->suppress_time = t_now; bdi->suppress_time = t_now;
bgp_no_reuse_list_delete(bdi, bdc); bgp_no_reuse_list_delete(bdi);
bgp_reuse_list_add(bdi, bdc); bgp_reuse_list_add(bdi, bdc);
} }
return BGP_DAMP_USED; return BGP_DAMP_USED;
@ -536,15 +483,13 @@ void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
afi_t afi, safi_t safi) afi_t afi, safi_t safi)
{ {
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
struct reuselist_node *rn;
struct reuselist *list; struct reuselist *list;
unsigned int i; unsigned int i;
bdc->reuse_offset = 0; bdc->reuse_offset = 0;
for (i = 0; i < bdc->reuse_list_size; ++i) { for (i = 0; i < bdc->reuse_list_size; ++i) {
list = &bdc->reuse_list[i]; list = &bdc->reuse_list[i];
while ((rn = SLIST_FIRST(list)) != NULL) { while ((bdi = SLIST_FIRST(list)) != NULL) {
bdi = rn->info;
if (bdi->lastrecord == BGP_RECORD_UPDATE) { if (bdi->lastrecord == BGP_RECORD_UPDATE) {
bgp_aggregate_increment(bgp, bgp_aggregate_increment(bgp,
bgp_dest_get_prefix( bgp_dest_get_prefix(
@ -554,14 +499,13 @@ void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
bgp_process(bgp, bdi->dest, bdi->path, bdi->afi, bgp_process(bgp, bdi->dest, bdi->path, bdi->afi,
bdi->safi); bdi->safi);
} }
bgp_reuselist_del(list, &rn); bgp_reuselist_del(list, bdi);
bgp_damp_info_free(bdi, bdc, 1, afi, safi); bgp_damp_info_free(bdi, bdc, 1, afi, safi);
} }
} }
while ((rn = SLIST_FIRST(&bdc->no_reuse_list)) != NULL) { while ((bdi = SLIST_FIRST(&bdc->no_reuse_list)) != NULL) {
bdi = rn->info; bgp_reuselist_del(&bdc->no_reuse_list, bdi);
bgp_reuselist_del(&bdc->no_reuse_list, &rn);
bgp_damp_info_free(bdi, bdc, 1, afi, safi); bgp_damp_info_free(bdi, bdc, 1, afi, safi);
} }
@ -573,10 +517,6 @@ void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index); XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index);
bdc->reuse_index_size = 0; bdc->reuse_index_size = 0;
/* Free reuse list array. */
for (i = 0; i < bdc->reuse_list_size; ++i)
bgp_reuselist_free(&bdc->reuse_list[i]);
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list); XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list);
bdc->reuse_list_size = 0; bdc->reuse_list_size = 0;

View File

@ -46,14 +46,11 @@ struct bgp_damp_info {
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
SLIST_ENTRY(bgp_damp_info) entry;
}; };
struct reuselist_node { SLIST_HEAD(reuselist, bgp_damp_info);
SLIST_ENTRY(reuselist_node) entry;
struct bgp_damp_info *info;
};
SLIST_HEAD(reuselist, reuselist_node);
/* Specified parameter set configuration. */ /* Specified parameter set configuration. */
struct bgp_damp_config { struct bgp_damp_config {