diff options
Diffstat (limited to 'pimd/pim_cmd_common.c')
| -rw-r--r-- | pimd/pim_cmd_common.c | 681 |
1 files changed, 614 insertions, 67 deletions
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index afb360f9b5..28e4c488f3 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -566,6 +566,18 @@ int pim_process_rp_cmd(struct vty *vty, const char *rp_str, return CMD_WARNING_CONFIG_FAILED; } + if (pim_addr_is_any(rp_addr) || pim_addr_is_multicast(rp_addr)) { + vty_out(vty, "%% Bad RP address specified: %s\n", rp_str); + return CMD_WARNING_CONFIG_FAILED; + } + +#if PIM_IPV == 6 + if (IN6_IS_ADDR_LINKLOCAL(&rp_addr)) { + vty_out(vty, "%% Bad RP address specified: %s\n", rp_str); + return CMD_WARNING_CONFIG_FAILED; + } +#endif + vrfname = pim_cli_get_vrf_name(vty); if (vrfname == NULL) return CMD_WARNING_CONFIG_FAILED; @@ -1027,6 +1039,11 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, json_object *json) { struct channel_oil *c_oil; +#if PIM_IPV != 4 + struct ttable *tt = NULL; + char *table = NULL; +#endif + char flag[50]; json_object *json_group = NULL; json_object *json_ifp_in = NULL; json_object *json_ifp_out = NULL; @@ -1038,9 +1055,18 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, if (!json) { vty_out(vty, - "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted"); + "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n"); +#if PIM_IPV == 4 vty_out(vty, - "\nActive Source Group RPT IIF OIL\n"); + "Active Source Group RPT IIF OIL\n"); +#else + /* Prepare table. */ + tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + ttable_add_row(tt, "Active|Source|Group|RPT|IIF|OIL"); + tt->style.cell.rpad = 2; + tt->style.corner = '+'; + ttable_restyle(tt); +#endif } frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { @@ -1153,11 +1179,14 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, "wrongInterface", c_oil->cc.wrong_if); } - } else + } +#if PIM_IPV == 4 + else vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ", c_oil->installed, oil_origin(c_oil), oil_mcastgrp(c_oil), isRpt ? "y" : "n", in_ifname); +#endif for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { @@ -1199,72 +1228,72 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty, json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); } else { + flag[0] = '\0'; + snprintf(flag, sizeof(flag), "(%c%c%c%c%c)", + (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_GM) + ? 'I' + : ' ', + (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_VXLAN) + ? 'V' + : ' ', + (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' ', + (c_oil->oif_flags[oif_vif_index] & + PIM_OIF_FLAG_MUTE) + ? 'M' + : ' '); + if (first_oif) { first_oif = 0; - vty_out(vty, "%s(%c%c%c%c%c)", - out_ifname, - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_GM) - ? 'I' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_PIM) - ? 'J' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_VXLAN) - ? 'V' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_STAR) - ? '*' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_MUTE) - ? 'M' - : ' '); - } else - vty_out(vty, ", %s(%c%c%c%c%c)", - out_ifname, - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_GM) - ? 'I' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_PIM) - ? 'J' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_VXLAN) - ? 'V' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_PROTO_STAR) - ? '*' - : ' ', - (c_oil->oif_flags - [oif_vif_index] & - PIM_OIF_FLAG_MUTE) - ? 'M' - : ' '); +#if PIM_IPV == 4 + vty_out(vty, "%s%s", out_ifname, flag); +#else + ttable_add_row( + tt, "%d|%pPAs|%pPAs|%s|%s|%s%s", + c_oil->installed, + oil_origin(c_oil), + oil_mcastgrp(c_oil), + isRpt ? "y" : "n", in_ifname, + out_ifname, flag); +#endif + } else { +#if PIM_IPV == 4 + vty_out(vty, ", %s%s", out_ifname, + flag); +#else + ttable_add_row(tt, + "%c|%c|%c|%c|%c|%s%s", + ' ', ' ', ' ', ' ', ' ', + out_ifname, flag); +#endif + } } } - +#if PIM_IPV == 4 if (!json) vty_out(vty, "\n"); +#endif } - if (!json) + /* Dump the generated table. */ + if (!json) { +#if PIM_IPV == 4 vty_out(vty, "\n"); +#else + table = ttable_dump(tt, "\n"); + vty_out(vty, "%s\n", table); + XFREE(MTYPE_TMP, table); + ttable_del(tt); +#endif + } } /* pim statistics - just adding only bsm related now. @@ -2795,21 +2824,35 @@ static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg) struct nexthop *nh_node = NULL; ifindex_t first_ifindex; struct interface *ifp = NULL; + struct ttable *tt = NULL; + char *table = NULL; + + /* Prepare table. */ + tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + ttable_add_row(tt, "Address|Interface|Nexthop"); + tt->style.cell.rpad = 2; + tt->style.corner = '+'; + ttable_restyle(tt); for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { first_ifindex = nh_node->ifindex; ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id); - vty_out(vty, "%-15pPA ", &pnc->rpf.rpf_addr); - vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL"); #if PIM_IPV == 4 - vty_out(vty, "%pI4 ", &nh_node->gate.ipv4); + ttable_add_row(tt, "%pPA|%s|%pI4", &pnc->rpf.rpf_addr, + ifp ? ifp->name : "NULL", &nh_node->gate.ipv4); #else - vty_out(vty, "%pI6 ", &nh_node->gate.ipv6); + ttable_add_row(tt, "%pPA|%s|%pI6", &pnc->rpf.rpf_addr, + ifp ? ifp->name : "NULL", &nh_node->gate.ipv6); #endif - vty_out(vty, "\n"); } + /* Dump the generated table. */ + table = ttable_dump(tt, "\n"); + vty_out(vty, "%s\n", table); + XFREE(MTYPE_TMP, table); + ttable_del(tt); + return CMD_SUCCESS; } @@ -2937,8 +2980,6 @@ void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj) } else { vty_out(vty, "Number of registered addresses: %lu\n", pim->rpf_hash->count); - vty_out(vty, "Address Interface Nexthop\n"); - vty_out(vty, "---------------------------------------------\n"); } if (uj) { @@ -3399,6 +3440,66 @@ int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation, return nb_cli_apply_changes(vty, NULL); } +int pim_process_bsm_cmd(struct vty *vty) +{ + const struct lyd_node *gm_enable_dnode; + + gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode, + FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH, + FRR_PIM_AF_XPATH_VAL); + if (!gm_enable_dnode) + nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, + "true"); + else { + if (!yang_dnode_get_bool(gm_enable_dnode, ".")) + nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, + "true"); + } + + nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH, + FRR_PIM_AF_XPATH_VAL); +} + +int pim_process_no_bsm_cmd(struct vty *vty) +{ + nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false"); + + return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH, + FRR_PIM_AF_XPATH_VAL); +} + +int pim_process_unicast_bsm_cmd(struct vty *vty) +{ + const struct lyd_node *gm_enable_dnode; + + gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode, + FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH, + FRR_PIM_AF_XPATH_VAL); + if (!gm_enable_dnode) + nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, + "true"); + else { + if (!yang_dnode_get_bool(gm_enable_dnode, ".")) + nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, + "true"); + } + + nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH, + FRR_PIM_AF_XPATH_VAL); +} + +int pim_process_no_unicast_bsm_cmd(struct vty *vty) +{ + nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false"); + + return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH, + FRR_PIM_AF_XPATH_VAL); +} + static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, time_t now) { @@ -5166,3 +5267,449 @@ void clear_pim_interfaces(struct pim_instance *pim) pim_neighbor_delete_all(ifp, "interface cleared"); } } + +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]; + json_object *json = NULL; + + if (pim_addr_is_any(pim->global_scope.current_bsr)) { + 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 { + 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: + strlcpy(bsr_state, "NO_INFO", sizeof(bsr_state)); + break; + case ACCEPT_ANY: + strlcpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state)); + break; + case ACCEPT_PREFERRED: + strlcpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state)); + break; + default: + strlcpy(bsr_state, "", sizeof(bsr_state)); + } + + + if (uj) { + json = json_object_new_object(); + json_object_string_addf(json, "bsr", "%pPA", + &pim->global_scope.current_bsr); + json_object_int_add(json, "priority", + pim->global_scope.current_bsr_prio); + json_object_int_add(json, "fragmentTag", + 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, "lastBsmSeen", last_bsm_seen); + } + + else { + vty_out(vty, "PIMv2 Bootstrap information\n"); + vty_out(vty, "Current preferred BSR address: %pPA\n", + &pim->global_scope.current_bsr); + 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_json(vty, json); +} + +int pim_show_bsr_helper(const char *vrf, struct vty *vty, bool uj) +{ + struct pim_instance *pim; + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim = pim_get_pim_instance(v->vrf_id); + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_bsr(v->info, vty, uj); + + return CMD_SUCCESS; +} + +/*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 bsm_rpinfo *bsm_rp; + struct route_node *rn; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + struct ttable *tt = NULL; + + if (uj) { + json = json_object_new_object(); + json_object_string_addf(json, "BSR Address", "%pPA", + &pim->global_scope.current_bsr); + } else + vty_out(vty, "BSR Address %pPA\n", + &pim->global_scope.current_bsr); + + 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[PREFIX_STRLEN]; + + 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 %pFX\n", &bsgrp->group); + vty_out(vty, "--------------------------\n"); + /* Prepare table. */ + tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + ttable_add_row(tt, "Rp Address|priority|Holdtime|Hash"); + tt->style.cell.rpad = 2; + tt->style.corner = '+'; + ttable_restyle(tt); + + ttable_add_row(tt, "%s|%c|%c|%c", "(ACTIVE)", ' ', ' ', + ' '); + } + + frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) { + if (uj) { + json_row = json_object_new_object(); + json_object_string_addf(json_row, "Rp Address", + "%pPA", + &bsm_rp->rp_address); + 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_addf(json_group, json_row, + "%pPA", + &bsm_rp->rp_address); + + } else { + ttable_add_row( + tt, "%pPA|%u|%u|%u", + &bsm_rp->rp_address, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, bsm_rp->hash); + } + } + /* Dump the generated table. */ + if (tt) { + char *table = NULL; + + table = ttable_dump(tt, "\n"); + vty_out(vty, "%s\n", table); + XFREE(MTYPE_TMP, table); + ttable_del(tt); + tt = NULL; + } + if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !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) { + /* Prepare table. */ + tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + ttable_add_row( + tt, + "Rp Address|priority|Holdtime|Hash"); + tt->style.cell.rpad = 2; + tt->style.corner = '+'; + ttable_restyle(tt); + } + } + + frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) { + if (uj) { + json_row = json_object_new_object(); + json_object_string_addf(json_row, "Rp Address", + "%pPA", + &bsm_rp->rp_address); + 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_addf(json_group, json_row, + "%pPA", + &bsm_rp->rp_address); + } else { + ttable_add_row( + tt, "%pPA|%u|%u|%u", + &bsm_rp->rp_address, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, bsm_rp->hash); + } + } + /* Dump the generated table. */ + if (tt) { + char *table = NULL; + + table = ttable_dump(tt, "\n"); + vty_out(vty, "%s\n", table); + XFREE(MTYPE_TMP, table); + ttable_del(tt); + } + if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj) + vty_out(vty, "Partial List is empty\n"); + + if (!uj) + vty_out(vty, "\n"); + } + + if (uj) + vty_json(vty, json); +} + +int pim_show_group_rp_mappings_info_helper(const char *vrf, struct vty *vty, + bool uj) +{ + struct pim_instance *pim; + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim = v->info; + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_group_rp_mappings_info(v->info, vty, uj); + + return CMD_SUCCESS; +} + +/* Display the bsm database details */ +static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) +{ + int count = 0; + int fragment = 1; + struct bsm_frag *bsfrag; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + count = bsm_frags_count(pim->global_scope.bsm_frags); + + 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"); + } + + frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) { + char grp_str[PREFIX_STRLEN]; + struct bsmmsg_grpinfo *group; + struct bsmmsg_rpinfo *bsm_rpinfo; + struct prefix grp; + struct bsm_hdr *hdr; + pim_addr bsr_addr; + uint32_t offset = 0; + uint8_t *buf; + uint32_t len = 0; + uint32_t frag_rp_cnt = 0; + + buf = bsfrag->data; + len = bsfrag->size; + + /* skip pim header */ + buf += PIM_MSG_HEADER_LEN; + len -= PIM_MSG_HEADER_LEN; + + hdr = (struct bsm_hdr *)buf; + /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */ + memcpy(&bsr_addr, &hdr->bsr_addr.addr, sizeof(bsr_addr)); + + /* BSM starts with bsr header */ + buf += sizeof(struct bsm_hdr); + len -= sizeof(struct bsm_hdr); + + if (uj) { + json_object_string_addf(json, "BSR address", "%pPA", + &bsr_addr); + 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, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr, + 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; + else if (group->group.family == + PIM_MSG_ADDRESS_FAMILY_IPV6) + grp.family = AF_INET6; + + grp.prefixlen = group->group.mask; +#if PIM_IPV == 4 + grp.u.prefix4 = group->group.addr; +#else + grp.u.prefix6 = group->group.addr; +#endif + + 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--) { + pim_addr rp_addr; + + bsm_rpinfo = (struct bsmmsg_rpinfo *)buf; + /* unaligned, again */ + memcpy(&rp_addr, &bsm_rpinfo->rpaddr.addr, + sizeof(rp_addr)); + + buf += sizeof(struct bsmmsg_rpinfo); + offset += sizeof(struct bsmmsg_rpinfo); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_addf( + json_row, "Rp Address", "%pPA", + &rp_addr); + json_object_int_add( + json_row, "Rp HoldTime", + ntohs(bsm_rpinfo->rp_holdtime)); + json_object_int_add(json_row, + "Rp Priority", + bsm_rpinfo->rp_pri); + json_object_object_addf( + json_group, json_row, "%pPA", + &rp_addr); + } else { + vty_out(vty, "%-15pPA %-12d %d\n", + &rp_addr, + ntohs(bsm_rpinfo->rp_holdtime), + bsm_rpinfo->rp_pri); + } + } + vty_out(vty, "\n"); + } + + fragment++; + } + + if (uj) + vty_json(vty, json); +} + +int pim_show_bsm_db_helper(const char *vrf, struct vty *vty, bool uj) +{ + struct pim_instance *pim; + struct vrf *v; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + + if (!v) + return CMD_WARNING; + + pim = v->info; + + if (!pim) { + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + pim_show_bsm_db(v->info, vty, uj); + + return CMD_SUCCESS; +} |
