forked from Mirror/frr
bgpd: rfapi: track outstanding rib and import timers, free mem at exit
While here, also make "VPN SAFI clear" test wait for clear result (tests/topotests/bgp_rfapi_basic_sanity{,_config2}) Original RFAPI code relied on the frr timer system to remember various allocations that were supposed to be freed at future times rather than manage a parallel database. However, if bgpd is terminated before the times expire, those pending allocations are marked as memory leaks, even though they wouldn't be leaks under normal operation. This change adds some hash tables to track these outstanding allocations that are associated with pending timers, and uses those tables to free the allocations when bgpd exits. Signed-off-by: G. Paul Ziemba <paulz@labn.net>
This commit is contained in:
parent
a02ec27693
commit
1629c05924
|
@ -8846,6 +8846,9 @@ void bgp_terminate(void)
|
||||||
EVENT_OFF(bm->t_bgp_zebra_l3_vni);
|
EVENT_OFF(bm->t_bgp_zebra_l3_vni);
|
||||||
|
|
||||||
bgp_mac_finish();
|
bgp_mac_finish();
|
||||||
|
#if ENABLE_BGP_VNC
|
||||||
|
rfapi_terminate();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
|
struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
|
||||||
|
|
|
@ -3546,6 +3546,8 @@ DEFUN (skiplist_debug_cli,
|
||||||
|
|
||||||
void rfapi_init(void)
|
void rfapi_init(void)
|
||||||
{
|
{
|
||||||
|
rfapi_rib_init();
|
||||||
|
rfapi_import_init();
|
||||||
bgp_rfapi_cfg_init();
|
bgp_rfapi_cfg_init();
|
||||||
vnc_debug_init();
|
vnc_debug_init();
|
||||||
|
|
||||||
|
@ -3576,6 +3578,12 @@ void rfapi_init(void)
|
||||||
rfapi_vty_init();
|
rfapi_vty_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rfapi_terminate(void)
|
||||||
|
{
|
||||||
|
rfapi_import_terminate();
|
||||||
|
rfapi_rib_terminate();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_RFAPI
|
#ifdef DEBUG_RFAPI
|
||||||
static void rfapi_print_exported(struct bgp *bgp)
|
static void rfapi_print_exported(struct bgp *bgp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "bgpd/bgp_nexthop.h"
|
#include "bgpd/bgp_nexthop.h"
|
||||||
|
|
||||||
extern void rfapi_init(void);
|
extern void rfapi_init(void);
|
||||||
|
extern void rfapi_terminate(void);
|
||||||
extern void vnc_zebra_init(struct event_loop *master);
|
extern void vnc_zebra_init(struct event_loop *master);
|
||||||
extern void vnc_zebra_destroy(void);
|
extern void vnc_zebra_destroy(void);
|
||||||
|
|
||||||
|
|
|
@ -52,14 +52,23 @@
|
||||||
#undef DEBUG_IT_NODES
|
#undef DEBUG_IT_NODES
|
||||||
#undef DEBUG_BI_SEARCH
|
#undef DEBUG_BI_SEARCH
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash to keep track of outstanding timers so we can force them to
|
||||||
|
* expire at shutdown time, thus freeing their allocated memory.
|
||||||
|
*/
|
||||||
|
PREDECL_HASH(rwcb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocated for each withdraw timer instance; freed when the timer
|
* Allocated for each withdraw timer instance; freed when the timer
|
||||||
* expires or is canceled
|
* expires or is canceled
|
||||||
*/
|
*/
|
||||||
struct rfapi_withdraw {
|
struct rfapi_withdraw {
|
||||||
|
struct rwcb_item rwcbi;
|
||||||
|
|
||||||
struct rfapi_import_table *import_table;
|
struct rfapi_import_table *import_table;
|
||||||
struct agg_node *node;
|
struct agg_node *node;
|
||||||
struct bgp_path_info *info;
|
struct bgp_path_info *info;
|
||||||
|
void (*timer_service_func)(struct event *t); /* for cleanup */
|
||||||
safi_t safi; /* used only for bulk operations */
|
safi_t safi; /* used only for bulk operations */
|
||||||
/*
|
/*
|
||||||
* For import table node reference count checking (i.e., debugging).
|
* For import table node reference count checking (i.e., debugging).
|
||||||
|
@ -72,6 +81,19 @@ struct rfapi_withdraw {
|
||||||
int lockoffset;
|
int lockoffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int _rwcb_cmp(const struct rfapi_withdraw *w1, const struct rfapi_withdraw *w2)
|
||||||
|
{
|
||||||
|
return (w1 != w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t _rwcb_hash(const struct rfapi_withdraw *w)
|
||||||
|
{
|
||||||
|
return (uintptr_t)w & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_HASH(rwcb, struct rfapi_withdraw, rwcbi, _rwcb_cmp, _rwcb_hash);
|
||||||
|
static struct rwcb_head _rwcbhash;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DEBUG FUNCTION
|
* DEBUG FUNCTION
|
||||||
* Count remote routes and compare with actively-maintained values.
|
* Count remote routes and compare with actively-maintained values.
|
||||||
|
@ -826,6 +848,7 @@ static void rfapiBgpInfoChainFree(struct bgp_path_info *bpi)
|
||||||
struct rfapi_withdraw *wcb =
|
struct rfapi_withdraw *wcb =
|
||||||
EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
|
EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
|
||||||
|
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
||||||
}
|
}
|
||||||
|
@ -2349,6 +2372,7 @@ static void rfapiWithdrawTimerVPN(struct event *t)
|
||||||
|
|
||||||
/* This callback is responsible for the withdraw object's memory */
|
/* This callback is responsible for the withdraw object's memory */
|
||||||
if (early_exit) {
|
if (early_exit) {
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2462,6 +2486,7 @@ done:
|
||||||
|
|
||||||
RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset);
|
RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset);
|
||||||
agg_unlock_node(wcb->node); /* decr ref count */
|
agg_unlock_node(wcb->node); /* decr ref count */
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2705,6 +2730,7 @@ static void rfapiWithdrawTimerEncap(struct event *t)
|
||||||
done:
|
done:
|
||||||
RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 1);
|
RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 1);
|
||||||
agg_unlock_node(wcb->node); /* decr ref count */
|
agg_unlock_node(wcb->node); /* decr ref count */
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
skiplist_free(vpn_node_sl);
|
skiplist_free(vpn_node_sl);
|
||||||
}
|
}
|
||||||
|
@ -2754,6 +2780,8 @@ rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table,
|
||||||
wcb->node = rn;
|
wcb->node = rn;
|
||||||
wcb->info = bpi;
|
wcb->info = bpi;
|
||||||
wcb->import_table = import_table;
|
wcb->import_table = import_table;
|
||||||
|
wcb->timer_service_func = timer_service_func;
|
||||||
|
rwcb_add(&_rwcbhash, wcb);
|
||||||
bgp_attr_intern(bpi->attr);
|
bgp_attr_intern(bpi->attr);
|
||||||
|
|
||||||
if (VNC_DEBUG(VERBOSE)) {
|
if (VNC_DEBUG(VERBOSE)) {
|
||||||
|
@ -2819,6 +2847,7 @@ static void rfapiExpireEncapNow(struct rfapi_import_table *it,
|
||||||
wcb->info = bpi;
|
wcb->info = bpi;
|
||||||
wcb->node = rn;
|
wcb->node = rn;
|
||||||
wcb->import_table = it;
|
wcb->import_table = it;
|
||||||
|
rwcb_add(&_rwcbhash, wcb);
|
||||||
memset(&t, 0, sizeof(t));
|
memset(&t, 0, sizeof(t));
|
||||||
t.arg = wcb;
|
t.arg = wcb;
|
||||||
rfapiWithdrawTimerEncap(&t); /* frees wcb */
|
rfapiWithdrawTimerEncap(&t); /* frees wcb */
|
||||||
|
@ -3057,6 +3086,7 @@ static void rfapiBgpInfoFilteredImportEncap(
|
||||||
struct rfapi_withdraw *wcb = EVENT_ARG(
|
struct rfapi_withdraw *wcb = EVENT_ARG(
|
||||||
bpi->extra->vnc->vnc.import.timer);
|
bpi->extra->vnc->vnc.import.timer);
|
||||||
|
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
EVENT_OFF(bpi->extra->vnc->vnc.import
|
EVENT_OFF(bpi->extra->vnc->vnc.import
|
||||||
.timer);
|
.timer);
|
||||||
|
@ -3083,6 +3113,7 @@ static void rfapiBgpInfoFilteredImportEncap(
|
||||||
wcb->info = bpi;
|
wcb->info = bpi;
|
||||||
wcb->node = rn;
|
wcb->node = rn;
|
||||||
wcb->import_table = import_table;
|
wcb->import_table = import_table;
|
||||||
|
rwcb_add(&_rwcbhash, wcb);
|
||||||
memset(&t, 0, sizeof(t));
|
memset(&t, 0, sizeof(t));
|
||||||
t.arg = wcb;
|
t.arg = wcb;
|
||||||
rfapiWithdrawTimerEncap(
|
rfapiWithdrawTimerEncap(
|
||||||
|
@ -3149,6 +3180,7 @@ static void rfapiBgpInfoFilteredImportEncap(
|
||||||
struct rfapi_withdraw *wcb =
|
struct rfapi_withdraw *wcb =
|
||||||
EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
|
EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
|
||||||
|
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
||||||
}
|
}
|
||||||
|
@ -3293,6 +3325,7 @@ static void rfapiExpireVpnNow(struct rfapi_import_table *it,
|
||||||
wcb->node = rn;
|
wcb->node = rn;
|
||||||
wcb->import_table = it;
|
wcb->import_table = it;
|
||||||
wcb->lockoffset = lockoffset;
|
wcb->lockoffset = lockoffset;
|
||||||
|
rwcb_add(&_rwcbhash, wcb);
|
||||||
memset(&t, 0, sizeof(t));
|
memset(&t, 0, sizeof(t));
|
||||||
t.arg = wcb;
|
t.arg = wcb;
|
||||||
rfapiWithdrawTimerVPN(&t); /* frees wcb */
|
rfapiWithdrawTimerVPN(&t); /* frees wcb */
|
||||||
|
@ -3510,6 +3543,7 @@ void rfapiBgpInfoFilteredImportVPN(
|
||||||
struct rfapi_withdraw *wcb = EVENT_ARG(
|
struct rfapi_withdraw *wcb = EVENT_ARG(
|
||||||
bpi->extra->vnc->vnc.import.timer);
|
bpi->extra->vnc->vnc.import.timer);
|
||||||
|
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
EVENT_OFF(bpi->extra->vnc->vnc.import
|
EVENT_OFF(bpi->extra->vnc->vnc.import
|
||||||
.timer);
|
.timer);
|
||||||
|
@ -3729,6 +3763,7 @@ void rfapiBgpInfoFilteredImportVPN(
|
||||||
struct rfapi_withdraw *wcb =
|
struct rfapi_withdraw *wcb =
|
||||||
EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
|
EVENT_ARG(bpi->extra->vnc->vnc.import.timer);
|
||||||
|
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
|
||||||
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
||||||
}
|
}
|
||||||
|
@ -4474,6 +4509,7 @@ static void rfapiDeleteRemotePrefixesIt(
|
||||||
RFAPI_UPDATE_ITABLE_COUNT(
|
RFAPI_UPDATE_ITABLE_COUNT(
|
||||||
bpi, wcb->import_table,
|
bpi, wcb->import_table,
|
||||||
afi, 1);
|
afi, 1);
|
||||||
|
rwcb_del(&_rwcbhash, wcb);
|
||||||
XFREE(MTYPE_RFAPI_WITHDRAW,
|
XFREE(MTYPE_RFAPI_WITHDRAW,
|
||||||
wcb);
|
wcb);
|
||||||
EVENT_OFF(bpi->extra->vnc->vnc
|
EVENT_OFF(bpi->extra->vnc->vnc
|
||||||
|
@ -4798,3 +4834,33 @@ uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime)
|
||||||
else
|
else
|
||||||
return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
|
return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rfapi_import_init(void)
|
||||||
|
{
|
||||||
|
rwcb_init(&_rwcbhash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rfapi_import_terminate(void)
|
||||||
|
{
|
||||||
|
struct rfapi_withdraw *wcb;
|
||||||
|
struct bgp_path_info *bpi;
|
||||||
|
void (*timer_service_func)(struct event *t);
|
||||||
|
struct event t;
|
||||||
|
|
||||||
|
vnc_zlog_debug_verbose("%s: cleaning up %zu pending timers", __func__,
|
||||||
|
rwcb_count(&_rwcbhash));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clean up memory allocations stored in pending timers
|
||||||
|
*/
|
||||||
|
while ((wcb = rwcb_pop(&_rwcbhash))) {
|
||||||
|
bpi = wcb->info;
|
||||||
|
assert(wcb == EVENT_ARG(bpi->extra->vnc->vnc.import.timer));
|
||||||
|
EVENT_OFF(bpi->extra->vnc->vnc.import.timer);
|
||||||
|
|
||||||
|
timer_service_func = wcb->timer_service_func;
|
||||||
|
memset(&t, 0, sizeof(t));
|
||||||
|
t.arg = wcb;
|
||||||
|
(*timer_service_func)(&t); /* frees wcb */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -225,4 +225,7 @@ extern void rfapiCountAllItRoutes(int *pALRcount, /* active local routes */
|
||||||
--------------------------------------------*/
|
--------------------------------------------*/
|
||||||
extern uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime);
|
extern uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime);
|
||||||
|
|
||||||
|
extern void rfapi_import_init(void);
|
||||||
|
extern void rfapi_import_terminate(void);
|
||||||
|
|
||||||
#endif /* QUAGGA_HGP_RFAPI_IMPORT_H */
|
#endif /* QUAGGA_HGP_RFAPI_IMPORT_H */
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "lib/skiplist.h"
|
#include "lib/skiplist.h"
|
||||||
#include "lib/workqueue.h"
|
#include "lib/workqueue.h"
|
||||||
|
#include <typesafe.h>
|
||||||
|
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
#include "bgpd/bgp_route.h"
|
#include "bgpd/bgp_route.h"
|
||||||
|
@ -44,8 +45,7 @@
|
||||||
|
|
||||||
/* forward decl */
|
/* forward decl */
|
||||||
#if DEBUG_NHL
|
#if DEBUG_NHL
|
||||||
static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
|
static void rfapiRibShowRibSl(void *stream, const struct prefix *pfx, struct skiplist *sl);
|
||||||
struct skiplist *sl);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -234,9 +234,45 @@ void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash to keep track of outstanding timers so we can force them to
|
||||||
|
* expire at shutdown time, thus freeing their allocated memory.
|
||||||
|
*/
|
||||||
|
PREDECL_HASH(rrtcb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer control block for recently-deleted and expired routes
|
||||||
|
*/
|
||||||
|
struct rfapi_rib_tcb {
|
||||||
|
struct rrtcb_item tcbi;
|
||||||
|
|
||||||
|
struct rfapi_descriptor *rfd;
|
||||||
|
struct skiplist *sl;
|
||||||
|
struct rfapi_info *ri;
|
||||||
|
struct agg_node *rn;
|
||||||
|
int flags;
|
||||||
|
#define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _rrtcb_cmp(const struct rfapi_rib_tcb *t1, const struct rfapi_rib_tcb *t2)
|
||||||
|
{
|
||||||
|
return (t1 != t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t _rrtcb_hash(const struct rfapi_rib_tcb *t)
|
||||||
|
{
|
||||||
|
return (uintptr_t)t & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_HASH(rrtcb, struct rfapi_rib_tcb, tcbi, _rrtcb_cmp, _rrtcb_hash);
|
||||||
|
static struct rrtcb_head _rrtcbhash;
|
||||||
|
|
||||||
static void rfapi_info_free(struct rfapi_info *goner)
|
static void rfapi_info_free(struct rfapi_info *goner)
|
||||||
{
|
{
|
||||||
if (goner) {
|
if (goner) {
|
||||||
|
#if DEBUG_CLEANUP
|
||||||
|
zlog_debug("%s: ri %p, timer %p", __func__, goner, goner->timer);
|
||||||
|
#endif
|
||||||
if (goner->tea_options) {
|
if (goner->tea_options) {
|
||||||
rfapiFreeBgpTeaOptionChain(goner->tea_options);
|
rfapiFreeBgpTeaOptionChain(goner->tea_options);
|
||||||
goner->tea_options = NULL;
|
goner->tea_options = NULL;
|
||||||
|
@ -253,32 +289,19 @@ static void rfapi_info_free(struct rfapi_info *goner)
|
||||||
struct rfapi_rib_tcb *tcb;
|
struct rfapi_rib_tcb *tcb;
|
||||||
|
|
||||||
tcb = EVENT_ARG(goner->timer);
|
tcb = EVENT_ARG(goner->timer);
|
||||||
|
#if DEBUG_CLEANUP
|
||||||
|
zlog_debug("%s: ri %p, tcb %p", __func__, goner, tcb);
|
||||||
|
#endif
|
||||||
EVENT_OFF(goner->timer);
|
EVENT_OFF(goner->timer);
|
||||||
|
rrtcb_del(&_rrtcbhash, tcb);
|
||||||
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
||||||
}
|
}
|
||||||
XFREE(MTYPE_RFAPI_INFO, goner);
|
XFREE(MTYPE_RFAPI_INFO, goner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void _rfapiRibExpireTimer(struct rfapi_rib_tcb *tcb)
|
||||||
* Timer control block for recently-deleted and expired routes
|
|
||||||
*/
|
|
||||||
struct rfapi_rib_tcb {
|
|
||||||
struct rfapi_descriptor *rfd;
|
|
||||||
struct skiplist *sl;
|
|
||||||
struct rfapi_info *ri;
|
|
||||||
struct agg_node *rn;
|
|
||||||
int flags;
|
|
||||||
#define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* remove route from rib
|
|
||||||
*/
|
|
||||||
static void rfapiRibExpireTimer(struct event *t)
|
|
||||||
{
|
{
|
||||||
struct rfapi_rib_tcb *tcb = EVENT_ARG(t);
|
|
||||||
|
|
||||||
RFAPI_RIB_CHECK_COUNTS(1, 0);
|
RFAPI_RIB_CHECK_COUNTS(1, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -309,11 +332,22 @@ static void rfapiRibExpireTimer(struct event *t)
|
||||||
agg_unlock_node(tcb->rn);
|
agg_unlock_node(tcb->rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rrtcb_del(&_rrtcbhash, tcb);
|
||||||
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
||||||
|
|
||||||
RFAPI_RIB_CHECK_COUNTS(1, 0);
|
RFAPI_RIB_CHECK_COUNTS(1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove route from rib
|
||||||
|
*/
|
||||||
|
static void rfapiRibExpireTimer(struct event *t)
|
||||||
|
{
|
||||||
|
struct rfapi_rib_tcb *tcb = EVENT_ARG(t);
|
||||||
|
|
||||||
|
_rfapiRibExpireTimer(tcb);
|
||||||
|
}
|
||||||
|
|
||||||
static void rfapiRibStartTimer(struct rfapi_descriptor *rfd,
|
static void rfapiRibStartTimer(struct rfapi_descriptor *rfd,
|
||||||
struct rfapi_info *ri,
|
struct rfapi_info *ri,
|
||||||
struct agg_node *rn, /* route node attached to */
|
struct agg_node *rn, /* route node attached to */
|
||||||
|
@ -349,6 +383,8 @@ static void rfapiRibStartTimer(struct rfapi_descriptor *rfd,
|
||||||
|
|
||||||
event_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime,
|
event_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime,
|
||||||
&ri->timer);
|
&ri->timer);
|
||||||
|
|
||||||
|
rrtcb_add(&_rrtcbhash, tcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */
|
extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */
|
||||||
|
@ -519,6 +555,7 @@ void rfapiRibClear(struct rfapi_descriptor *rfd)
|
||||||
tcb = EVENT_ARG(
|
tcb = EVENT_ARG(
|
||||||
ri->timer);
|
ri->timer);
|
||||||
EVENT_OFF(ri->timer);
|
EVENT_OFF(ri->timer);
|
||||||
|
rrtcb_del(&_rrtcbhash, tcb);
|
||||||
XFREE(MTYPE_RFAPI_RECENT_DELETE,
|
XFREE(MTYPE_RFAPI_RECENT_DELETE,
|
||||||
tcb);
|
tcb);
|
||||||
}
|
}
|
||||||
|
@ -852,11 +889,6 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||||
int rib_node_started_nonempty = 0;
|
int rib_node_started_nonempty = 0;
|
||||||
int sendingsomeroutes = 0;
|
int sendingsomeroutes = 0;
|
||||||
const struct prefix *p;
|
const struct prefix *p;
|
||||||
#if DEBUG_PROCESS_PENDING_NODE
|
|
||||||
unsigned int count_rib_initial = 0;
|
|
||||||
unsigned int count_pend_vn_initial = 0;
|
|
||||||
unsigned int count_pend_cost_initial = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert(pn);
|
assert(pn);
|
||||||
p = agg_node_get_prefix(pn);
|
p = agg_node_get_prefix(pn);
|
||||||
|
@ -885,19 +917,6 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||||
slPendPt = (struct skiplist *)(pn->aggregate);
|
slPendPt = (struct skiplist *)(pn->aggregate);
|
||||||
lPendCost = (struct list *)(pn->info);
|
lPendCost = (struct list *)(pn->info);
|
||||||
|
|
||||||
#if DEBUG_PROCESS_PENDING_NODE
|
|
||||||
/* debugging */
|
|
||||||
if (slRibPt)
|
|
||||||
count_rib_initial = skiplist_count(slRibPt);
|
|
||||||
|
|
||||||
if (slPendPt)
|
|
||||||
count_pend_vn_initial = skiplist_count(slPendPt);
|
|
||||||
|
|
||||||
if (lPendCost && lPendCost != (struct list *)1)
|
|
||||||
count_pend_cost_initial = lPendCost->count;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle special case: delete all routes at prefix
|
* Handle special case: delete all routes at prefix
|
||||||
*/
|
*/
|
||||||
|
@ -920,6 +939,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||||
|
|
||||||
tcb = EVENT_ARG(ri->timer);
|
tcb = EVENT_ARG(ri->timer);
|
||||||
EVENT_OFF(ri->timer);
|
EVENT_OFF(ri->timer);
|
||||||
|
rrtcb_del(&_rrtcbhash, tcb);
|
||||||
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,6 +1025,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||||
|
|
||||||
tcb = EVENT_ARG(ori->timer);
|
tcb = EVENT_ARG(ori->timer);
|
||||||
EVENT_OFF(ori->timer);
|
EVENT_OFF(ori->timer);
|
||||||
|
rrtcb_del(&_rrtcbhash, tcb);
|
||||||
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,6 +1038,11 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
#if DEBUG_PROCESS_PENDING_NODE
|
||||||
|
vnc_zlog_debug_verbose("%s: slRibPt ri %p matched in pending list",
|
||||||
|
__func__, ori);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Found in pending list. If same lifetime,
|
* Found in pending list. If same lifetime,
|
||||||
* cost, options,
|
* cost, options,
|
||||||
|
@ -1040,16 +1066,12 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||||
rfapi_info_free(
|
rfapi_info_free(
|
||||||
ri); /* grr... */
|
ri); /* grr... */
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#if DEBUG_PROCESS_PENDING_NODE
|
#if DEBUG_PROCESS_PENDING_NODE
|
||||||
vnc_zlog_debug_verbose(
|
vnc_zlog_debug_verbose("%s: same info", __func__);
|
||||||
"%s: slRibPt ri %p matched in pending list, %s",
|
|
||||||
__func__, ori,
|
|
||||||
(same ? "same info"
|
|
||||||
: "different info"));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Go back and delete items from RIB
|
* Go back and delete items from RIB
|
||||||
*/
|
*/
|
||||||
|
@ -1339,6 +1361,7 @@ callback:
|
||||||
|
|
||||||
tcb = EVENT_ARG(ri->timer);
|
tcb = EVENT_ARG(ri->timer);
|
||||||
EVENT_OFF(ri->timer);
|
EVENT_OFF(ri->timer);
|
||||||
|
rrtcb_del(&_rrtcbhash, tcb);
|
||||||
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
|
||||||
}
|
}
|
||||||
RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
|
RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
|
||||||
|
@ -2285,8 +2308,7 @@ static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
|
||||||
/*
|
/*
|
||||||
* This one is for debugging (set stream to NULL to send output to log)
|
* This one is for debugging (set stream to NULL to send output to log)
|
||||||
*/
|
*/
|
||||||
static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
|
static void rfapiRibShowRibSl(void *stream, const struct prefix *pfx, struct skiplist *sl)
|
||||||
struct skiplist *sl)
|
|
||||||
{
|
{
|
||||||
int (*fp)(void *, const char *, ...);
|
int (*fp)(void *, const char *, ...);
|
||||||
struct vty *vty;
|
struct vty *vty;
|
||||||
|
@ -2426,3 +2448,25 @@ void rfapiRibShowResponses(void *stream, struct prefix *pfx_match,
|
||||||
fp(out, "\n");
|
fp(out, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rfapi_rib_init(void)
|
||||||
|
{
|
||||||
|
rrtcb_init(&_rrtcbhash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rfapi_rib_terminate(void)
|
||||||
|
{
|
||||||
|
struct rfapi_rib_tcb *tcb;
|
||||||
|
|
||||||
|
vnc_zlog_debug_verbose("%s: cleaning up %zu pending timers", __func__,
|
||||||
|
rrtcb_count(&_rrtcbhash));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up memory allocations stored in pending timers
|
||||||
|
*/
|
||||||
|
while ((tcb = rrtcb_pop(&_rrtcbhash))) {
|
||||||
|
assert(tcb == EVENT_ARG(tcb->ri->timer));
|
||||||
|
EVENT_OFF(tcb->ri->timer);
|
||||||
|
_rfapiRibExpireTimer(tcb); /* deletes hash entry, frees tcb */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -138,4 +138,7 @@ extern int rfapi_rib_key_cmp(const void *k1, const void *k2);
|
||||||
|
|
||||||
extern void rfapiAdbFree(struct rfapi_adb *adb);
|
extern void rfapiAdbFree(struct rfapi_adb *adb);
|
||||||
|
|
||||||
|
extern void rfapi_rib_init(void);
|
||||||
|
extern void rfapi_rib_terminate(void);
|
||||||
|
|
||||||
#endif /* QUAGGA_HGP_RFAPI_RIB_H */
|
#endif /* QUAGGA_HGP_RFAPI_RIB_H */
|
||||||
|
|
|
@ -4,6 +4,7 @@ hostname r3
|
||||||
password zebra
|
password zebra
|
||||||
log stdout notifications
|
log stdout notifications
|
||||||
log commands
|
log commands
|
||||||
|
#debug bgp vnc verbose
|
||||||
router bgp 5226
|
router bgp 5226
|
||||||
bgp router-id 3.3.3.3
|
bgp router-id 3.3.3.3
|
||||||
bgp cluster-id 3.3.3.3
|
bgp cluster-id 3.3.3.3
|
||||||
|
|
|
@ -91,10 +91,10 @@ luCommand(
|
||||||
)
|
)
|
||||||
|
|
||||||
num = "0 exist"
|
num = "0 exist"
|
||||||
luCommand("r1", 'vtysh -c "show bgp ipv4 vpn"', num, "pass", "VPN SAFI clear")
|
luCommand("r1", 'vtysh -c "show bgp ipv4 vpn"', num, "wait", "VPN SAFI clear")
|
||||||
luCommand("r2", 'vtysh -c "show bgp ipv4 vpn"', num, "pass", "VPN SAFI clear")
|
luCommand("r2", 'vtysh -c "show bgp ipv4 vpn"', num, "wait", "VPN SAFI clear")
|
||||||
luCommand("r3", 'vtysh -c "show bgp ipv4 vpn"', num, "pass", "VPN SAFI clear")
|
luCommand("r3", 'vtysh -c "show bgp ipv4 vpn"', num, "wait", "VPN SAFI clear")
|
||||||
luCommand("r4", 'vtysh -c "show bgp ipv4 vpn"', num, "pass", "VPN SAFI clear")
|
luCommand("r4", 'vtysh -c "show bgp ipv4 vpn"', num, "wait", "VPN SAFI clear")
|
||||||
|
|
||||||
luCommand(
|
luCommand(
|
||||||
"r1",
|
"r1",
|
||||||
|
|
|
@ -4,6 +4,7 @@ hostname r3
|
||||||
password zebra
|
password zebra
|
||||||
log stdout notifications
|
log stdout notifications
|
||||||
log commands
|
log commands
|
||||||
|
#debug bgp vnc verbose
|
||||||
router bgp 5226
|
router bgp 5226
|
||||||
bgp router-id 3.3.3.3
|
bgp router-id 3.3.3.3
|
||||||
bgp cluster-id 3.3.3.3
|
bgp cluster-id 3.3.3.3
|
||||||
|
|
Loading…
Reference in a new issue