forked from Mirror/frr
bfdd: support global BFD reset
Add command 'no bfd' to remove all BFD sessions configuration and fix other daemon integration. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
parent
47a7b00c2d
commit
2a573ff672
30
bfdd/bfd.c
30
bfdd/bfd.c
|
@ -1290,6 +1290,7 @@ static unsigned int bfd_key_hash_do(const void *p);
|
|||
static void _bfd_free(struct hash_bucket *hb,
|
||||
void *arg __attribute__((__unused__)));
|
||||
int _bfd_session_next(struct hash_bucket *hb, void *arg);
|
||||
void _bfd_session_remove_manual(struct hash_bucket *hb, void *arg);
|
||||
|
||||
/* BFD hash for our discriminator. */
|
||||
static unsigned int bfd_id_hash_do(const void *p)
|
||||
|
@ -1587,6 +1588,35 @@ const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
|
|||
return bsi.bsi_bs;
|
||||
}
|
||||
|
||||
void _bfd_session_remove_manual(struct hash_bucket *hb,
|
||||
void *arg __attribute__((__unused__)))
|
||||
{
|
||||
struct bfd_session *bs = hb->data;
|
||||
|
||||
/* Delete only manually configured sessions. */
|
||||
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0)
|
||||
return;
|
||||
|
||||
bs->refcount--;
|
||||
BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
|
||||
|
||||
/* Don't delete sessions still in use. */
|
||||
if (bs->refcount != 0)
|
||||
return;
|
||||
|
||||
bfd_session_free(bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* bfd_sessions_remove_manual: remove all manually configured sessions.
|
||||
*
|
||||
* NOTE: this function doesn't remove automatically created sessions.
|
||||
*/
|
||||
void bfd_sessions_remove_manual(void)
|
||||
{
|
||||
hash_iterate(bfd_key_hash, _bfd_session_remove_manual, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* VRF related functions.
|
||||
*/
|
||||
|
|
|
@ -550,6 +550,7 @@ struct bfd_session *bs_registrate(struct bfd_session *bs);
|
|||
void bfd_session_free(struct bfd_session *bs);
|
||||
const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
|
||||
bool mhop);
|
||||
void bfd_sessions_remove_manual(void);
|
||||
|
||||
/* BFD hash data structures interface */
|
||||
void bfd_initialize(void);
|
||||
|
|
|
@ -52,6 +52,16 @@
|
|||
/*
|
||||
* Functions.
|
||||
*/
|
||||
DEFUN(
|
||||
bfd_config_reset, bfd_config_reset_cmd,
|
||||
"no bfd",
|
||||
NO_STR
|
||||
"Configure BFD peers\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "/frr-bfdd:bfdd/bfd", NB_OP_DESTROY, NULL);
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
void bfd_cli_show_header(struct vty *vty,
|
||||
struct lyd_node *dnode __attribute__((__unused__)),
|
||||
bool show_defaults __attribute__((__unused__)))
|
||||
|
@ -343,6 +353,8 @@ void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode,
|
|||
void
|
||||
bfdd_cli_init(void)
|
||||
{
|
||||
install_element(CONFIG_NODE, &bfd_config_reset_cmd);
|
||||
|
||||
install_element(BFD_NODE, &bfd_peer_enter_cmd);
|
||||
install_element(BFD_NODE, &bfd_no_peer_cmd);
|
||||
|
||||
|
|
|
@ -71,11 +71,27 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
|
|||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
bfd_session_get_key(mhop, dnode, &bk);
|
||||
if (bfd_key_lookup(bk))
|
||||
bs = bfd_key_lookup(bk);
|
||||
|
||||
/* This session was already configured by CLI. */
|
||||
if (bs != NULL && BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG))
|
||||
return NB_ERR_VALIDATION;
|
||||
break;
|
||||
|
||||
case NB_EV_PREPARE:
|
||||
bfd_session_get_key(mhop, dnode, &bk);
|
||||
bs = bfd_key_lookup(bk);
|
||||
|
||||
/* This session was already configured by another daemon. */
|
||||
if (bs != NULL) {
|
||||
/* Now it is configured also by CLI. */
|
||||
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
|
||||
bs->refcount++;
|
||||
|
||||
resource->ptr = bs;
|
||||
break;
|
||||
}
|
||||
|
||||
bs = bfd_session_new();
|
||||
if (bs == NULL)
|
||||
return NB_ERR_RESOURCE;
|
||||
|
@ -84,6 +100,7 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
|
|||
bfd_session_get_key(mhop, dnode, &bs->key);
|
||||
|
||||
/* Set configuration flags. */
|
||||
bs->refcount = 1;
|
||||
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
|
||||
if (mhop)
|
||||
BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_MH);
|
||||
|
@ -95,14 +112,18 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
|
|||
|
||||
case NB_EV_APPLY:
|
||||
bs = resource->ptr;
|
||||
if (bs_registrate(bs) == NULL)
|
||||
|
||||
/* Only attempt to registrate if freshly allocated. */
|
||||
if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL)
|
||||
return NB_ERR_RESOURCE;
|
||||
|
||||
nb_running_set_entry(dnode, bs);
|
||||
break;
|
||||
|
||||
case NB_EV_ABORT:
|
||||
bfd_session_free(resource->ptr);
|
||||
bs = resource->ptr;
|
||||
if (bs->refcount <= 1)
|
||||
bfd_session_free(resource->ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -112,6 +133,7 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
|
|||
int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode,
|
||||
bool mhop)
|
||||
{
|
||||
struct bfd_session *bs;
|
||||
struct bfd_key bk;
|
||||
|
||||
switch (event) {
|
||||
|
@ -126,7 +148,18 @@ int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode,
|
|||
break;
|
||||
|
||||
case NB_EV_APPLY:
|
||||
bfd_session_free(nb_running_unset_entry(dnode));
|
||||
bs = nb_running_unset_entry(dnode);
|
||||
/* CLI is not using this session anymore. */
|
||||
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0)
|
||||
break;
|
||||
|
||||
BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
|
||||
bs->refcount--;
|
||||
/* There are still daemons using it. */
|
||||
if (bs->refcount > 0)
|
||||
break;
|
||||
|
||||
bfd_session_free(bs);
|
||||
break;
|
||||
|
||||
case NB_EV_ABORT:
|
||||
|
@ -152,7 +185,24 @@ static int bfdd_bfd_create(enum nb_event event,
|
|||
|
||||
static int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode)
|
||||
{
|
||||
/* NOTHING */
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
/* NOTHING */
|
||||
return NB_OK;
|
||||
|
||||
case NB_EV_PREPARE:
|
||||
/* NOTHING */
|
||||
return NB_OK;
|
||||
|
||||
case NB_EV_APPLY:
|
||||
bfd_sessions_remove_manual();
|
||||
break;
|
||||
|
||||
case NB_EV_ABORT:
|
||||
/* NOTHING */
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue