diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f30fa6d379bd..2489f4d8ad49 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -7842,6 +7842,91 @@ static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty, vty_json(vty, json); } +static void msdp_peer_details_add_json(struct json_object *peer_json, + const struct pim_msdp_peer *peer) +{ + char state_str[PIM_MSDP_STATE_STRLEN]; + char holdtimer[PIM_MSDP_TIMER_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char katimer[PIM_MSDP_TIMER_STRLEN]; + char crtimer[PIM_MSDP_TIMER_STRLEN]; + time_t now; + + if (peer->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - peer->uptime); + } else + strlcpy(timebuf, "-", sizeof(timebuf)); + + pim_msdp_state_dump(peer->state, state_str, sizeof(state_str)); + pim_time_timer_to_hhmmss(katimer, sizeof(katimer), peer->ka_timer); + pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), peer->cr_timer); + pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), peer->hold_timer); + + if (peer->state == PIM_MSDP_ESTABLISHED) { + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } sock_address; + socklen_t sock_address_size = sizeof(sock_address); + char address_string[INET6_ADDRSTRLEN]; + + memset(&sock_address, 0, sizeof(sock_address)); + + if (getsockname(peer->fd, &sock_address.sa, &sock_address_size) == -1) { + zlog_warn("MSDP peer failed to get socket local address: (%d) %s", errno, + strerror(errno)); + return; + } + + inet_ntop(AF_INET, &sock_address.sin.sin_addr, address_string, + sizeof(address_string)); + json_object_string_add(peer_json, "local", address_string); + json_object_int_add(peer_json, "localPort", ntohs(sock_address.sin.sin_port)); + + if (getpeername(peer->fd, &sock_address.sa, &sock_address_size) == -1) { + zlog_warn("MSDP peer failed to get socket peer address: (%d) %s", errno, + strerror(errno)); + return; + } + + inet_ntop(AF_INET, &sock_address.sin.sin_addr, address_string, + sizeof(address_string)); + json_object_string_add(peer_json, "peer", address_string); + json_object_int_add(peer_json, "peerPort", ntohs(sock_address.sin.sin_port)); + } + + if (peer->flags & PIM_MSDP_PEERF_IN_GROUP) + json_object_string_add(peer_json, "meshGroupName", peer->mesh_group_name); + + json_object_string_add(peer_json, "state", state_str); + json_object_string_add(peer_json, "upTime", timebuf); + json_object_string_add(peer_json, "keepAliveTimer", katimer); + json_object_string_add(peer_json, "connRetryTimer", crtimer); + json_object_string_add(peer_json, "holdTimer", holdtimer); + json_object_string_add(peer_json, "lastReset", peer->last_reset); + json_object_int_add(peer_json, "connAttempts", peer->conn_attempts); + json_object_int_add(peer_json, "establishedChanges", peer->est_flaps); + json_object_int_add(peer_json, "saCount", peer->sa_cnt); + json_object_int_add(peer_json, "kaSent", peer->ka_tx_cnt); + json_object_int_add(peer_json, "kaRcvd", peer->ka_rx_cnt); + json_object_int_add(peer_json, "saSent", peer->sa_tx_cnt); + json_object_int_add(peer_json, "saRcvd", peer->sa_rx_cnt); + if (peer->asn != 0) + json_object_int_add(peer_json, "asn", peer->asn); + + json_object_int_add(peer_json, "saFilteredIn", peer->acl_in_count); + if (peer->acl_in) + json_object_string_add(peer_json, "saFilterIn", peer->acl_in); + + json_object_int_add(peer_json, "saFilteredOut", peer->acl_out_count); + if (peer->acl_out) + json_object_string_add(peer_json, "saFilterout", peer->acl_out); + + json_object_int_add(peer_json, "rpfLookupFailures", peer->rpf_lookup_failure_count); +} + static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty, const char *peer, bool uj) { @@ -7867,6 +7952,13 @@ static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty, if (strcmp(peer, "detail") && strcmp(peer, peer_str)) continue; + if (uj) { + json_row = json_object_new_object(); + msdp_peer_details_add_json(json_row, mp); + json_object_object_add(json, peer_str, json_row); + continue; + } + if (mp->state == PIM_MSDP_ESTABLISHED) { now = pim_time_monotonic_sec(); pim_time_uptime(timebuf, sizeof(timebuf), @@ -7884,63 +7976,29 @@ static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty, pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), mp->hold_timer); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "peer", peer_str); - json_object_string_add(json_row, "local", local_str); - if (mp->flags & PIM_MSDP_PEERF_IN_GROUP) - json_object_string_add(json_row, - "meshGroupName", - mp->mesh_group_name); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "keepAliveTimer", - katimer); - json_object_string_add(json_row, "connRetryTimer", - crtimer); - json_object_string_add(json_row, "holdTimer", - holdtimer); - json_object_string_add(json_row, "lastReset", - mp->last_reset); - json_object_int_add(json_row, "connAttempts", - mp->conn_attempts); - json_object_int_add(json_row, "establishedChanges", - mp->est_flaps); - json_object_int_add(json_row, "saCount", mp->sa_cnt); - json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); - json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); - json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); - json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); - json_object_object_add(json, peer_str, json_row); - } else { - vty_out(vty, "Peer : %s\n", peer_str); - vty_out(vty, " Local : %s\n", local_str); - if (mp->flags & PIM_MSDP_PEERF_IN_GROUP) - vty_out(vty, " Mesh Group : %s\n", - mp->mesh_group_name); - vty_out(vty, " State : %s\n", state_str); - vty_out(vty, " Uptime : %s\n", timebuf); - - vty_out(vty, " Keepalive Timer : %s\n", katimer); - vty_out(vty, " Conn Retry Timer : %s\n", crtimer); - vty_out(vty, " Hold Timer : %s\n", holdtimer); - vty_out(vty, " Last Reset : %s\n", - mp->last_reset); - vty_out(vty, " Conn Attempts : %d\n", - mp->conn_attempts); - vty_out(vty, " Established Changes : %d\n", - mp->est_flaps); - vty_out(vty, " SA Count : %d\n", - mp->sa_cnt); - vty_out(vty, " Statistics :\n"); - vty_out(vty, - " Sent Rcvd\n"); - vty_out(vty, " Keepalives : %10d %10d\n", - mp->ka_tx_cnt, mp->ka_rx_cnt); - vty_out(vty, " SAs : %10d %10d\n", - mp->sa_tx_cnt, mp->sa_rx_cnt); - vty_out(vty, "\n"); - } + vty_out(vty, "Peer : %s\n", peer_str); + vty_out(vty, " Local : %s\n", local_str); + if (mp->flags & PIM_MSDP_PEERF_IN_GROUP) + vty_out(vty, " Mesh Group : %s\n", mp->mesh_group_name); + if (mp->asn != 0) + vty_out(vty, " BGP/AS : %u\n", mp->asn); + else + vty_out(vty, " BGP/AS : -\n"); + vty_out(vty, " State : %s\n", state_str); + vty_out(vty, " Uptime : %s\n", timebuf); + + vty_out(vty, " Keepalive Timer : %s\n", katimer); + vty_out(vty, " Conn Retry Timer : %s\n", crtimer); + vty_out(vty, " Hold Timer : %s\n", holdtimer); + vty_out(vty, " Last Reset : %s\n", mp->last_reset); + vty_out(vty, " Conn Attempts : %d\n", mp->conn_attempts); + vty_out(vty, " Established Changes : %d\n", mp->est_flaps); + vty_out(vty, " SA Count : %d\n", mp->sa_cnt); + vty_out(vty, " Statistics :\n"); + vty_out(vty, " Sent Rcvd\n"); + vty_out(vty, " Keepalives : %10d %10d\n", mp->ka_tx_cnt, mp->ka_rx_cnt); + vty_out(vty, " SAs : %10d %10d\n", mp->sa_tx_cnt, mp->sa_rx_cnt); + vty_out(vty, "\n"); } if (uj) @@ -8021,6 +8079,85 @@ DEFUN (show_ip_msdp_peer_detail_vrf_all, return CMD_SUCCESS; } +static void clear_msdp_peer_counters(struct pim_msdp_peer *peer) +{ + peer->ka_rx_cnt = 0; + peer->ka_tx_cnt = 0; + peer->sa_rx_cnt = 0; + peer->sa_tx_cnt = 0; + peer->est_flaps = 0; + peer->conn_attempts = 0; + peer->acl_in_count = 0; + peer->acl_out_count = 0; + peer->rpf_lookup_failure_count = 0; +} + +DEFPY(clear_ip_msdp_peer_counters, clear_ip_msdp_peer_counters_cmd, + "clear ip msdp [] peer [A.B.C.D$peer] counters", + CLEAR_STR + IP_STR + MSDP_STR + VRF_CMD_HELP_STR + VRF_CMD_HELP_STR + "MSDP peer information\n" + "Peer IP address\n" + "MSDP peer counters\n") +{ + const struct pim_instance *pim; + struct pim_msdp_peer *msdp_peer = NULL; + struct vrf *vrf; + + if (vrf_name) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf == NULL) { + vty_out(vty, "VRF %s does not exist\n", vrf_name); + return CMD_WARNING; + } + } else if (vrf_all) { + vrf = NULL; + } else { + vrf = vrf_lookup_by_id(VRF_DEFAULT); + if (vrf == NULL) { + vty_out(vty, "Default VRF does not exist\n"); + return CMD_WARNING; + } + } + + if (vrf) { + pim = vrf->info; + + if (peer_str) { + msdp_peer = pim_msdp_peer_find(pim, peer); + if (msdp_peer) + clear_msdp_peer_counters(msdp_peer); + } else { + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, msdp_peer)) + clear_msdp_peer_counters(msdp_peer); + } + + return CMD_SUCCESS; + } + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + pim = vrf->info; + + if (peer_str) { + msdp_peer = pim_msdp_peer_find(pim, peer); + if (msdp_peer) + clear_msdp_peer_counters(msdp_peer); + } else { + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, msdp_peer)) + clear_msdp_peer_counters(msdp_peer); + } + } + + return CMD_SUCCESS; +} + static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) { struct listnode *sanode; @@ -9234,6 +9371,7 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &clear_ip_mroute_count_cmd); install_element(ENABLE_NODE, &clear_ip_msdp_peer_cmd); + install_element(ENABLE_NODE, &clear_ip_msdp_peer_counters_cmd); install_element(ENABLE_NODE, &clear_ip_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_mroute_cmd);