diff --git a/doc/user/pimv6.rst b/doc/user/pimv6.rst index 843734e21719..75e756a48846 100644 --- a/doc/user/pimv6.rst +++ b/doc/user/pimv6.rst @@ -162,6 +162,18 @@ is in a vrf, enter the interface command with the vrf keyword at the end. Disable sending and receiving pim control packets on the interface. +.. clicmd:: ipv6 pim bsm + + Tell pim that we would like to use this interface to process bootstrap + messages. This is enabled by default. 'no' form of this command is used to + restrict bsm messages on this interface. + +.. clicmd:: ipv6 pim unicast-bsm + + Tell pim that we would like to allow interface to process unicast bootstrap + messages. This is enabled by default. 'no' form of this command is used to + restrict processing of unicast bsm messages on this interface. + .. clicmd:: ipv6 mld Tell pim to receive MLD reports and Query on this interface. The default @@ -373,6 +385,18 @@ General multicast routing state Display total number of S,G mroutes and number of S,G mroutes installed into the kernel for all vrfs. +.. clicmd:: show ipv6 pim bsr + + Display current bsr, its uptime and last received bsm age. + +.. clicmd:: show ipv6 pim bsrp-info + + Display group-to-rp mappings received from E-BSR. + +.. clicmd:: show ipv6 pim bsm-database + + Display all fragments ofstored bootstrap message in user readable format. + PIMv6 Clear Commands ==================== @@ -456,3 +480,7 @@ the config was written out. .. clicmd:: debug mroute6 detail This turns on detailed debugging for PIMv6 interaction with kernel MFC cache. + +.. clicmd:: debug pimv6 bsm + + This turns on debugging for BSR message processing. diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index dc84de6bfd63..4c4271f1b7d4 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -476,6 +476,47 @@ DEFPY (no_ipv6_pim_rp_prefix_list, return pim_process_no_rp_plist_cmd(vty, rp_str, plist); } +DEFPY (ipv6_pim_bsm, + ipv6_pim_bsm_cmd, + "ipv6 pim bsm", + IPV6_STR + PIM_STR + "Enables BSM support on the interface\n") +{ + return pim_process_bsm_cmd(vty); +} + +DEFPY (no_ipv6_pim_bsm, + no_ipv6_pim_bsm_cmd, + "no ipv6 pim bsm", + NO_STR + IPV6_STR + PIM_STR + "Disables BSM support\n") +{ + return pim_process_no_bsm_cmd(vty); +} + +DEFPY (ipv6_pim_ucast_bsm, + ipv6_pim_ucast_bsm_cmd, + "ipv6 pim unicast-bsm", + IPV6_STR + PIM_STR + "Accept/Send unicast BSM on the interface\n") +{ + return pim_process_unicast_bsm_cmd(vty); +} + +DEFPY (no_ipv6_pim_ucast_bsm, + no_ipv6_pim_ucast_bsm_cmd, + "no ipv6 pim unicast-bsm", + NO_STR + IPV6_STR + PIM_STR + "Block send/receive unicast BSM on this interface\n") +{ + return pim_process_no_unicast_bsm_cmd(vty); +} DEFPY (ipv6_ssmpingd, ipv6_ssmpingd_cmd, @@ -1240,6 +1281,44 @@ DEFPY (show_ipv6_pim_interface_traffic, return pim_show_interface_traffic_helper(vrf, if_name, vty, !!json); } +DEFPY (show_ipv6_pim_bsr, + show_ipv6_pim_bsr_cmd, + "show ipv6 pim bsr [vrf NAME] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + "boot-strap router information\n" + VRF_CMD_HELP_STR + JSON_STR) +{ + return pim_show_bsr_helper(vrf, vty, !!json); +} + +DEFPY (show_ipv6_pim_bsm_db, + show_ipv6_pim_bsm_db_cmd, + "show ipv6 pim bsm-database [vrf NAME] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + "PIM cached bsm packets information\n" + VRF_CMD_HELP_STR + JSON_STR) +{ + return pim_show_bsm_db_helper(vrf, vty, !!json); +} + +DEFPY (show_ipv6_pim_bsrp, + show_ipv6_pim_bsrp_cmd, + "show ipv6 pim bsrp-info [vrf NAME] [json$json]", + SHOW_STR + IPV6_STR + PIM_STR + "PIM cached group-rp mappings information\n" + VRF_CMD_HELP_STR + JSON_STR) +{ + return pim_show_group_rp_mappings_info_helper(vrf, vty, !!json); +} DEFPY (clear_ipv6_pim_statistics, clear_ipv6_pim_statistics_cmd, @@ -1561,6 +1640,22 @@ DEFUN_NOSH (show_debugging_pimv6, return CMD_SUCCESS; } +DEFPY (debug_pimv6_bsm, + debug_pimv6_bsm_cmd, + "[no] debug pimv6 bsm", + NO_STR + DEBUG_STR + DEBUG_PIMV6_STR + DEBUG_PIMV6_BSM_STR) +{ + if (!no) + PIM_DO_DEBUG_BSM; + else + PIM_DONT_DEBUG_BSM; + + return CMD_SUCCESS; +} + void pim_cmd_init(void) { if_cmd_init(pim_interface_config_write); @@ -1598,6 +1693,11 @@ void pim_cmd_init(void) &interface_no_ipv6_pim_boundary_oil_cmd); install_element(INTERFACE_NODE, &interface_ipv6_mroute_cmd); install_element(INTERFACE_NODE, &interface_no_ipv6_mroute_cmd); + /* Install BSM command */ + install_element(INTERFACE_NODE, &ipv6_pim_bsm_cmd); + install_element(INTERFACE_NODE, &no_ipv6_pim_bsm_cmd); + install_element(INTERFACE_NODE, &ipv6_pim_ucast_bsm_cmd); + install_element(INTERFACE_NODE, &no_ipv6_pim_ucast_bsm_cmd); install_element(CONFIG_NODE, &ipv6_pim_rp_cmd); install_element(VRF_NODE, &ipv6_pim_rp_cmd); install_element(CONFIG_NODE, &no_ipv6_pim_rp_cmd); @@ -1670,7 +1770,8 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ipv6_mroute_summary_cmd); install_element(VIEW_NODE, &show_ipv6_mroute_summary_vrf_all_cmd); install_element(VIEW_NODE, &show_ipv6_pim_interface_traffic_cmd); - + install_element(VIEW_NODE, &show_ipv6_pim_bsr_cmd); + install_element(VIEW_NODE, &show_ipv6_pim_bsm_db_cmd); install_element(ENABLE_NODE, &clear_ipv6_pim_statistics_cmd); install_element(ENABLE_NODE, &clear_ipv6_mroute_cmd); install_element(ENABLE_NODE, &clear_ipv6_pim_oil_cmd); @@ -1693,6 +1794,7 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &debug_pimv6_zebra_cmd); install_element(ENABLE_NODE, &debug_mroute6_cmd); install_element(ENABLE_NODE, &debug_mroute6_detail_cmd); + install_element(ENABLE_NODE, &debug_pimv6_bsm_cmd); install_element(CONFIG_NODE, &debug_pimv6_cmd); install_element(CONFIG_NODE, &debug_pimv6_nht_cmd); @@ -1706,4 +1808,5 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &debug_pimv6_zebra_cmd); install_element(CONFIG_NODE, &debug_mroute6_cmd); install_element(CONFIG_NODE, &debug_mroute6_detail_cmd); + install_element(CONFIG_NODE, &debug_pimv6_bsm_cmd); } diff --git a/pimd/pim6_cmd.h b/pimd/pim6_cmd.h index c45c99845351..d9ff2ca70b5a 100644 --- a/pimd/pim6_cmd.h +++ b/pimd/pim6_cmd.h @@ -58,6 +58,7 @@ #define DEBUG_PIMV6_TRACE_STR "PIMv6 internal daemon activity\n" #define DEBUG_PIMV6_ZEBRA_STR "ZEBRA protocol activity\n" #define DEBUG_MROUTE6_STR "PIMv6 interaction with kernel MFC cache\n" +#define DEBUG_PIMV6_BSM_STR "BSR message processing activity\n" void pim_cmd_init(void); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c2f7396c180e..d8b93441ce4f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -837,285 +837,6 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty, } } -/* 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, - 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); -} - -/*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; - - 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"); - vty_out(vty, "%-15s %-15s %-15s %-15s\n", "Rp Address", - "priority", "Holdtime", "Hash"); - - vty_out(vty, "(ACTIVE)\n"); - } - - 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 { - vty_out(vty, "%-15pPA %-15u %-15u %-15u\n", - &bsm_rp->rp_address, bsm_rp->rp_prio, - bsm_rp->rp_holdtime, bsm_rp->hash); - } - } - 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) - vty_out(vty, "%-15s %-15s %-15s %-15s\n", - "Rp Address", "priority", "Holdtime", - "Hash"); - } - - 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 { - vty_out(vty, "%-15pPA %-15u %-15u %-15u\n", - &bsm_rp->rp_address, bsm_rp->rp_prio, - bsm_rp->rp_holdtime, bsm_rp->hash); - } - } - 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); -} - static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) { struct interface *ifp; @@ -1439,77 +1160,6 @@ 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]; - 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); -} - static void clear_igmp_interfaces(struct pim_instance *pim) { struct interface *ifp; @@ -2772,9 +2422,9 @@ DEFPY (show_ip_pim_interface_traffic, return pim_show_interface_traffic_helper(vrf, if_name, vty, !!json); } -DEFUN (show_ip_pim_bsm_db, +DEFPY (show_ip_pim_bsm_db, show_ip_pim_bsm_db_cmd, - "show ip pim bsm-database [vrf NAME] [json]", + "show ip pim bsm-database [vrf NAME] [json$json]", SHOW_STR IP_STR PIM_STR @@ -2782,20 +2432,12 @@ DEFUN (show_ip_pim_bsm_db, VRF_CMD_HELP_STR 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; + return pim_show_bsm_db_helper(vrf, vty, !!json); } -DEFUN (show_ip_pim_bsrp, +DEFPY (show_ip_pim_bsrp, show_ip_pim_bsrp_cmd, - "show ip pim bsrp-info [vrf NAME] [json]", + "show ip pim bsrp-info [vrf NAME] [json$json]", SHOW_STR IP_STR PIM_STR @@ -2803,16 +2445,7 @@ DEFUN (show_ip_pim_bsrp, VRF_CMD_HELP_STR 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; + return pim_show_group_rp_mappings_info_helper(vrf, vty, !!json); } DEFPY (show_ip_pim_statistics, @@ -3586,25 +3219,17 @@ DEFUN (show_ip_pim_group_type, return CMD_SUCCESS; } -DEFUN (show_ip_pim_bsr, +DEFPY (show_ip_pim_bsr, show_ip_pim_bsr_cmd, - "show ip pim bsr [json]", + "show ip pim bsr [vrf NAME] [json$json]", SHOW_STR IP_STR PIM_STR "boot-strap router information\n" + VRF_CMD_HELP_STR 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; + return pim_show_bsr_helper(vrf, vty, !!json); } DEFUN (ip_ssmpingd, @@ -5011,27 +4636,8 @@ DEFUN (ip_pim_bsm, PIM_STR "Enables BSM support on the interface\n") { - const struct lyd_node *igmp_enable_dnode; - - igmp_enable_dnode = - yang_dnode_getf(vty->candidate_config->dnode, - FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH, - "frr-routing:ipv4"); - if (!igmp_enable_dnode) - nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, - "true"); - else { - if (!yang_dnode_get_bool(igmp_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-routing:ipv4"); + return pim_process_bsm_cmd(vty); } - DEFUN (no_ip_pim_bsm, no_ip_pim_bsm_cmd, "no ip pim bsm", @@ -5040,10 +4646,7 @@ DEFUN (no_ip_pim_bsm, PIM_STR "Disables BSM support\n") { - nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false"); - - return nb_cli_apply_changes(vty, - FRR_PIM_INTERFACE_XPATH, "frr-routing:ipv4"); + return pim_process_no_bsm_cmd(vty); } DEFUN (ip_pim_ucast_bsm, @@ -5053,26 +4656,7 @@ DEFUN (ip_pim_ucast_bsm, PIM_STR "Accept/Send unicast BSM on the interface\n") { - const struct lyd_node *igmp_enable_dnode; - - igmp_enable_dnode = - yang_dnode_getf(vty->candidate_config->dnode, - FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH, - "frr-routing:ipv4"); - if (!igmp_enable_dnode) - nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, - "true"); - else { - if (!yang_dnode_get_bool(igmp_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-routing:ipv4"); - + return pim_process_unicast_bsm_cmd(vty); } DEFUN (no_ip_pim_ucast_bsm, @@ -5083,10 +4667,7 @@ DEFUN (no_ip_pim_ucast_bsm, PIM_STR "Block send/receive unicast BSM on this interface\n") { - nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false"); - - return nb_cli_apply_changes(vty, - FRR_PIM_INTERFACE_XPATH, "frr-routing:ipv4"); + return pim_process_no_unicast_bsm_cmd(vty); } #if HAVE_BFDD > 0 diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 9283016d0814..08f6c6f61efa 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -3416,6 +3416,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) { @@ -5183,3 +5243,416 @@ 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; + + 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"); + vty_out(vty, "%-15s %-15s %-15s %-15s\n", "Rp Address", + "priority", "Holdtime", "Hash"); + + vty_out(vty, "(ACTIVE)\n"); + } + + 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 { + vty_out(vty, "%-15pPA %-15u %-15u %-15u\n", + &bsm_rp->rp_address, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, bsm_rp->hash); + } + } + 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) + vty_out(vty, "%-15s %-15s %-15s %-15s\n", + "Rp Address", "priority", "Holdtime", + "Hash"); + } + + 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 { + vty_out(vty, "%-15pPA %-15u %-15u %-15u\n", + &bsm_rp->rp_address, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, bsm_rp->hash); + } + } + 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, + 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; +} diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 27c029670e59..d34a4af9e1ce 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -62,6 +62,10 @@ int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface, const char *group_str, const char *source_str); int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface, const char *group_str, const char *src_str); +int pim_process_bsm_cmd(struct vty *vty); +int pim_process_no_bsm_cmd(struct vty *vty); +int pim_process_unicast_bsm_cmd(struct vty *vty); +int pim_process_no_unicast_bsm_cmd(struct vty *vty); void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up); void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json); void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty); @@ -114,6 +118,9 @@ void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty, const char *neighbor, json_object *json); void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, json_object *json); +int pim_show_group_rp_mappings_info_helper(const char *vrf, struct vty *vty, + bool uj); +int pim_show_bsm_db_helper(const char *vrf, struct vty *vty, bool uj); int gm_process_query_max_response_time_cmd(struct vty *vty, const char *qmrt_str); int gm_process_no_query_max_response_time_cmd(struct vty *vty); @@ -186,6 +193,8 @@ void pim_show_interface_traffic(struct pim_instance *pim, struct vty *vty, int pim_show_interface_traffic_helper(const char *vrf, const char *if_name, struct vty *vty, bool uj); void clear_pim_interfaces(struct pim_instance *pim); +void pim_show_bsr(struct pim_instance *pim, struct vty *vty, bool uj); +int pim_show_bsr_helper(const char *vrf, struct vty *vty, bool uj); /* * Special Macro to allow us to get the correct pim_instance; */