forked from Mirror/frr
Merge pull request #18546 from LabNConsulting/ziemba/250330-rfapi-mem-cleanup
bgpd: rfapi: track outstanding rib and import timers, free mem at exit
This commit is contained in:
commit
e0a97e5b85
|
@ -8972,6 +8972,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,
|
||||||
|
|
|
@ -3545,6 +3545,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();
|
||||||
|
|
||||||
|
@ -3575,6 +3577,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);
|
||||||
}
|
}
|
||||||
|
@ -4480,6 +4515,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
|
||||||
|
@ -4804,3 +4840,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