summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/dplane.c3
-rw-r--r--ospfd/ospf_asbr.c70
-rw-r--r--ospfd/ospf_asbr.h4
-rw-r--r--ospfd/ospf_lsa.c7
-rw-r--r--ospfd/ospf_vty.c3
-rw-r--r--ospfd/ospf_zebra.c30
-rw-r--r--ospfd/ospf_zebra.h3
-rw-r--r--pimd/pim_cmd.c33
-rw-r--r--pimd/pim_instance.c10
-rw-r--r--pimd/pim_instance.h10
-rw-r--r--pimd/pim_msdp.c201
-rw-r--r--pimd/pim_msdp.h7
-rw-r--r--pimd/pim_msdp_packet.c27
-rw-r--r--pimd/pim_msdp_socket.c29
-rw-r--r--pimd/pim_nb.c12
-rw-r--r--pimd/pim_nb.h2
-rw-r--r--pimd/pim_nb_config.c60
-rw-r--r--tests/topotests/msdp_topo1/r1/pimd.conf2
-rwxr-xr-xtests/topotests/msdp_topo1/test_msdp_topo1.py20
-rw-r--r--tests/topotests/ospf_multi_instance/r1/frr.conf19
-rw-r--r--tests/topotests/ospf_multi_instance/r2/frr.conf37
-rw-r--r--tests/topotests/ospf_multi_instance/r3/frr.conf19
-rw-r--r--tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py403
-rw-r--r--tools/etc/frr/support_bundle_commands.conf23
-rw-r--r--yang/frr-pim.yang14
25 files changed, 873 insertions, 175 deletions
diff --git a/bfdd/dplane.c b/bfdd/dplane.c
index 7f55f34073..b1a32fb150 100644
--- a/bfdd/dplane.c
+++ b/bfdd/dplane.c
@@ -948,6 +948,9 @@ static void bfd_dplane_client_connect(struct event *t)
_bfd_dplane_client_bootstrap(bdc);
}
+ /* Continue with the connection */
+ return;
+
reschedule_connect:
EVENT_OFF(bdc->inbufev);
EVENT_OFF(bdc->outbufev);
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index b47c390088..738ac6d8cf 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -168,6 +168,38 @@ void ospf_external_info_delete(struct ospf *ospf, uint8_t type,
}
}
+/*
+ * ospf_external_info_delete_multi_instance
+ *
+ * Delete instances of the external route information for a given route type.
+ * The preserve_instance parameter may be used to prevent the current instance
+ * from being deleted.
+ */
+void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type, struct prefix_ipv4 p,
+ unsigned long preserve_instance)
+{
+ struct route_node *rn;
+ struct ospf_external *ext;
+ struct list *ext_list;
+ struct listnode *node;
+
+ ext_list = ospf->external[type];
+ if (!ext_list)
+ return;
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ if (ext->instance != preserve_instance) {
+ rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
+ if (rn) {
+ ospf_external_info_free(rn->info);
+ rn->info = NULL;
+ route_unlock_node(rn);
+ route_unlock_node(rn);
+ }
+ }
+ }
+}
+
struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
unsigned short instance,
struct prefix_ipv4 *p)
@@ -189,6 +221,44 @@ struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
return NULL;
}
+/*
+ * ospf_external_info_default_lookup
+ *
+ * For default information criteria, we really don't care about the
+ * source of the route and there only should be one.
+ */
+struct external_info *ospf_external_info_default_lookup(struct ospf *ospf)
+{
+ struct ospf_external *ext;
+ struct external_info *ei;
+ struct list *ext_list;
+ struct listnode *node;
+ struct route_node *rn;
+ struct prefix_ipv4 p = {
+ .family = AF_INET,
+ .prefixlen = 0,
+ .prefix.s_addr = INADDR_ANY,
+ };
+
+ ext_list = ospf->external[DEFAULT_ROUTE];
+ if (!ext_list)
+ return (NULL);
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
+ if (rn) {
+ route_unlock_node(rn);
+ if (rn->info) {
+ ei = rn->info;
+ if (ei->type != ZEBRA_ROUTE_OSPF || ei->instance != ospf->instance)
+ return ei;
+ }
+ }
+ }
+
+ return NULL;
+}
+
struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf,
struct prefix_ipv4 *p)
{
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
index 6158d65f22..648a5a11ae 100644
--- a/ospfd/ospf_asbr.h
+++ b/ospfd/ospf_asbr.h
@@ -109,6 +109,10 @@ ospf_external_info_add(struct ospf *, uint8_t, unsigned short,
route_tag_t, uint32_t metric);
extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,
struct prefix_ipv4);
+extern void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type,
+ struct prefix_ipv4 p,
+ unsigned long preserve_instance);
+#define OSPF_DELETE_ANY_INSTANCE 0xffffffff
extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
unsigned short,
struct prefix_ipv4 *);
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 1350487898..7354223397 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2407,15 +2407,10 @@ struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
static struct external_info *ospf_default_external_info(struct ospf *ospf)
{
int type;
- struct prefix_ipv4 p;
struct external_info *default_ei;
int ret = 0;
- p.family = AF_INET;
- p.prefix.s_addr = 0;
- p.prefixlen = 0;
-
- default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, 0, &p);
+ default_ei = ospf_external_info_default_lookup(ospf);
if (!default_ei)
return NULL;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 0457b13337..27528f6594 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -7347,6 +7347,9 @@ DEFPY (show_ip_ospf_database,
struct in_addr *adv_router_p = NULL;
json_object *json = NULL;
+ if (instance_id != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
if (uj)
json = json_object_new_object();
if (lsid_str)
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index c7cba1e20f..b718d498ae 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1292,15 +1292,14 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
* originate)ZEBRA_ROUTE_MAX is used to delete the ex-info.
* Resolved this inconsistency by maintaining same route type.
*/
- if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF))
+ if ((is_default_prefix(&pgen)) &&
+ ((api.type != ZEBRA_ROUTE_OSPF) || (api.instance != ospf->instance)))
rt_type = DEFAULT_ROUTE;
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
- zlog_debug("%s: cmd %s from client %s: vrf %s(%u), p %pFX, metric %d",
- __func__, zserv_command_string(cmd),
- zebra_route_string(api.type),
- ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix,
- api.metric);
+ zlog_debug("%s: cmd %s from client %s-%d: vrf %s(%u), p %pFX, metric %d", __func__,
+ zserv_command_string(cmd), zebra_route_string(api.type), api.instance,
+ ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix, api.metric);
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
/* XXX|HACK|TODO|FIXME:
@@ -1315,16 +1314,17 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
api.tag = ospf->dtag[rt_type];
/*
- * Given zebra sends update for a prefix via ADD message, it
- * should
- * be considered as an implicit DEL for that prefix with other
- * source
- * types.
+ * Given zebra sends an update for a prefix via an ADD message, it
+ * will be considered as an impilict DELETE for that prefix for other
+ * types and instances other than the type and instance associated with
+ * the prefix.
*/
- for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
- if (i != rt_type)
- ospf_external_info_delete(ospf, i, api.instance,
- p);
+ for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+ unsigned long preserve_instance;
+
+ preserve_instance = (i == rt_type) ? api.instance : OSPF_DELETE_ANY_INSTANCE;
+ ospf_external_info_delete_multi_instance(ospf, i, p, preserve_instance);
+ }
ei = ospf_external_info_add(ospf, rt_type, api.instance, p,
ifindex, nexthop, api.tag,
diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h
index 86a5678fc4..b83524303f 100644
--- a/ospfd/ospf_zebra.h
+++ b/ospfd/ospf_zebra.h
@@ -47,6 +47,9 @@ extern uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *,
struct ospf_route *);
extern struct ospf_external *ospf_external_lookup(struct ospf *, uint8_t,
unsigned short);
+
+extern struct external_info *ospf_external_info_default_lookup(struct ospf *ospf);
+
extern struct ospf_external *ospf_external_add(struct ospf *, uint8_t,
unsigned short);
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 732dd2971c..a2a4c34931 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -8288,6 +8288,37 @@ DEFUN (show_ip_msdp_sa_sg_vrf_all,
return CMD_SUCCESS;
}
+DEFPY(msdp_log_neighbor_changes, msdp_log_neighbor_changes_cmd,
+ "[no] msdp log neighbor-events",
+ NO_STR
+ MSDP_STR
+ "MSDP log messages\n"
+ "MSDP log neighbor event messages\n")
+{
+ char xpath_value[XPATH_MAXLEN + 32];
+
+ snprintf(xpath_value, sizeof(xpath_value), "%s/msdp/log-neighbor-events", VTY_CURR_XPATH);
+ nb_cli_enqueue_change(vty, xpath_value, no ? NB_OP_DESTROY : NB_OP_MODIFY, "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY(msdp_log_sa_changes, msdp_log_sa_changes_cmd,
+ "[no] msdp log sa-events",
+ NO_STR
+ MSDP_STR
+ "MSDP log messages\n"
+ "MSDP log SA event messages\n")
+{
+ char xpath_value[XPATH_MAXLEN + 32];
+
+ snprintf(xpath_value, sizeof(xpath_value), "%s/msdp/log-sa-events", VTY_CURR_XPATH);
+ nb_cli_enqueue_change(vty, xpath_value, no ? NB_OP_DESTROY : NB_OP_MODIFY, "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+
struct pim_sg_cache_walk_data {
struct vty *vty;
json_object *json;
@@ -8921,6 +8952,8 @@ void pim_cmd_init(void)
install_element(PIM_NODE, &pim_msdp_mesh_group_source_cmd);
install_element(PIM_NODE, &no_pim_msdp_mesh_group_source_cmd);
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, &pim_bsr_candidate_rp_cmd);
install_element(PIM_NODE, &pim_bsr_candidate_rp_group_cmd);
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
index e18ae97d6f..4e4e5a6ce8 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -272,3 +272,13 @@ void pim_vrf_terminate(void)
vrf_terminate();
}
+
+bool pim_msdp_log_neighbor_events(const struct pim_instance *pim)
+{
+ return (pim->log_flags & PIM_MSDP_LOG_NEIGHBOR_EVENTS);
+}
+
+bool pim_msdp_log_sa_events(const struct pim_instance *pim)
+{
+ return (pim->log_flags & PIM_MSDP_LOG_SA_EVENTS);
+}
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index 1b7815d86c..dab7ed2698 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -192,6 +192,13 @@ struct pim_instance {
uint64_t gm_rx_drop_sys;
+ /** Log information flags. */
+ uint32_t log_flags;
+/** Log neighbor event messages. */
+#define PIM_MSDP_LOG_NEIGHBOR_EVENTS 0x01
+/** Log SA event messages. */
+#define PIM_MSDP_LOG_SA_EVENTS 0x02
+
bool stopping;
#if PIM_IPV == 6
@@ -218,4 +225,7 @@ extern struct pim_router *router;
struct pim_instance *pim_get_pim_instance(vrf_id_t vrf_id);
+extern bool pim_msdp_log_neighbor_events(const struct pim_instance *pim);
+extern bool pim_msdp_log_sa_events(const struct pim_instance *pim);
+
#endif
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c
index 215cc3c502..a536ab6fe0 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -47,20 +47,13 @@ static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2);
static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr);
/************************ SA cache management ******************************/
-static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa,
- const char *timer_str)
-{
- zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str);
-}
-
/* RFC-3618:Sec-5.1 - global active source advertisement timer */
static void pim_msdp_sa_adv_timer_cb(struct event *t)
{
struct pim_instance *pim = EVENT_ARG(t);
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA advertisement timer expired");
- }
+ if (pim_msdp_log_sa_events(pim))
+ zlog_info("MSDP SA advertisement timer expired");
pim_msdp_sa_adv_timer_setup(pim, true /* start */);
pim_msdp_pkt_sa_tx(pim);
@@ -83,9 +76,8 @@ static void pim_msdp_sa_state_timer_cb(struct event *t)
sa = EVENT_ARG(t);
- if (PIM_DEBUG_MSDP_EVENTS) {
- pim_msdp_sa_timer_expiry_log(sa, "state");
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s state timer expired", sa->sg_str);
pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER);
}
@@ -120,9 +112,8 @@ static void pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa)
sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG;
}
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s de-referenced SPT", sa->sg_str);
}
static bool pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa,
@@ -185,10 +176,8 @@ static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa,
if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) {
/* somehow we lost track of the upstream ptr? best log it */
sa->up = up;
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s SPT reference missing",
- sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s SPT reference missing", sa->sg_str);
return;
}
@@ -204,14 +193,11 @@ static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa,
/* should we also start the kat in parallel? we will need it
* when the
* SA ages out */
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s referenced SPT", sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s referenced SPT", sa->sg_str);
} else {
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s SPT reference failed",
- sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s SPT reference failed", sa->sg_str);
}
}
@@ -240,9 +226,8 @@ static struct pim_msdp_sa *pim_msdp_sa_new(struct pim_instance *pim,
sa = hash_get(pim->msdp.sa_hash, sa, hash_alloc_intern);
listnode_add_sort(pim->msdp.sa_list, sa);
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s created", sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(pim))
+ zlog_info("MSDP SA %s created", sa->sg_str);
return sa;
}
@@ -282,9 +267,8 @@ static void pim_msdp_sa_del(struct pim_msdp_sa *sa)
listnode_delete(sa->pim->msdp.sa_list, sa);
hash_release(sa->pim->msdp.sa_hash, sa);
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s deleted", sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s deleted", sa->sg_str);
/* free up any associated memory */
pim_msdp_sa_free(sa);
@@ -333,10 +317,9 @@ static void pim_msdp_sa_deref(struct pim_msdp_sa *sa,
if ((sa->flags & PIM_MSDP_SAF_LOCAL)) {
if (flags & PIM_MSDP_SAF_LOCAL) {
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s local reference removed",
- sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s local reference removed", sa->sg_str);
+
if (sa->pim->msdp.local_cnt)
--sa->pim->msdp.local_cnt;
}
@@ -346,10 +329,9 @@ static void pim_msdp_sa_deref(struct pim_msdp_sa *sa,
if (flags & PIM_MSDP_SAF_PEER) {
struct in_addr rp;
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s peer reference removed",
- sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP SA %s peer reference removed", sa->sg_str);
+
pim_msdp_sa_state_timer_setup(sa, false /* start */);
rp.s_addr = INADDR_ANY;
pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp);
@@ -386,10 +368,8 @@ void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
if (mp) {
if (!(sa->flags & PIM_MSDP_SAF_PEER)) {
sa->flags |= PIM_MSDP_SAF_PEER;
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s added by peer",
- sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(pim))
+ zlog_info("MSDP SA %s added by peer", sa->sg_str);
}
pim_msdp_sa_peer_ip_set(sa, mp, rp);
/* start/re-start the state timer to prevent cache expiry */
@@ -403,10 +383,9 @@ void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) {
sa->flags |= PIM_MSDP_SAF_LOCAL;
++sa->pim->msdp.local_cnt;
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP SA %s added locally",
- sa->sg_str);
- }
+ if (pim_msdp_log_sa_events(pim))
+ zlog_info("MSDP SA %s added locally", sa->sg_str);
+
/* send an immediate SA update to peers */
pim_addr_to_prefix(&grp, sa->sg.grp);
rp_info = pim_rp_find_match_group(pim, &grp);
@@ -710,6 +689,9 @@ bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp)
return true;
}
+ if (pim_msdp_log_sa_events(mp->pim))
+ zlog_info("MSDP peer %pI4 RPF failure for %pI4", &mp->peer, &rp);
+
return false;
}
@@ -744,7 +726,7 @@ static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp)
char state_str[PIM_MSDP_STATE_STRLEN];
pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
- zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str);
+ zlog_info("MSDP peer %s state changed to %s", mp->key_str, state_str);
}
/* MSDP Connection State Machine actions (defined in RFC-3618:Sec-11.2) */
@@ -753,9 +735,8 @@ static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp)
static void pim_msdp_peer_connect(struct pim_msdp_peer *mp)
{
mp->state = PIM_MSDP_CONNECTING;
- if (PIM_DEBUG_MSDP_EVENTS) {
+ if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
- }
pim_msdp_peer_cr_timer_setup(mp, true /* start */);
}
@@ -764,9 +745,8 @@ static void pim_msdp_peer_connect(struct pim_msdp_peer *mp)
static void pim_msdp_peer_listen(struct pim_msdp_peer *mp)
{
mp->state = PIM_MSDP_LISTEN;
- if (PIM_DEBUG_MSDP_EVENTS) {
+ if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
- }
/* this is interntionally asymmetric i.e. we set up listen-socket when
* the
@@ -790,9 +770,8 @@ void pim_msdp_peer_established(struct pim_msdp_peer *mp)
mp->state = PIM_MSDP_ESTABLISHED;
mp->uptime = pim_time_monotonic_sec();
- if (PIM_DEBUG_MSDP_EVENTS) {
+ if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
- }
/* stop retry timer on active peers */
pim_msdp_peer_cr_timer_setup(mp, false /* start */);
@@ -816,9 +795,9 @@ void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state)
++mp->est_flaps;
}
mp->state = PIM_MSDP_INACTIVE;
- if (PIM_DEBUG_MSDP_EVENTS) {
+
+ if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
- }
}
if (PIM_DEBUG_MSDP_INTERNAL) {
@@ -851,10 +830,10 @@ void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state)
/* RFC-3618:Sec-5.6 - stop the peer tcp connection and startover */
void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str)
{
- if (PIM_DEBUG_EVENTS) {
- zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str);
- snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str);
- }
+ if (pim_msdp_log_neighbor_events(mp->pim))
+ zlog_info("MSDP peer %s tcp reset %s", mp->key_str, rc_str);
+
+ snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str);
/* close the connection and transition to listening or connecting */
pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */);
@@ -865,12 +844,6 @@ void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str)
}
}
-static void pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp,
- const char *timer_str)
-{
- zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str);
-}
-
/* RFC-3618:Sec-5.4 - peer hold timer */
static void pim_msdp_peer_hold_timer_cb(struct event *t)
{
@@ -878,17 +851,16 @@ static void pim_msdp_peer_hold_timer_cb(struct event *t)
mp = EVENT_ARG(t);
- if (PIM_DEBUG_MSDP_EVENTS) {
- pim_msdp_peer_timer_expiry_log(mp, "hold");
- }
+ if (pim_msdp_log_neighbor_events(mp->pim))
+ zlog_info("MSDP peer %s hold timer expired", mp->key_str);
if (mp->state != PIM_MSDP_ESTABLISHED) {
return;
}
- if (PIM_DEBUG_MSDP_EVENTS) {
+ if (pim_msdp_log_neighbor_events(mp->pim))
pim_msdp_peer_state_chg_log(mp);
- }
+
pim_msdp_peer_reset_tcp_conn(mp, "ht-expired");
}
@@ -910,9 +882,8 @@ static void pim_msdp_peer_ka_timer_cb(struct event *t)
mp = EVENT_ARG(t);
- if (PIM_DEBUG_MSDP_EVENTS) {
- pim_msdp_peer_timer_expiry_log(mp, "ka");
- }
+ if (pim_msdp_log_neighbor_events(mp->pim))
+ zlog_info("MSDP peer %s keep alive timer expired", mp->key_str);
pim_msdp_pkt_ka_tx(mp);
pim_msdp_peer_ka_timer_setup(mp, true /* start */);
@@ -970,9 +941,8 @@ static void pim_msdp_peer_cr_timer_cb(struct event *t)
mp = EVENT_ARG(t);
- if (PIM_DEBUG_MSDP_EVENTS) {
- pim_msdp_peer_timer_expiry_log(mp, "connect-retry");
- }
+ if (pim_msdp_log_neighbor_events(mp->pim))
+ zlog_info("MSDP peer %s connection retry timer expired", mp->key_str);
if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) {
return;
@@ -1012,16 +982,6 @@ void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp)
}
}
-static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr)
-{
- sockunion_init(su);
- su->sin.sin_addr = addr;
- su->sin.sin_family = AF_INET;
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- su->sin.sin_len = sizeof(struct sockaddr_in);
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
-}
-
/* 11.2.A1: create a new peer and transition state to listen or connecting */
struct pim_msdp_peer *pim_msdp_peer_add(struct pim_instance *pim,
const struct in_addr *peer,
@@ -1037,11 +997,9 @@ struct pim_msdp_peer *pim_msdp_peer_add(struct pim_instance *pim,
mp->pim = pim;
mp->peer = *peer;
pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str));
- pim_msdp_addr2su(&mp->su_peer, mp->peer);
mp->local = *local;
/* XXX: originator_id setting needs to move to the mesh group */
pim->msdp.originator_id = *local;
- pim_msdp_addr2su(&mp->su_local, mp->local);
if (mesh_group_name)
mp->mesh_group_name =
XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name);
@@ -1063,8 +1021,8 @@ struct pim_msdp_peer *pim_msdp_peer_add(struct pim_instance *pim,
mp = hash_get(pim->msdp.peer_hash, mp, hash_alloc_intern);
listnode_add_sort(pim->msdp.peer_list, mp);
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP peer %s created", mp->key_str);
+ if (pim_msdp_log_neighbor_events(pim)) {
+ zlog_info("MSDP peer %s created", mp->key_str);
pim_msdp_peer_state_chg_log(mp);
}
@@ -1078,8 +1036,7 @@ struct pim_msdp_peer *pim_msdp_peer_add(struct pim_instance *pim,
return mp;
}
-struct pim_msdp_peer *pim_msdp_peer_find(struct pim_instance *pim,
- struct in_addr peer_addr)
+struct pim_msdp_peer *pim_msdp_peer_find(const struct pim_instance *pim, struct in_addr peer_addr)
{
struct pim_msdp_peer lookup;
@@ -1129,9 +1086,8 @@ void pim_msdp_peer_del(struct pim_msdp_peer **mp)
listnode_delete((*mp)->pim->msdp.peer_list, *mp);
hash_release((*mp)->pim->msdp.peer_hash, *mp);
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP peer %s deleted", (*mp)->key_str);
- }
+ if (pim_msdp_log_neighbor_events((*mp)->pim))
+ zlog_info("MSDP peer %s deleted", (*mp)->key_str);
/* free up any associated memory */
pim_msdp_peer_free(*mp);
@@ -1206,10 +1162,8 @@ void pim_msdp_mg_free(struct pim_instance *pim, struct pim_msdp_mg **mgp)
for (ALL_LIST_ELEMENTS((*mgp)->mbr_list, n, nn, mbr))
pim_msdp_mg_mbr_del((*mgp), mbr);
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP mesh-group %s deleted",
- (*mgp)->mesh_group_name);
- }
+ if (pim_msdp_log_neighbor_events(pim))
+ zlog_info("MSDP mesh-group %s deleted", (*mgp)->mesh_group_name);
XFREE(MTYPE_PIM_MSDP_MG_NAME, (*mgp)->mesh_group_name);
@@ -1226,15 +1180,14 @@ struct pim_msdp_mg *pim_msdp_mg_new(struct pim_instance *pim,
struct pim_msdp_mg *mg;
mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg));
-
+ mg->pim = pim;
mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name);
mg->mbr_list = list_new();
mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free;
mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp;
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name);
- }
+ if (pim_msdp_log_neighbor_events(pim))
+ zlog_info("MSDP mesh-group %s created", mg->mesh_group_name);
SLIST_INSERT_HEAD(&pim->msdp.mglist, mg, mg_entry);
@@ -1268,12 +1221,10 @@ void pim_msdp_mg_mbr_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr)
}
listnode_delete(mg->mbr_list, mbr);
- if (PIM_DEBUG_MSDP_EVENTS) {
- char ip_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str));
- zlog_debug("MSDP mesh-group %s mbr %s deleted",
- mg->mesh_group_name, ip_str);
- }
+ if (pim_msdp_log_neighbor_events(mg->pim))
+ zlog_info("MSDP mesh-group %s neighbor %pI4 deleted", mg->mesh_group_name,
+ &mbr->mbr_ip);
+
pim_msdp_mg_mbr_free(mbr);
if (mg->mbr_cnt) {
--mg->mbr_cnt;
@@ -1290,10 +1241,9 @@ static void pim_msdp_src_del(struct pim_msdp_mg *mg)
if (mbr->mp)
pim_msdp_peer_del(&mbr->mp);
}
- if (PIM_DEBUG_MSDP_EVENTS) {
- zlog_debug("MSDP mesh-group %s src cleared",
- mg->mesh_group_name);
- }
+
+ if (pim_msdp_log_neighbor_events(mg->pim))
+ zlog_info("MSDP mesh-group %s source cleared", mg->mesh_group_name);
}
/*********************** MSDP feature APIs *********************************/
@@ -1305,6 +1255,11 @@ int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty)
char src_str[INET_ADDRSTRLEN];
int count = 0;
+ if (pim_msdp_log_neighbor_events(pim))
+ vty_out(vty, " msdp log neighbor-events\n");
+ if (pim_msdp_log_sa_events(pim))
+ vty_out(vty, " msdp log sa-events\n");
+
if (SLIST_EMPTY(&pim->msdp.mglist))
return count;
@@ -1439,9 +1394,8 @@ void pim_msdp_mg_src_add(struct pim_instance *pim, struct pim_msdp_mg *mg,
/* No new address, disable everyone. */
if (ai->s_addr == INADDR_ANY) {
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP mesh-group %s src unset",
- mg->mesh_group_name);
+ if (pim_msdp_log_neighbor_events(pim))
+ zlog_info("MSDP mesh-group %s source unset", mg->mesh_group_name);
return;
}
@@ -1450,9 +1404,8 @@ void pim_msdp_mg_src_add(struct pim_instance *pim, struct pim_msdp_mg *mg,
mbr->mp = pim_msdp_peer_add(pim, &mbr->mbr_ip, &mg->src_ip,
mg->mesh_group_name);
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP mesh-group %s src %pI4 set",
- mg->mesh_group_name, &mg->src_ip);
+ if (pim_msdp_log_neighbor_events(pim))
+ zlog_info("MSDP mesh-group %s source %pI4 set", mg->mesh_group_name, &mg->src_ip);
}
struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_add(struct pim_instance *pim,
@@ -1470,9 +1423,9 @@ struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_add(struct pim_instance *pim,
mbr->mp = pim_msdp_peer_add(pim, &mbr->mbr_ip, &mg->src_ip,
mg->mesh_group_name);
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP mesh-group %s mbr %pI4 created",
- mg->mesh_group_name, &mbr->mbr_ip);
+ if (pim_msdp_log_neighbor_events(pim))
+ zlog_info("MSDP mesh-group %s neighbor %pI4 created", mg->mesh_group_name,
+ &mbr->mbr_ip);
++mg->mbr_cnt;
diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h
index f77b0e1a3a..0a7c74e438 100644
--- a/pimd/pim_msdp.h
+++ b/pimd/pim_msdp.h
@@ -114,9 +114,6 @@ struct pim_msdp_peer {
enum pim_msdp_peer_state state;
enum pim_msdp_peer_flags flags;
- /* TCP socket info */
- union sockunion su_local;
- union sockunion su_peer;
int fd;
/* protocol timers */
@@ -168,6 +165,7 @@ struct pim_msdp_mg {
struct in_addr src_ip;
uint32_t mbr_cnt;
struct list *mbr_list;
+ struct pim_instance *pim;
/** Belongs to PIM instance list. */
SLIST_ENTRY(pim_msdp_mg) mg_entry;
@@ -238,8 +236,7 @@ void pim_msdp_init(struct pim_instance *pim, struct event_loop *master);
void pim_msdp_exit(struct pim_instance *pim);
char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf,
int buf_size);
-struct pim_msdp_peer *pim_msdp_peer_find(struct pim_instance *pim,
- struct in_addr peer_addr);
+struct pim_msdp_peer *pim_msdp_peer_find(const struct pim_instance *pim, struct in_addr peer_addr);
void pim_msdp_peer_established(struct pim_msdp_peer *mp);
void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp);
void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state);
diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c
index 27f4966a1c..f66a941ee3 100644
--- a/pimd/pim_msdp_packet.c
+++ b/pimd/pim_msdp_packet.c
@@ -487,9 +487,8 @@ static void pim_msdp_pkt_sa_gen(struct pim_instance *pim,
}
if (msdp_peer_sa_filter(mp, sa)) {
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP peer %pI4 filter SA out %s",
- &mp->peer, sa->sg_str);
+ if (pim_msdp_log_sa_events(pim))
+ zlog_info("MSDP peer %pI4 filter SA out %s", &mp->peer, sa->sg_str);
continue;
}
@@ -551,9 +550,9 @@ void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa)
pim_msdp_pkt_sa_fill_one(sa);
for (ALL_LIST_ELEMENTS_RO(sa->pim->msdp.peer_list, node, mp)) {
if (msdp_peer_sa_filter(mp, sa)) {
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP peer %pI4 filter SA out %s",
- &mp->peer, sa->sg_str);
+ if (pim_msdp_log_sa_events(sa->pim))
+ zlog_info("MSDP peer %pI4 filter SA out %s", &mp->peer, sa->sg_str);
+
continue;
}
@@ -583,9 +582,10 @@ void pim_msdp_pkt_sa_tx_one_to_one_peer(struct pim_msdp_peer *mp,
/* Don't push it if filtered. */
if (msdp_peer_sa_filter(mp, &sa)) {
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP peer %pI4 filter SA out (%pI4, %pI4)",
- &mp->peer, &sa.sg.src, &sa.sg.grp);
+ if (pim_msdp_log_sa_events(mp->pim))
+ zlog_info("MSDP peer %pI4 filter SA out (%pI4, %pI4)", &mp->peer,
+ &sa.sg.src, &sa.sg.grp);
+
return;
}
@@ -641,11 +641,10 @@ static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp)
/* Filter incoming SA with configured access list. */
if (mp->acl_in) {
acl = access_list_lookup(AFI_IP, mp->acl_in);
- if (msdp_access_list_apply(acl, &sg.src, &sg.grp) ==
- FILTER_DENY) {
- if (PIM_DEBUG_MSDP_EVENTS)
- zlog_debug("MSDP peer %pI4 filter SA in (%pI4, %pI4)",
- &mp->peer, &sg.src, &sg.grp);
+ if (msdp_access_list_apply(acl, &sg.src, &sg.grp) == FILTER_DENY) {
+ if (pim_msdp_log_sa_events(mp->pim))
+ zlog_info("MSDP peer %pI4 filter SA in (%pI4, %pI4)", &mp->peer,
+ &sg.src, &sg.grp);
return;
}
}
diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c
index 2fb0bb87c7..b29993304d 100644
--- a/pimd/pim_msdp_socket.c
+++ b/pimd/pim_msdp_socket.c
@@ -49,6 +49,16 @@ static void pim_msdp_update_sock_send_buffer_size(int fd)
}
}
+static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr)
+{
+ sockunion_init(su);
+ su->sin.sin_addr = addr;
+ su->sin.sin_family = AF_INET;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ su->sin.sin_len = sizeof(struct sockaddr_in);
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
+}
+
/**
* Helper function to reduce code duplication.
*
@@ -64,7 +74,6 @@ static int _pim_msdp_sock_listen(const struct vrf *vrf,
int rv;
socklen_t socklen;
struct sockaddr_in sin = {};
- union sockunion su_peer = {};
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
@@ -117,7 +126,9 @@ static int _pim_msdp_sock_listen(const struct vrf *vrf,
/* Set MD5 authentication. */
if (mp && mp->auth_key) {
- su_peer = mp->su_peer;
+ union sockunion su_peer = {};
+
+ pim_msdp_addr2su(&su_peer, mp->peer);
frr_with_privs (&pimd_privs) {
sockopt_tcp_signature(sock, &su_peer, mp->auth_key);
}
@@ -349,6 +360,7 @@ int pim_msdp_sock_listen(struct pim_instance *pim)
int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
{
int rc;
+ union sockunion su_peer = {}, su_local = {};
if (PIM_DEBUG_MSDP_INTERNAL) {
zlog_debug("MSDP peer %s attempt connect%s", mp->key_str,
@@ -366,8 +378,11 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */);
}
+ pim_msdp_addr2su(&su_peer, mp->peer);
+ pim_msdp_addr2su(&su_local, mp->local);
+
/* Make socket for the peer. */
- mp->fd = sockunion_socket(&mp->su_peer);
+ mp->fd = sockunion_socket(&su_peer);
if (mp->fd < 0) {
flog_err_sys(EC_LIB_SOCKET,
"pim_msdp_socket socket failure: %s",
@@ -402,7 +417,7 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
sockopt_reuseport(mp->fd);
/* source bind */
- rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local);
+ rc = sockunion_bind(mp->fd, &su_local, 0, &su_local);
if (rc < 0) {
flog_err_sys(EC_LIB_SOCKET,
"pim_msdp_socket connect bind failure: %s",
@@ -421,12 +436,10 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
/* Set authentication (if configured). */
if (mp->auth_key) {
frr_with_privs (&pimd_privs) {
- sockopt_tcp_signature(mp->fd, &mp->su_peer,
- mp->auth_key);
+ sockopt_tcp_signature(mp->fd, &su_peer, mp->auth_key);
}
}
/* Connect to the remote mp. */
- return (sockunion_connect(mp->fd, &mp->su_peer,
- htons(PIM_MSDP_TCP_PORT), 0));
+ return (sockunion_connect(mp->fd, &su_peer, htons(PIM_MSDP_TCP_PORT), 0));
}
diff --git a/pimd/pim_nb.c b/pimd/pim_nb.c
index cb0f5e8255..c5a9c7f055 100644
--- a/pimd/pim_nb.c
+++ b/pimd/pim_nb.c
@@ -130,6 +130,18 @@ const struct frr_yang_module_info frr_pim_info = {
}
},
{
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/log-neighbor-events",
+ .cbs = {
+ .modify = pim_msdp_log_neighbor_events_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/log-sa-events",
+ .cbs = {
+ .modify = pim_msdp_log_sa_events_modify,
+ }
+ },
+ {
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups",
.cbs = {
.create = pim_msdp_mesh_group_create,
diff --git a/pimd/pim_nb.h b/pimd/pim_nb.h
index 49a94f363e..8412ef4a6e 100644
--- a/pimd/pim_nb.h
+++ b/pimd/pim_nb.h
@@ -54,6 +54,8 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss
int pim_msdp_hold_time_modify(struct nb_cb_modify_args *args);
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_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);
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index 6366699857..e594a150fd 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -1096,10 +1096,70 @@ pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address
pim6_msdp_err(pim_msdp_peer_authentication_type_modify, nb_cb_modify_args);
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);
#if PIM_IPV != 6
/*
* XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/log-neighbor-events
+ */
+int pim_msdp_log_neighbor_events_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;
+ if (yang_dnode_get_bool(args->dnode, NULL))
+ SET_FLAG(pim->log_flags, PIM_MSDP_LOG_NEIGHBOR_EVENTS);
+ else
+ UNSET_FLAG(pim->log_flags, PIM_MSDP_LOG_NEIGHBOR_EVENTS);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/log-sa-events
+ */
+int pim_msdp_log_sa_events_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;
+ if (yang_dnode_get_bool(args->dnode, NULL))
+ SET_FLAG(pim->log_flags, PIM_MSDP_LOG_SA_EVENTS);
+ else
+ UNSET_FLAG(pim->log_flags, PIM_MSDP_LOG_SA_EVENTS);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups
*/
int pim_msdp_mesh_group_create(struct nb_cb_create_args *args)
diff --git a/tests/topotests/msdp_topo1/r1/pimd.conf b/tests/topotests/msdp_topo1/r1/pimd.conf
index 3c116a003b..1548aed05e 100644
--- a/tests/topotests/msdp_topo1/r1/pimd.conf
+++ b/tests/topotests/msdp_topo1/r1/pimd.conf
@@ -22,5 +22,7 @@ ip pim rp 10.254.254.1
ip pim join-prune-interval 5
!
router pim
+ msdp log neighbor-events
+ msdp log sa-events
msdp peer 192.168.0.2 password 1234
!
diff --git a/tests/topotests/msdp_topo1/test_msdp_topo1.py b/tests/topotests/msdp_topo1/test_msdp_topo1.py
index ff80052d26..1c97f7cb1e 100755
--- a/tests/topotests/msdp_topo1/test_msdp_topo1.py
+++ b/tests/topotests/msdp_topo1/test_msdp_topo1.py
@@ -17,6 +17,7 @@ import os
import sys
import json
from functools import partial
+import re
import pytest
# Save the Current Working Directory to find configuration files.
@@ -510,6 +511,25 @@ def test_msdp_sa_filter():
assert val is None, "multicast route convergence failure"
+def test_msdp_log_events():
+ "Test that the enabled logs are working as expected."
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ 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)
+ assert match is not None
+
+ match = re.search(
+ r"MSDP SA \(192.168.10.100\,229.1.2.3\) created", r1_log)
+ assert match is not None
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/ospf_multi_instance/r1/frr.conf b/tests/topotests/ospf_multi_instance/r1/frr.conf
new file mode 100644
index 0000000000..c341a7176a
--- /dev/null
+++ b/tests/topotests/ospf_multi_instance/r1/frr.conf
@@ -0,0 +1,19 @@
+!
+hostname r1
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface lo
+ ip address 1.1.1.1/32
+ ip ospf area 0
+!
+interface r1-eth0
+ ip address 10.1.1.1/24
+ ip ospf area 0
+!
+!
+router ospf
+ ospf router-id 1.1.1.1
+ distance 20
+!
diff --git a/tests/topotests/ospf_multi_instance/r2/frr.conf b/tests/topotests/ospf_multi_instance/r2/frr.conf
new file mode 100644
index 0000000000..8501e0edc0
--- /dev/null
+++ b/tests/topotests/ospf_multi_instance/r2/frr.conf
@@ -0,0 +1,37 @@
+!
+hostname r2
+password zebra
+! debug ospf event
+! debug ospf lsa
+! debug ospf default-information
+! debug ospf zebra redistribute
+
+ip forwarding
+!
+interface lo1
+ ip address 2.2.2.1/32
+ ip ospf 1 area 0
+ no shut
+!
+interface lo2
+ ip address 2.2.2.2/32
+ ip ospf 2 area 0
+ no shut
+!
+interface r2-eth0
+ ip address 10.1.1.2/24
+ ip ospf 1 area 0
+!
+interface r2-eth1
+ ip address 10.1.2.2/24
+ ip ospf 2 area 0
+!
+router ospf 1
+ ospf router-id 2.2.2.1
+ distance 20
+!
+router ospf 2
+ ospf router-id 2.2.2.2
+ distance 20
+!
+
diff --git a/tests/topotests/ospf_multi_instance/r3/frr.conf b/tests/topotests/ospf_multi_instance/r3/frr.conf
new file mode 100644
index 0000000000..97a3e19c9b
--- /dev/null
+++ b/tests/topotests/ospf_multi_instance/r3/frr.conf
@@ -0,0 +1,19 @@
+!
+hostname r3
+password zebra
+log file /tmp/r3-frr.log
+ip forwarding
+!
+interface lo
+ ip address 3.3.3.1/32
+ ip ospf area 0
+!
+interface r3-eth0
+ ip address 10.1.2.3/24
+ ip ospf area 0
+!
+!
+router ospf
+ ospf router-id 3.3.3.1
+ distance 20
+!
diff --git a/tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py b/tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py
new file mode 100644
index 0000000000..de44140c09
--- /dev/null
+++ b/tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py
@@ -0,0 +1,403 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_ospf_multi_instance.py
+#
+# Copyright (c) 2024 LabN Consulting
+# Acee Lindem
+#
+
+import os
+import sys
+from functools import partial
+import pytest
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from lib.common_config import (
+ step,
+ create_interface_in_kernel,
+)
+
+
+"""
+test_ospf_metric_propagation.py: Test OSPF/BGP metric propagation
+"""
+
+TOPOLOGY = """
+
+ +---------+ +--------------------+ +---------+
+ | r1 | | r2 | r2 | | r3 |
+ | | | ospf 1 | ospf 2 | | |
+ | 1.1.1.1 | eth0 eth0| 2.2.2.1 | 2.2.2.2 |eth1 eth0| 3.3.3.1 |
+ | +-------------+ | +-------------+ |
+ | | 10.1.1.0/24 | | | 10.1.2.0/24 | |
+ +---------+ +--------------------+ +---------+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 3 routers
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("r3")
+
+ # Interconect router 1, 2 (0)
+ switch = tgen.add_switch("s1-1-2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ # Interconect router 2, 3 (1)
+ switch = tgen.add_switch("s2-2-3")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+ # Add more loopbacks to r2
+ create_interface_in_kernel(
+ tgen, "r2", "lo1", "2.2.2.1", netmask="255.255.255.255", create=True
+ )
+ create_interface_in_kernel(
+ tgen, "r2", "lo2", "2.2.2.2", netmask="255.255.255.255", create=True
+ )
+
+
+def setup_module(mod):
+ logger.info("OSPF Multi-Instance:\n {}".format(TOPOLOGY))
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module():
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_multi_instance_default_origination():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Configure a local default route")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\nip route 0.0.0.0/0 Null0")
+
+ step("Verify the R1 configuration and install of 'ip route 0.0.0.0/0 Null0'")
+ prefix_suppression_cfg = (
+ tgen.net["r1"]
+ .cmd('vtysh -c "show running" | grep "^ip route 0.0.0.0/0 Null0"')
+ .rstrip()
+ )
+ assertmsg = "'ip route 0.0.0.0/0 Null0' applied, but not present in configuration"
+ assert prefix_suppression_cfg == "ip route 0.0.0.0/0 Null0", assertmsg
+
+ input_dict = {
+ "0.0.0.0/0": [
+ {
+ "prefix": "0.0.0.0/0",
+ "prefixLen": 0,
+ "protocol": "static",
+ "nexthops": [
+ {
+ "blackhole": True,
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route 0.0.0.0/0 json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "0.0.0.0/0 not installed on router r1"
+ assert result is None, assertmsg
+
+ step(
+ "Verify the R1 configuration and advertisement of 'default-information originate'"
+ )
+ r1.vtysh_cmd("conf t\nrouter ospf\n default-information originate")
+
+ input_dict = {
+ "asExternalLinkStates": [
+ {
+ "lsaType": "AS-external-LSA",
+ "linkStateId": "0.0.0.0",
+ "advertisingRouter": "1.1.1.1",
+ "networkMask": 0,
+ "metricType": "E2 (Larger than any link state path)",
+ "metric": 10,
+ "forwardAddress": "0.0.0.0",
+ "externalRouteTag": 0,
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf database json", input_dict
+ )
+
+ r2 = tgen.gears["r2"]
+ step("Verify the OSPF instance 1 installation of default route on router 2")
+ input_dict = {
+ "0.0.0.0/0": [
+ {
+ "prefix": "0.0.0.0/0",
+ "prefixLen": 0,
+ "protocol": "ospf",
+ "instance": 1,
+ "nexthops": [
+ {
+ "ip": "10.1.1.1",
+ "interfaceName": "r2-eth0",
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip route 0.0.0.0/0 json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "0.0.0.0/0 not installed on router r2"
+ assert result is None, assertmsg
+
+ step("Configure OSPF 'default-intformation originate' on router r2 instance 2")
+ r2.vtysh_cmd("conf t\nrouter ospf 2\n default-information originate")
+
+ step("Verify r2 instance 2 AS-External default origination")
+ input_dict = {
+ "ospfInstance": 2,
+ "routerId": "2.2.2.2",
+ "asExternalLinkStates": [
+ {
+ "lsaType": "AS-external-LSA",
+ "linkStateId": "0.0.0.0",
+ "advertisingRouter": "2.2.2.2",
+ "networkMask": 0,
+ "metricType": "E2 (Larger than any link state path)",
+ "tos": 0,
+ "metric": 10,
+ "forwardAddress": "0.0.0.0",
+ "externalRouteTag": 0,
+ }
+ ],
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show ip ospf 2 database external json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "AS-External default not originated by router r2 OSPF instance 2"
+ assert result is None, assertmsg
+
+ step("Update the OSPF instance 2 distance so it will be preferred over instance 1")
+ r2.vtysh_cmd("conf t\nrouter ospf 2\n distance 15")
+
+ step("Generate a default route from OSPF on r3")
+ r3 = tgen.gears["r3"]
+ r3.vtysh_cmd("conf t\nrouter ospf\n default-information originate")
+ r3.vtysh_cmd("conf t\nip route 0.0.0.0/0 Null0")
+
+ step("Verify r3 AS-External default origination on r2")
+ input_dict = {
+ "ospfInstance": 2,
+ "routerId": "2.2.2.2",
+ "asExternalLinkStates": [
+ {
+ "lsaType": "AS-external-LSA",
+ "linkStateId": "0.0.0.0",
+ "advertisingRouter": "3.3.3.1",
+ "length": 36,
+ "networkMask": 0,
+ "metricType": "E2 (Larger than any link state path)",
+ "tos": 0,
+ "metric": 10,
+ "forwardAddress": "0.0.0.0",
+ "externalRouteTag": 0,
+ }
+ ],
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show ip ospf 2 database external json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "AS-External default not originated by router r3 OSPF"
+ assert result is None, assertmsg
+
+ step("Verify r3's default installed by OSPF instance 2 is preferred on r2")
+ input_dict = {
+ "0.0.0.0/0": [
+ {
+ "prefix": "0.0.0.0/0",
+ "prefixLen": 0,
+ "protocol": "ospf",
+ "instance": 2,
+ "distance": 15,
+ "nexthops": [
+ {
+ "ip": "10.1.2.3",
+ "interfaceName": "r2-eth1",
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip route 0.0.0.0/0 json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "0.0.0.0/0 from r3 not installed on router r2"
+ assert result is None, assertmsg
+
+ step(
+ "Verify that r2's OSPF instance 2 AS-External LSA default is flushed due to default from r3"
+ )
+ input_dict = {
+ "ospfInstance": 2,
+ "routerId": "2.2.2.2",
+ "asExternalLinkStates": [
+ {
+ "lsaAge": 3600,
+ "lsaType": "AS-external-LSA",
+ "linkStateId": "0.0.0.0",
+ "advertisingRouter": "2.2.2.2",
+ "networkMask": 0,
+ "metricType": "E2 (Larger than any link state path)",
+ "tos": 0,
+ "metric": 10,
+ "forwardAddress": "0.0.0.0",
+ "externalRouteTag": 0,
+ }
+ ],
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show ip ospf 2 database external json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "AS-External default not flushed by router r2 OSPF instance 2"
+ assert result is None, assertmsg
+
+ step("Remove r3's default route and verify that its advertisement is flushed")
+ r3.vtysh_cmd("conf t\nno ip route 0.0.0.0/0 Null0")
+ input_dict = {
+ "routerId": "3.3.3.1",
+ "asExternalLinkStates": [
+ {
+ "lsaAge": 3600,
+ "lsaType": "AS-external-LSA",
+ "linkStateId": "0.0.0.0",
+ "advertisingRouter": "3.3.3.1",
+ "networkMask": 0,
+ "metricType": "E2 (Larger than any link state path)",
+ "tos": 0,
+ "metric": 10,
+ "forwardAddress": "0.0.0.0",
+ "externalRouteTag": 0,
+ }
+ ],
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r3, "show ip ospf database external json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "AS-External default not flushed by router r3 OSPF"
+ assert result is None, assertmsg
+
+ step(
+ "Verify that r2's OSPF instance 2 AS-External default is advertised and installed by r3"
+ )
+ input_dict = {
+ "routerId": "3.3.3.1",
+ "asExternalLinkStates": [
+ {
+ "lsaType": "AS-external-LSA",
+ "linkStateId": "0.0.0.0",
+ "advertisingRouter": "2.2.2.2",
+ "networkMask": 0,
+ "metricType": "E2 (Larger than any link state path)",
+ "tos": 0,
+ "metric": 10,
+ "forwardAddress": "0.0.0.0",
+ "externalRouteTag": 0,
+ }
+ ],
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r3, "show ip ospf database external json", input_dict
+ )
+ assertmsg = "AS-External default not originated by r2 OSPF instance 2"
+ assert result is None, assertmsg
+
+ step("Verify r2's OSPF instance 2 is AS-External default is installed on r3")
+ input_dict = {
+ "0.0.0.0/0": [
+ {
+ "prefix": "0.0.0.0/0",
+ "prefixLen": 0,
+ "protocol": "ospf",
+ "distance": 20,
+ "nexthops": [
+ {
+ "ip": "10.1.2.2",
+ "interfaceName": "r3-eth0",
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r3, "show ip route 0.0.0.0/0 json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "0.0.0.0/0 from router r2 not installed on r3"
+ assert result is None, assertmsg
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tools/etc/frr/support_bundle_commands.conf b/tools/etc/frr/support_bundle_commands.conf
index b3889e8784..6a21ae3fb5 100644
--- a/tools/etc/frr/support_bundle_commands.conf
+++ b/tools/etc/frr/support_bundle_commands.conf
@@ -56,6 +56,7 @@ show evpn next-hops vni all
show evpn rmac vni all
show evpn vni detail
+show bmp
CMD_LIST_END
# Zebra Support Bundle Command List
@@ -74,6 +75,10 @@ show ip fib
show ipv6 fib
show nexthop-group rib
show route-map
+show mpls table
+show mpls fec
+show mpls ldp
+show mpls pseudowires
show memory
show interface vrf all
show vrf
@@ -134,9 +139,18 @@ CMD_LIST_END
# CMD_LIST_END
# ISIS Support Bundle Command List
-# PROC_NAME:isis
-# CMD_LIST_START
-# CMD_LIST_END
+PROC_NAME:isis
+CMD_LIST_START
+show isis database detail
+show isis interface detail
+show isis route
+show isis mpls ldp-sync
+show isis mpls-te database detail
+show isis mpls-te interface
+show isis mpls-te router
+show isis neighbor detail
+show isis topology
+CMD_LIST_END
# BFD Support Bundle Command List
# PROC_NAME:bfd
@@ -171,6 +185,9 @@ show ip pim join
show ip pim state
show ip pim statistics
show ip pim rpf
+show ip msdp vrf all mesh-group
+show ip msdp vrf all peer
+show ip msdp vrf all sa detail
CMD_LIST_END
# OSPFv3 Support Bundle Command List
diff --git a/yang/frr-pim.yang b/yang/frr-pim.yang
index 6a6c52185d..c3c953b76b 100644
--- a/yang/frr-pim.yang
+++ b/yang/frr-pim.yang
@@ -250,6 +250,20 @@ module frr-pim {
container msdp {
description "Global MSDP configuration.";
uses msdp-timers;
+
+ leaf log-neighbor-events {
+ type boolean;
+ default false;
+ description
+ "Log all MSDP neighbor related events.";
+ }
+
+ leaf log-sa-events {
+ type boolean;
+ default false;
+ description
+ "Log all MSDP SA related events.";
+ }
}
list msdp-mesh-groups {