Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pimd: implement MSDP shutdown command #17502

Merged
merged 3 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/user/pim.rst
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ Commands available for MSDP

To apply it immediately call `clear ip msdp peer A.B.C.D`.

.. clicmd:: msdp shutdown

Shutdown the MSDP sessions in this PIM instance.


.. _show-pim-information:

Expand Down
19 changes: 19 additions & 0 deletions pimd/pim_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -7560,6 +7560,24 @@ DEFPY_ATTR(no_ip_pim_msdp_mesh_group,
return ret;
}

DEFPY(msdp_shutdown,
msdp_shutdown_cmd,
"[no] msdp shutdown",
NO_STR
CFG_MSDP_STR
"Shutdown MSDP operation\n")
{
char xpath_value[XPATH_MAXLEN];

snprintf(xpath_value, sizeof(xpath_value), "./msdp/shutdown");
if (no)
nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
else
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");

return nb_cli_apply_changes(vty, NULL);
}

static void ip_msdp_show_mesh_group(struct vty *vty, struct pim_msdp_mg *mg,
struct json_object *json)
{
Expand Down Expand Up @@ -8954,6 +8972,7 @@ void pim_cmd_init(void)
install_element(PIM_NODE, &no_pim_msdp_mesh_group_cmd);
install_element(PIM_NODE, &msdp_log_neighbor_changes_cmd);
install_element(PIM_NODE, &msdp_log_sa_changes_cmd);
install_element(PIM_NODE, &msdp_shutdown_cmd);

install_element(PIM_NODE, &pim_bsr_candidate_rp_cmd);
install_element(PIM_NODE, &pim_bsr_candidate_rp_group_cmd);
Expand Down
50 changes: 50 additions & 0 deletions pimd/pim_msdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,10 @@ static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp)
* a tcp connection will be made */
static void pim_msdp_peer_connect(struct pim_msdp_peer *mp)
{
/* Stop here if we are shutdown. */
if (mp->pim->msdp.shutdown)
return;

mp->state = PIM_MSDP_CONNECTING;
if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
Expand All @@ -744,6 +748,10 @@ static void pim_msdp_peer_connect(struct pim_msdp_peer *mp)
/* 11.2.A3: passive peer - just listen for connections */
static void pim_msdp_peer_listen(struct pim_msdp_peer *mp)
{
/* Stop here if we are shutdown. */
if (mp->pim->msdp.shutdown)
return;

mp->state = PIM_MSDP_LISTEN;
if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
Expand Down Expand Up @@ -1311,6 +1319,9 @@ bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim)
written = true;
}

if (pim->msdp.shutdown)
vty_out(vty, " msdp shutdown\n");

return written;
}

Expand Down Expand Up @@ -1431,3 +1442,42 @@ struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_add(struct pim_instance *pim,

return mbr;
}

void pim_msdp_shutdown(struct pim_instance *pim, bool state)
{
struct pim_msdp_peer *peer;
struct listnode *node;

/* Same value nothing to do. */
if (pim->msdp.shutdown == state)
return;

if (state) {
pim->msdp.shutdown = true;

for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, peer)) {
/* Stop the tcp connection and shutdown all timers */
pim_msdp_peer_stop_tcp_conn(peer, true);

/* Stop listening socket if any. */
event_cancel(&peer->auth_listen_ev);
if (peer->auth_listen_sock != -1)
close(peer->auth_listen_sock);

/* Disable and remove listener flag. */
UNSET_FLAG(pim->msdp.flags, PIM_MSDPF_ENABLE | PIM_MSDPF_LISTENER);
}
} else {
pim->msdp.shutdown = false;

for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, peer)) {
/* Start connection again. */
if (PIM_MSDP_PEER_IS_LISTENER(peer))
pim_msdp_peer_listen(peer);
else
pim_msdp_peer_connect(peer);

SET_FLAG(pim->msdp.flags, PIM_MSDPF_ENABLE);
}
}
}
15 changes: 15 additions & 0 deletions pimd/pim_msdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ struct pim_msdp {
uint32_t keep_alive;
/** MSDP global connection retry period. */
uint32_t connection_retry;

/** MSDP operation state. */
bool shutdown;
};

#define PIM_MSDP_PEER_READ_ON(mp) \
Expand Down Expand Up @@ -327,6 +330,14 @@ void pim_msdp_peer_change_source(struct pim_msdp_peer *mp,
*/
void pim_msdp_peer_restart(struct pim_msdp_peer *mp);

/**
* Toggle MSDP functionality administrative state.
*
* \param pim PIM instance we want to shutdown.
* \param state shutdown state.
*/
void pim_msdp_shutdown(struct pim_instance *pim, bool state);

#else /* PIM_IPV == 6 */
static inline void pim_msdp_init(struct pim_instance *pim,
struct event_loop *master)
Expand Down Expand Up @@ -370,6 +381,10 @@ static inline bool pim_msdp_peer_config_write(struct vty *vty,
{
return false;
}

static inline void pim_msdp_shutdown(struct pim_instance *pim, bool state)
{
}
#endif /* PIM_IPV == 6 */

#endif
6 changes: 6 additions & 0 deletions pimd/pim_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ const struct frr_yang_module_info frr_pim_info = {
.modify = pim_msdp_log_sa_events_modify,
}
},
{
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/shutdown",
.cbs = {
.modify = pim_msdp_shutdown_modify,
}
},
{
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups",
.cbs = {
Expand Down
1 change: 1 addition & 0 deletions pimd/pim_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ int pim_msdp_keep_alive_modify(struct nb_cb_modify_args *args);
int pim_msdp_connection_retry_modify(struct nb_cb_modify_args *args);
int pim_msdp_log_neighbor_events_modify(struct nb_cb_modify_args *args);
int pim_msdp_log_sa_events_modify(struct nb_cb_modify_args *args);
int pim_msdp_shutdown_modify(struct nb_cb_modify_args *args);
int pim_msdp_mesh_group_create(struct nb_cb_create_args *args);
int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args);
int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args);
Expand Down
27 changes: 27 additions & 0 deletions pimd/pim_nb_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@ pim6_msdp_err(pim_msdp_peer_authentication_key_modify, nb_cb_modify_args);
pim6_msdp_err(pim_msdp_peer_authentication_key_destroy, nb_cb_destroy_args);
pim6_msdp_err(pim_msdp_log_neighbor_events_modify, nb_cb_modify_args);
pim6_msdp_err(pim_msdp_log_sa_events_modify, nb_cb_modify_args);
pim6_msdp_err(pim_msdp_shutdown_modify, nb_cb_modify_args);

#if PIM_IPV != 6
/*
Expand Down Expand Up @@ -1158,6 +1159,32 @@ int pim_msdp_log_sa_events_modify(struct nb_cb_modify_args *args)
return NB_OK;
}

/*
* XPath:
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/shutdown
*/
int pim_msdp_shutdown_modify(struct nb_cb_modify_args *args)
{
struct pim_instance *pim;
struct vrf *vrf;

switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
/* NOTHING */
break;

case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
pim = vrf->info;
pim_msdp_shutdown(pim, yang_dnode_get_bool(args->dnode, NULL));
break;
}

return NB_OK;
}

/*
* XPath:
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups
Expand Down
51 changes: 47 additions & 4 deletions tests/topotests/msdp_topo1/test_msdp_topo1.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,15 +521,58 @@ def test_msdp_log_events():
r1_log = tgen.gears["r1"].net.getLog("log", "pimd")

# Look up for informational messages that should have been enabled.
match = re.search(
"MSDP peer 192.168.1.2 state changed to established", r1_log)
match = re.search("MSDP peer 192.168.1.2 state changed to established", r1_log)
assert match is not None

match = re.search(
r"MSDP SA \(192.168.10.100\,229.1.2.3\) created", r1_log)
match = re.search(r"MSDP SA \(192.168.10.100\,229.1.2.3\) created", r1_log)
assert match is not None


def test_msdp_shutdown():
"Shutdown MSDP sessions between r1, r2, r3, then check the state."

tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)

tgen.gears["r1"].vtysh_cmd(
"""
configure terminal
router pim
msdp shutdown
"""
)

r1_expect = {
"192.168.0.2": {
"state": "inactive",
},
"192.168.1.2": {
"state": "inactive",
},
}
r2_expect = {
"192.168.0.1": {
"state": "listen",
}
}
r3_expect = {
"192.168.1.1": {
"state": "listen",
}
}
for router in [("r1", r1_expect), ("r2", r2_expect), ("r3", r3_expect)]:
test_func = partial(
topotest.router_json_cmp,
tgen.gears[router[0]],
"show ip msdp peer json",
router[1],
)
logger.info("Waiting for {} msdp peer data".format(router[0]))
_, val = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert val is None, "multicast route convergence failure"


def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
Expand Down
7 changes: 7 additions & 0 deletions yang/frr-pim.yang
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ module frr-pim {
description
"Log all MSDP SA related events.";
}

leaf shutdown {
type boolean;
default false;
description
"Shutdown MSDP functionality.";
}
}

list msdp-mesh-groups {
Expand Down
Loading