diff options
Diffstat (limited to 'pimd/pim_cmd.c')
| -rw-r--r-- | pimd/pim_cmd.c | 962 |
1 files changed, 899 insertions, 63 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index cb2ba87ec6..e6e9c2d0c8 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -62,6 +62,7 @@ #include "pim_bfd.h" #include "pim_vxlan.h" #include "bfd.h" +#include "pim_bsm.h" #ifndef VTYSH_EXTRACT_PL #include "pimd/pim_cmd_clippy.c" @@ -1477,13 +1478,14 @@ static void pim_show_interface_traffic(struct pim_instance *pim, json = json_object_new_object(); else { vty_out(vty, "\n"); - vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n", + vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", " HELLO", " JOIN", " PRUNE", " REGISTER", "REGISTER-STOP", - " ASSERT"); - vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n", "", + " ASSERT", " BSM"); + vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "", " Rx/Tx", " Rx/Tx", " Rx/Tx", - " Rx/Tx", " Rx/Tx", " Rx/Tx"); + " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx"); vty_out(vty, "---------------------------------------------------------------------------------------------------------------\n"); } @@ -1518,12 +1520,15 @@ static void pim_show_interface_traffic(struct pim_instance *pim, json_object_int_add(json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); json_object_int_add(json_row, "assertTx", - pim_ifp->pim_ifstat_assert_send); - + pim_ifp->pim_ifstat_assert_send); + json_object_int_add(json_row, "bsmRx", + pim_ifp->pim_ifstat_bsm_rx); + json_object_int_add(json_row, "bsmTx", + pim_ifp->pim_ifstat_bsm_tx); json_object_object_add(json, ifp->name, json_row); } else { vty_out(vty, - "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", + "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7lu/%-7lu \n", ifp->name, pim_ifp->pim_ifstat_hello_recv, pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, @@ -1535,7 +1540,9 @@ static void pim_show_interface_traffic(struct pim_instance *pim, pim_ifp->pim_ifstat_reg_stop_recv, pim_ifp->pim_ifstat_reg_stop_send, pim_ifp->pim_ifstat_assert_recv, - pim_ifp->pim_ifstat_assert_send); + pim_ifp->pim_ifstat_assert_send, + pim_ifp->pim_ifstat_bsm_rx, + pim_ifp->pim_ifstat_bsm_tx); } } if (uj) { @@ -1559,14 +1566,15 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim, json = json_object_new_object(); else { vty_out(vty, "\n"); - vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n", + vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", " HELLO", " JOIN", " PRUNE", - " REGISTER", " REGISTER-STOP", " ASSERT"); - vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", + " REGISTER", " REGISTER-STOP", " ASSERT", + " BSM"); + vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", - " Rx/Tx", " Rx/Tx"); + " Rx/Tx", " Rx/Tx", " Rx/Tx"); vty_out(vty, - "---------------------------------------------------------------------------------------------------------------------\n"); + "-------------------------------------------------------------------------------------------------------------------------------\n"); } FOR_ALL_INTERFACES (pim->vrf, ifp) { @@ -1605,11 +1613,15 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim, pim_ifp->pim_ifstat_assert_recv); json_object_int_add(json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); + json_object_int_add(json_row, "bsmRx", + pim_ifp->pim_ifstat_bsm_rx); + json_object_int_add(json_row, "bsmTx", + pim_ifp->pim_ifstat_bsm_tx); json_object_object_add(json, ifp->name, json_row); } else { vty_out(vty, - "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", + "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7lu/%-7lu \n", ifp->name, pim_ifp->pim_ifstat_hello_recv, pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, @@ -1621,7 +1633,9 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim, pim_ifp->pim_ifstat_reg_stop_recv, pim_ifp->pim_ifstat_reg_stop_send, pim_ifp->pim_ifstat_assert_recv, - pim_ifp->pim_ifstat_assert_send); + pim_ifp->pim_ifstat_assert_send, + pim_ifp->pim_ifstat_bsm_rx, + pim_ifp->pim_ifstat_bsm_tx); } } if (uj) { @@ -1987,9 +2001,9 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); if (ifp_in) - strcpy(in_ifname, ifp_in->name); + strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname)); else - strcpy(in_ifname, "<iif?>"); + strlcpy(in_ifname, "<iif?>", sizeof(in_ifname)); if (src_or_group) { if (strcmp(src_or_group, src_str) @@ -2071,9 +2085,9 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, now - c_oil->oif_creation[oif_vif_index]); if (ifp_out) - strcpy(out_ifname, ifp_out->name); + strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname)); else - strcpy(out_ifname, "<oif?>"); + strlcpy(out_ifname, "<oif?>", sizeof(out_ifname)); if (uj) { json_ifp_out = json_object_new_object(); @@ -2352,37 +2366,37 @@ static void json_object_pim_upstream_add(json_object *json, static const char * pim_upstream_state2brief_str(enum pim_upstream_state join_state, - char *state_str) + char *state_str, size_t state_str_len) { switch (join_state) { case PIM_UPSTREAM_NOTJOINED: - strcpy(state_str, "NotJ"); + strlcpy(state_str, "NotJ", state_str_len); break; case PIM_UPSTREAM_JOINED: - strcpy(state_str, "J"); + strlcpy(state_str, "J", state_str_len); break; default: - strcpy(state_str, "Unk"); + strlcpy(state_str, "Unk", state_str_len); } return state_str; } static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, - char *state_str) + char *state_str, size_t state_str_len) { switch (reg_state) { case PIM_REG_NOINFO: - strcpy(state_str, "RegNI"); + strlcpy(state_str, "RegNI", state_str_len); break; case PIM_REG_JOIN: - strcpy(state_str, "RegJ"); + strlcpy(state_str, "RegJ", state_str_len); break; case PIM_REG_JOIN_PENDING: case PIM_REG_PRUNE: - strcpy(state_str, "RegP"); + strlcpy(state_str, "RegP", state_str_len); break; default: - strcpy(state_str, "Unk"); + strlcpy(state_str, "Unk", state_str_len); } return state_str; } @@ -2450,13 +2464,13 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer), up->t_msdp_reg_timer); - pim_upstream_state2brief_str(up->join_state, state_str); + pim_upstream_state2brief_str(up->join_state, state_str, sizeof(state_str)); if (up->reg_state != PIM_REG_NOINFO) { char tmp_str[PIM_REG_STATE_STR_LEN]; sprintf(state_str + strlen(state_str), ",%s", - pim_reg_state2brief_str(up->reg_state, - tmp_str)); + pim_reg_state2brief_str(up->reg_state, tmp_str, + sizeof(tmp_str))); } if (uj) { @@ -2507,7 +2521,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, pim_upstream_state2str(up->join_state)); json_object_string_add( json_row, "regState", - pim_reg_state2str(up->reg_state, state_str)); + pim_reg_state2str(up->reg_state, state_str, sizeof(state_str))); json_object_string_add(json_row, "upTime", uptime); json_object_string_add(json_row, "joinTimer", join_timer); @@ -2888,6 +2902,413 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty) hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd); } +/* Display the bsm database details */ +static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) +{ + struct listnode *bsmnode; + int count = 0; + int fragment = 1; + struct bsm_info *bsm; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + count = pim->global_scope.bsm_list->count; + + if (uj) { + json = json_object_new_object(); + json_object_int_add(json, "Number of the fragments", count); + } else { + vty_out(vty, "Scope Zone: Global\n"); + vty_out(vty, "Number of the fragments: %d\n", count); + vty_out(vty, "\n"); + } + + for (ALL_LIST_ELEMENTS_RO(pim->global_scope.bsm_list, bsmnode, bsm)) { + char grp_str[INET_ADDRSTRLEN]; + char rp_str[INET_ADDRSTRLEN]; + char bsr_str[INET_ADDRSTRLEN]; + struct bsmmsg_grpinfo *group; + struct bsmmsg_rpinfo *rpaddr; + struct prefix grp; + struct bsm_hdr *hdr; + uint32_t offset = 0; + uint8_t *buf; + uint32_t len = 0; + uint32_t frag_rp_cnt = 0; + + buf = bsm->bsm; + len = bsm->size; + + /* skip pim header */ + buf += PIM_MSG_HEADER_LEN; + len -= PIM_MSG_HEADER_LEN; + + hdr = (struct bsm_hdr *)buf; + + /* BSM starts with bsr header */ + buf += sizeof(struct bsm_hdr); + len -= sizeof(struct bsm_hdr); + + pim_inet4_dump("<BSR Address?>", hdr->bsr_addr.addr, bsr_str, + sizeof(bsr_str)); + + + if (uj) { + json_object_string_add(json, "BSR address", bsr_str); + json_object_int_add(json, "BSR priority", + hdr->bsr_prio); + json_object_int_add(json, "Hashmask Length", + hdr->hm_len); + json_object_int_add(json, "Fragment Tag", + ntohs(hdr->frag_tag)); + } else { + vty_out(vty, "BSM Fragment : %d\n", fragment); + vty_out(vty, "------------------\n"); + vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address", + "BSR-Priority", "Hashmask-len", "Fragment-Tag"); + vty_out(vty, "%-15s %-15d %-15d %-15d\n", bsr_str, + hdr->bsr_prio, hdr->hm_len, + ntohs(hdr->frag_tag)); + } + + vty_out(vty, "\n"); + + while (offset < len) { + group = (struct bsmmsg_grpinfo *)buf; + + if (group->group.family == PIM_MSG_ADDRESS_FAMILY_IPV4) + grp.family = AF_INET; + + grp.prefixlen = group->group.mask; + grp.u.prefix4.s_addr = group->group.addr.s_addr; + + prefix2str(&grp, grp_str, sizeof(grp_str)); + + buf += sizeof(struct bsmmsg_grpinfo); + offset += sizeof(struct bsmmsg_grpinfo); + + if (uj) { + json_object_object_get_ex(json, grp_str, + &json_group); + if (!json_group) { + json_group = json_object_new_object(); + json_object_int_add(json_group, + "Rp Count", + group->rp_count); + json_object_int_add( + json_group, "Fragment Rp count", + group->frag_rp_count); + json_object_object_add(json, grp_str, + json_group); + } + } else { + vty_out(vty, "Group : %s\n", grp_str); + vty_out(vty, "-------------------\n"); + vty_out(vty, "Rp Count:%d\n", group->rp_count); + vty_out(vty, "Fragment Rp Count : %d\n", + group->frag_rp_count); + } + + frag_rp_cnt = group->frag_rp_count; + + if (!frag_rp_cnt) + continue; + + if (!uj) + vty_out(vty, + "RpAddress HoldTime Priority\n"); + + while (frag_rp_cnt--) { + rpaddr = (struct bsmmsg_rpinfo *)buf; + + buf += sizeof(struct bsmmsg_rpinfo); + offset += sizeof(struct bsmmsg_rpinfo); + + pim_inet4_dump("<Rp addr?>", + rpaddr->rpaddr.addr, rp_str, + sizeof(rp_str)); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add( + json_row, "Rp Address", rp_str); + json_object_int_add( + json_row, "Rp HoldTime", + ntohs(rpaddr->rp_holdtime)); + json_object_int_add(json_row, + "Rp Priority", + rpaddr->rp_pri); + json_object_object_add( + json_group, rp_str, json_row); + } else { + vty_out(vty, "%-15s %-12d %d\n", rp_str, + ntohs(rpaddr->rp_holdtime), + rpaddr->rp_pri); + } + } + vty_out(vty, "\n"); + } + + fragment++; + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +/*Display the group-rp mappings */ +static void pim_show_group_rp_mappings_info(struct pim_instance *pim, + struct vty *vty, bool uj) +{ + struct bsgrp_node *bsgrp; + struct listnode *rpnode; + struct bsm_rpinfo *bsm_rp; + struct route_node *rn; + char bsr_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (pim->global_scope.current_bsr.s_addr == INADDR_ANY) + strncpy(bsr_str, "0.0.0.0", sizeof(bsr_str)); + + else + pim_inet4_dump("<bsr?>", pim->global_scope.current_bsr, bsr_str, + sizeof(bsr_str)); + + if (uj) { + json = json_object_new_object(); + json_object_string_add(json, "BSR Address", bsr_str); + } else { + vty_out(vty, "BSR Address %s\n", bsr_str); + } + + for (rn = route_top(pim->global_scope.bsrp_table); rn; + rn = route_next(rn)) { + bsgrp = (struct bsgrp_node *)rn->info; + + if (!bsgrp) + continue; + + char grp_str[INET_ADDRSTRLEN]; + + prefix2str(&bsgrp->group, grp_str, sizeof(grp_str)); + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + } else { + vty_out(vty, "Group Address %s\n", grp_str); + vty_out(vty, "--------------------------\n"); + vty_out(vty, "%-15s %-15s %-15s %-15s\n", "Rp Address", + "priority", "Holdtime", "Hash"); + + vty_out(vty, "(ACTIVE)\n"); + } + + if (bsgrp->bsrp_list) { + for (ALL_LIST_ELEMENTS_RO(bsgrp->bsrp_list, rpnode, + bsm_rp)) { + char rp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<Rp Address?>", + bsm_rp->rp_address, rp_str, + sizeof(rp_str)); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add( + json_row, "Rp Address", rp_str); + json_object_int_add( + json_row, "Rp HoldTime", + bsm_rp->rp_holdtime); + json_object_int_add(json_row, + "Rp Priority", + bsm_rp->rp_prio); + json_object_int_add(json_row, + "Hash Val", + bsm_rp->hash); + json_object_object_add( + json_group, rp_str, json_row); + + } else { + vty_out(vty, + "%-15s %-15u %-15u %-15u\n", + rp_str, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, + bsm_rp->hash); + } + } + if (!bsgrp->bsrp_list->count && !uj) + vty_out(vty, "Active List is empty.\n"); + } + + if (uj) { + json_object_int_add(json_group, "Pending RP count", + bsgrp->pend_rp_cnt); + } else { + vty_out(vty, "(PENDING)\n"); + vty_out(vty, "Pending RP count :%d\n", + bsgrp->pend_rp_cnt); + if (bsgrp->pend_rp_cnt) + vty_out(vty, "%-15s %-15s %-15s %-15s\n", + "Rp Address", "priority", "Holdtime", + "Hash"); + } + + if (bsgrp->partial_bsrp_list) { + for (ALL_LIST_ELEMENTS_RO(bsgrp->partial_bsrp_list, + rpnode, bsm_rp)) { + char rp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address, + rp_str, sizeof(rp_str)); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add( + json_row, "Rp Address", rp_str); + json_object_int_add( + json_row, "Rp HoldTime", + bsm_rp->rp_holdtime); + json_object_int_add(json_row, + "Rp Priority", + bsm_rp->rp_prio); + json_object_int_add(json_row, + "Hash Val", + bsm_rp->hash); + json_object_object_add( + json_group, rp_str, json_row); + } else { + vty_out(vty, + "%-15s %-15u %-15u %-15u\n", + rp_str, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, + bsm_rp->hash); + } + } + if (!bsgrp->partial_bsrp_list->count && !uj) + vty_out(vty, "Partial List is empty\n"); + } + + if (!uj) + vty_out(vty, "\n"); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +/* pim statistics - just adding only bsm related now. + * We can continue to add all pim related stats here. + */ +static void pim_show_statistics(struct pim_instance *pim, struct vty *vty, + const char *ifname, bool uj) +{ + json_object *json = NULL; + struct interface *ifp; + + if (uj) { + json = json_object_new_object(); + json_object_int_add(json, "Number of Received BSMs", + pim->bsm_rcvd); + json_object_int_add(json, "Number of Forwared BSMs", + pim->bsm_sent); + json_object_int_add(json, "Number of Dropped BSMs", + pim->bsm_dropped); + } else { + vty_out(vty, "BSM Statistics :\n"); + vty_out(vty, "----------------\n"); + vty_out(vty, "Number of Received BSMs : %ld\n", pim->bsm_rcvd); + vty_out(vty, "Number of Forwared BSMs : %ld\n", pim->bsm_sent); + vty_out(vty, "Number of Dropped BSMs : %ld\n", + pim->bsm_dropped); + } + + vty_out(vty, "\n"); + + /* scan interfaces */ + FOR_ALL_INTERFACES (pim->vrf, ifp) { + struct pim_interface *pim_ifp = ifp->info; + + if (ifname && strcmp(ifname, ifp->name)) + continue; + + if (!pim_ifp) + continue; + + if (!uj) { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "-------------------\n"); + vty_out(vty, + "Number of BSMs dropped due to config miss : %u\n", + pim_ifp->pim_ifstat_bsm_cfg_miss); + vty_out(vty, "Number of unicast BSMs dropped : %u\n", + pim_ifp->pim_ifstat_ucast_bsm_cfg_miss); + vty_out(vty, + "Number of BSMs dropped due to invalid scope zone : %u\n", + pim_ifp->pim_ifstat_bsm_invalid_sz); + } else { + + json_object *json_row = NULL; + + json_row = json_object_new_object(); + + json_object_string_add(json_row, "If Name", ifp->name); + json_object_int_add( + json_row, + "Number of BSMs dropped due to config miss", + pim_ifp->pim_ifstat_bsm_cfg_miss); + json_object_int_add( + json_row, "Number of unicast BSMs dropped", + pim_ifp->pim_ifstat_ucast_bsm_cfg_miss); + json_object_int_add(json_row, + "Number of BSMs dropped due to invalid scope zone", + pim_ifp->pim_ifstat_bsm_invalid_sz); + json_object_object_add(json, ifp->name, json_row); + } + vty_out(vty, "\n"); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void clear_pim_statistics(struct pim_instance *pim) +{ + struct interface *ifp; + + pim->bsm_rcvd = 0; + pim->bsm_sent = 0; + pim->bsm_dropped = 0; + + /* scan interfaces */ + FOR_ALL_INTERFACES (pim->vrf, ifp) { + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + pim_ifp->pim_ifstat_bsm_cfg_miss = 0; + pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0; + pim_ifp->pim_ifstat_bsm_invalid_sz = 0; + } +} + static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) { struct interface *ifp; @@ -3207,6 +3628,82 @@ static void igmp_show_source_retransmission(struct pim_instance *pim, } /* scan interfaces */ } +static void pim_show_bsr(struct pim_instance *pim, + struct vty *vty, + bool uj) +{ + char uptime[10]; + char last_bsm_seen[10]; + time_t now; + char bsr_state[20]; + char bsr_str[PREFIX_STRLEN]; + json_object *json = NULL; + + vty_out(vty, "PIMv2 Bootstrap information\n"); + + if (pim->global_scope.current_bsr.s_addr == INADDR_ANY) { + strncpy(bsr_str, "0.0.0.0", sizeof(bsr_str)); + pim_time_uptime(uptime, sizeof(uptime), + pim->global_scope.current_bsr_first_ts); + pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen), + pim->global_scope.current_bsr_last_ts); + } + + else { + pim_inet4_dump("<bsr?>", pim->global_scope.current_bsr, + bsr_str, sizeof(bsr_str)); + now = pim_time_monotonic_sec(); + pim_time_uptime(uptime, sizeof(uptime), + (now - pim->global_scope.current_bsr_first_ts)); + pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen), + now - pim->global_scope.current_bsr_last_ts); + } + + switch (pim->global_scope.state) { + case NO_INFO: + strncpy(bsr_state, "NO_INFO", sizeof(bsr_state)); + break; + case ACCEPT_ANY: + strncpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state)); + break; + case ACCEPT_PREFERRED: + strncpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state)); + break; + default: + strncpy(bsr_state, "", sizeof(bsr_state)); + } + + if (uj) { + json = json_object_new_object(); + json_object_string_add(json, "bsr", bsr_str); + json_object_int_add(json, "priority", + pim->global_scope.current_bsr_prio); + json_object_int_add(json, "fragment_tag", + pim->global_scope.bsm_frag_tag); + json_object_string_add(json, "state", bsr_state); + json_object_string_add(json, "upTime", uptime); + json_object_string_add(json, "last_bsm_seen", last_bsm_seen); + } + + else { + vty_out(vty, "Current preferred BSR address: %s\n", bsr_str); + vty_out(vty, + "Priority Fragment-Tag State UpTime\n"); + vty_out(vty, " %-12d %-12d %-13s %7s\n", + pim->global_scope.current_bsr_prio, + pim->global_scope.bsm_frag_tag, + bsr_state, + uptime); + vty_out(vty, "Last BSM seen: %s\n", last_bsm_seen); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + static void clear_igmp_interfaces(struct pim_instance *pim) { struct interface *ifp; @@ -3282,6 +3779,25 @@ DEFUN (clear_ip_igmp_interfaces, return CMD_SUCCESS; } +DEFUN (clear_ip_pim_statistics, + clear_ip_pim_statistics_cmd, + "clear ip pim statistics [vrf NAME]", + CLEAR_STR + IP_STR + CLEAR_IP_PIM_STR + VRF_CMD_HELP_STR + "Reset PIM statistics\n") +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + + if (!vrf) + return CMD_WARNING; + + clear_pim_statistics(vrf->info); + return CMD_SUCCESS; +} + static void mroute_add_all(struct pim_instance *pim) { struct listnode *node; @@ -3400,6 +3916,8 @@ DEFUN (clear_ip_pim_interface_traffic, pim_ifp->pim_ifstat_reg_stop_send = 0; pim_ifp->pim_ifstat_assert_recv = 0; pim_ifp->pim_ifstat_assert_send = 0; + pim_ifp->pim_ifstat_bsm_rx = 0; + pim_ifp->pim_ifstat_bsm_tx = 0; } return CMD_SUCCESS; @@ -4459,6 +4977,76 @@ DEFUN (show_ip_pim_interface_traffic, return CMD_SUCCESS; } +DEFUN (show_ip_pim_bsm_db, + show_ip_pim_bsm_db_cmd, + "show ip pim bsm-database [vrf NAME] [json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM cached bsm packets information\n" + JSON_STR) +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + bool uj = use_json(argc, argv); + + if (!vrf) + return CMD_WARNING; + + pim_show_bsm_db(vrf->info, vty, uj); + return CMD_SUCCESS; +} + +DEFUN (show_ip_pim_bsrp, + show_ip_pim_bsrp_cmd, + "show ip pim bsrp-info [vrf NAME] [json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM cached group-rp mappings information\n" + JSON_STR) +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + bool uj = use_json(argc, argv); + + if (!vrf) + return CMD_WARNING; + + pim_show_group_rp_mappings_info(vrf->info, vty, uj); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_pim_statistics, + show_ip_pim_statistics_cmd, + "show ip pim [vrf NAME] statistics [interface WORD] [json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM statistics\n" + "interface\n" + "PIM interface\n" + JSON_STR) +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + bool uj = use_json(argc, argv); + + if (!vrf) + return CMD_WARNING; + + if (argv_find(argv, argc, "WORD", &idx)) + pim_show_statistics(vrf->info, vty, argv[idx]->arg, uj); + else + pim_show_statistics(vrf->info, vty, NULL, uj); + + return CMD_SUCCESS; +} + static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty) { struct interface *ifp; @@ -4646,9 +5234,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); if (ifp_in) - strcpy(in_ifname, ifp_in->name); + strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname)); else - strcpy(in_ifname, "<iif?>"); + strlcpy(in_ifname, "<iif?>", sizeof(in_ifname)); if (uj) { @@ -4703,9 +5291,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, found_oif = 1; if (ifp_out) - strcpy(out_ifname, ifp_out->name); + strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname)); else - strcpy(out_ifname, "<oif?>"); + strlcpy(out_ifname, "<oif?>", sizeof(out_ifname)); if (uj) { json_ifp_out = json_object_new_object(); @@ -4763,27 +5351,27 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, } else { if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { - strcpy(proto, "PIM"); + strlcpy(proto, "PIM", sizeof(proto)); } if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { - strcpy(proto, "IGMP"); + strlcpy(proto, "IGMP", sizeof(proto)); } if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_VXLAN) { - strcpy(proto, "VxLAN"); + strlcpy(proto, "VxLAN", sizeof(proto)); } if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { - strcpy(proto, "SRC"); + strlcpy(proto, "SRC", sizeof(proto)); } if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) { - strcpy(proto, "STAR"); + strlcpy(proto, "STAR", sizeof(proto)); } vty_out(vty, @@ -4822,9 +5410,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, found_oif = 0; if (ifp_in) - strcpy(in_ifname, ifp_in->name); + strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname)); else - strcpy(in_ifname, "<iif?>"); + strlcpy(in_ifname, "<iif?>", sizeof(in_ifname)); if (uj) { @@ -4851,7 +5439,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, json_object_string_add(json_source, "iif", in_ifname); json_oil = NULL; } else { - strcpy(proto, "STATIC"); + strlcpy(proto, "STATIC", sizeof(proto)); } for (oif_vif_index = 0; oif_vif_index < MAXVIFS; @@ -4873,9 +5461,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, found_oif = 1; if (ifp_out) - strcpy(out_ifname, ifp_out->name); + strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname)); else - strcpy(out_ifname, "<oif?>"); + strlcpy(out_ifname, "<oif?>", sizeof(out_ifname)); if (uj) { json_ifp_out = json_object_new_object(); @@ -5117,6 +5705,97 @@ DEFUN (show_ip_mroute_count_vrf_all, return CMD_SUCCESS; } +static void show_mroute_summary(struct pim_instance *pim, struct vty *vty) +{ + struct listnode *node; + struct channel_oil *c_oil; + struct static_route *s_route; + uint32_t starg_sw_mroute_cnt = 0; + uint32_t sg_sw_mroute_cnt = 0; + uint32_t starg_hw_mroute_cnt = 0; + uint32_t sg_hw_mroute_cnt = 0; + + vty_out(vty, "Mroute Type Installed/Total\n"); + + for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) { + if (!c_oil->installed) { + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + starg_sw_mroute_cnt++; + else + sg_sw_mroute_cnt++; + } else { + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + starg_hw_mroute_cnt++; + else + sg_hw_mroute_cnt++; + } + } + + for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) { + if (!s_route->c_oil.installed) { + if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY) + starg_sw_mroute_cnt++; + else + sg_sw_mroute_cnt++; + } else { + if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY) + starg_hw_mroute_cnt++; + else + sg_hw_mroute_cnt++; + } + } + + vty_out(vty, "%-20s %d/%d\n", "(*, G)", starg_hw_mroute_cnt, + starg_sw_mroute_cnt + starg_hw_mroute_cnt); + vty_out(vty, "%-20s %d/%d\n", "(S, G)", sg_hw_mroute_cnt, + sg_sw_mroute_cnt + sg_hw_mroute_cnt); + vty_out(vty, "------\n"); + vty_out(vty, "%-20s %d/%d\n", "Total", + (starg_hw_mroute_cnt + sg_hw_mroute_cnt), + (starg_sw_mroute_cnt + + starg_hw_mroute_cnt + + sg_sw_mroute_cnt + + sg_hw_mroute_cnt)); +} + +DEFUN (show_ip_mroute_summary, + show_ip_mroute_summary_cmd, + "show ip mroute [vrf NAME] summary", + SHOW_STR + IP_STR + MROUTE_STR + VRF_CMD_HELP_STR + "Summary of all mroutes\n") +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + + if (!vrf) + return CMD_WARNING; + + show_mroute_summary(vrf->info, vty); + return CMD_SUCCESS; +} + +DEFUN (show_ip_mroute_summary_vrf_all, + show_ip_mroute_summary_vrf_all_cmd, + "show ip mroute vrf all summary", + SHOW_STR + IP_STR + MROUTE_STR + VRF_CMD_HELP_STR + "Summary of all mroutes\n") +{ + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + vty_out(vty, "VRF: %s\n", vrf->name); + show_mroute_summary(vrf->info, vty); + } + + return CMD_SUCCESS; +} + DEFUN (show_ip_rib, show_ip_rib_cmd, "show ip rib [vrf NAME] A.B.C.D", @@ -5233,7 +5912,13 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, { int result; - result = pim_rp_new(pim, rp, group, plist); + result = pim_rp_new_config(pim, rp, group, plist); + + if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) { + vty_out(vty, "%% Inconsistent address and mask: %s\n", + group); + return CMD_WARNING_CONFIG_FAILED; + } if (result == PIM_GROUP_BAD_ADDRESS) { vty_out(vty, "%% Bad group address specified: %s\n", group); @@ -5559,7 +6244,7 @@ static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, const char *rp, const char *group, const char *plist) { - int result = pim_rp_del(pim, rp, group, plist); + int result = pim_rp_del_config(pim, rp, group, plist); if (result == PIM_GROUP_BAD_ADDRESS) { vty_out(vty, "%% Bad group address specified: %s\n", group); @@ -5778,6 +6463,27 @@ DEFUN (show_ip_pim_group_type, return CMD_SUCCESS; } +DEFUN (show_ip_pim_bsr, + show_ip_pim_bsr_cmd, + "show ip pim bsr [json]", + SHOW_STR + IP_STR + PIM_STR + "boot-strap router information\n" + JSON_STR) +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + bool uj = use_json(argc, argv); + + if (!vrf) + return CMD_WARNING; + + pim_show_bsr(vrf->info, vty, uj); + + return CMD_SUCCESS; +} + DEFUN (ip_ssmpingd, ip_ssmpingd_cmd, "ip ssmpingd [A.B.C.D]", @@ -7226,6 +7932,7 @@ DEFUN (debug_pim, PIM_DO_DEBUG_PIM_TRACE; PIM_DO_DEBUG_MSDP_EVENTS; PIM_DO_DEBUG_MSDP_PACKETS; + PIM_DO_DEBUG_BSM; return CMD_SUCCESS; } @@ -7244,6 +7951,7 @@ DEFUN (no_debug_pim, PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; + PIM_DONT_DEBUG_BSM; return CMD_SUCCESS; } @@ -7629,6 +8337,30 @@ DEFUN (no_debug_mtrace, return CMD_SUCCESS; } +DEFUN (debug_bsm, + debug_bsm_cmd, + "debug pim bsm", + DEBUG_STR + DEBUG_PIM_STR + DEBUG_PIM_BSM_STR) +{ + PIM_DO_DEBUG_BSM; + return CMD_SUCCESS; +} + +DEFUN (no_debug_bsm, + no_debug_bsm_cmd, + "no debug pim bsm", + NO_STR + DEBUG_STR + DEBUG_PIM_STR + DEBUG_PIM_BSM_STR) +{ + PIM_DONT_DEBUG_BSM; + return CMD_SUCCESS; +} + + DEFUN_NOSH (show_debugging_pim, show_debugging_pim_cmd, "show debugging [pim]", @@ -7752,6 +8484,94 @@ DEFUN (no_ip_pim_bfd, return CMD_SUCCESS; } +DEFUN (ip_pim_bsm, + ip_pim_bsm_cmd, + "ip pim bsm", + IP_STR + PIM_STR + "Enables BSM support on the interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) { + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING; + } + } + + pim_ifp = ifp->info; + pim_ifp->bsm_enable = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_bsm, + no_ip_pim_bsm_cmd, + "no ip pim bsm", + NO_STR + IP_STR + PIM_STR + "Disables BSM support\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) { + vty_out(vty, "Pim not enabled on this interface\n"); + return CMD_WARNING; + } + + pim_ifp->bsm_enable = false; + + return CMD_SUCCESS; +} + +DEFUN (ip_pim_ucast_bsm, + ip_pim_ucast_bsm_cmd, + "ip pim unicast-bsm", + IP_STR + PIM_STR + "Accept/Send unicast BSM on the interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) { + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING; + } + } + + pim_ifp = ifp->info; + pim_ifp->ucast_bsm_accept = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_pim_ucast_bsm, + no_ip_pim_ucast_bsm_cmd, + "no ip pim unicast-bsm", + NO_STR + IP_STR + PIM_STR + "Block send/receive unicast BSM on this interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + + if (!pim_ifp) { + vty_out(vty, "Pim not enabled on this interface\n"); + return CMD_WARNING; + } + + pim_ifp->ucast_bsm_accept = false; + + return CMD_SUCCESS; +} + #if HAVE_BFDD > 0 DEFUN_HIDDEN( #else @@ -8269,7 +9089,7 @@ static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty, pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); } else { - strcpy(timebuf, "-"); + strlcpy(timebuf, "-", sizeof(timebuf)); } pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); pim_inet4_dump("<local?>", mp->local, local_str, @@ -8326,7 +9146,7 @@ static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty, pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); } else { - strcpy(timebuf, "-"); + strlcpy(timebuf, "-", sizeof(timebuf)); } pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); @@ -8505,18 +9325,18 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) if (sa->flags & PIM_MSDP_SAF_PEER) { pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); if (sa->up) { - strcpy(spt_str, "yes"); + strlcpy(spt_str, "yes", sizeof(spt_str)); } else { - strcpy(spt_str, "no"); + strlcpy(spt_str, "no", sizeof(spt_str)); } } else { - strcpy(rp_str, "-"); - strcpy(spt_str, "-"); + strlcpy(rp_str, "-", sizeof(rp_str)); + strlcpy(spt_str, "-", sizeof(spt_str)); } if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(local_str, "yes"); + strlcpy(local_str, "yes", sizeof(local_str)); } else { - strcpy(local_str, "no"); + strlcpy(local_str, "no", sizeof(local_str)); } if (uj) { json_object_object_get_ex(json, grp_str, &json_group); @@ -8570,19 +9390,19 @@ static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str)); if (sa->up) { - strcpy(spt_str, "yes"); + strlcpy(spt_str, "yes", sizeof(spt_str)); } else { - strcpy(spt_str, "no"); + strlcpy(spt_str, "no", sizeof(spt_str)); } } else { - strcpy(rp_str, "-"); - strcpy(peer_str, "-"); - strcpy(spt_str, "-"); + strlcpy(rp_str, "-", sizeof(rp_str)); + strlcpy(peer_str, "-", sizeof(peer_str)); + strlcpy(spt_str, "-", sizeof(spt_str)); } if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(local_str, "yes"); + strlcpy(local_str, "yes", sizeof(local_str)); } else { - strcpy(local_str, "no"); + strlcpy(local_str, "no", sizeof(local_str)); } pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), sa->sa_state_timer); @@ -9349,17 +10169,23 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); install_element(VIEW_NODE, &show_ip_pim_rp_cmd); install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd); + install_element(VIEW_NODE, &show_ip_pim_bsr_cmd); install_element(VIEW_NODE, &show_ip_multicast_cmd); install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_mroute_cmd); install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_mroute_count_cmd); install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd); + install_element(VIEW_NODE, &show_ip_mroute_summary_cmd); + install_element(VIEW_NODE, &show_ip_mroute_summary_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_rib_cmd); install_element(VIEW_NODE, &show_ip_ssmpingd_cmd); install_element(VIEW_NODE, &show_debugging_pim_cmd); install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd); install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); + install_element(VIEW_NODE, &show_ip_pim_bsrp_cmd); + install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd); + install_element(VIEW_NODE, &show_ip_pim_statistics_cmd); install_element(ENABLE_NODE, &clear_ip_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); @@ -9367,6 +10193,7 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd); install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd); install_element(ENABLE_NODE, &debug_igmp_cmd); install_element(ENABLE_NODE, &no_debug_igmp_cmd); @@ -9414,6 +10241,8 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd); install_element(ENABLE_NODE, &debug_mtrace_cmd); install_element(ENABLE_NODE, &no_debug_mtrace_cmd); + install_element(ENABLE_NODE, &debug_bsm_cmd); + install_element(ENABLE_NODE, &no_debug_bsm_cmd); install_element(CONFIG_NODE, &debug_igmp_cmd); install_element(CONFIG_NODE, &no_debug_igmp_cmd); @@ -9457,6 +10286,8 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd); install_element(CONFIG_NODE, &debug_mtrace_cmd); install_element(CONFIG_NODE, &no_debug_mtrace_cmd); + install_element(CONFIG_NODE, &debug_bsm_cmd); + install_element(CONFIG_NODE, &no_debug_bsm_cmd); install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd); @@ -9480,6 +10311,11 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd); install_element(INTERFACE_NODE, &interface_pim_use_source_cmd); install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd); + /* Install BSM command */ + install_element(INTERFACE_NODE, &ip_pim_bsm_cmd); + install_element(INTERFACE_NODE, &no_ip_pim_bsm_cmd); + install_element(INTERFACE_NODE, &ip_pim_ucast_bsm_cmd); + install_element(INTERFACE_NODE, &no_ip_pim_ucast_bsm_cmd); /* Install BFD command */ install_element(INTERFACE_NODE, &ip_pim_bfd_cmd); install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd); |
