diff options
| -rw-r--r-- | bfdd/dplane.c | 3 | ||||
| -rw-r--r-- | ospfd/ospf_asbr.c | 70 | ||||
| -rw-r--r-- | ospfd/ospf_asbr.h | 4 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 7 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 3 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.c | 30 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.h | 3 | ||||
| -rw-r--r-- | pimd/pim_cmd.c | 33 | ||||
| -rw-r--r-- | pimd/pim_instance.c | 10 | ||||
| -rw-r--r-- | pimd/pim_instance.h | 10 | ||||
| -rw-r--r-- | pimd/pim_msdp.c | 201 | ||||
| -rw-r--r-- | pimd/pim_msdp.h | 7 | ||||
| -rw-r--r-- | pimd/pim_msdp_packet.c | 27 | ||||
| -rw-r--r-- | pimd/pim_msdp_socket.c | 29 | ||||
| -rw-r--r-- | pimd/pim_nb.c | 12 | ||||
| -rw-r--r-- | pimd/pim_nb.h | 2 | ||||
| -rw-r--r-- | pimd/pim_nb_config.c | 60 | ||||
| -rw-r--r-- | tests/topotests/msdp_topo1/r1/pimd.conf | 2 | ||||
| -rwxr-xr-x | tests/topotests/msdp_topo1/test_msdp_topo1.py | 20 | ||||
| -rw-r--r-- | tests/topotests/ospf_multi_instance/r1/frr.conf | 19 | ||||
| -rw-r--r-- | tests/topotests/ospf_multi_instance/r2/frr.conf | 37 | ||||
| -rw-r--r-- | tests/topotests/ospf_multi_instance/r3/frr.conf | 19 | ||||
| -rw-r--r-- | tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py | 403 | ||||
| -rw-r--r-- | tools/etc/frr/support_bundle_commands.conf | 23 | ||||
| -rw-r--r-- | yang/frr-pim.yang | 14 |
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 { |
