}
}
-static void json_object_pim_ifp_add(struct json_object *json,
- struct interface *ifp)
-{
- struct pim_interface *pim_ifp;
-
- pim_ifp = ifp->info;
- json_object_string_add(json, "name", ifp->name);
- json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
- json_object_string_addf(json, "address", "%pI4",
- &pim_ifp->primary_address);
- json_object_int_add(json, "index", ifp->ifindex);
-
- if (if_is_multicast(ifp))
- json_object_boolean_true_add(json, "flagMulticast");
-
- if (if_is_broadcast(ifp))
- json_object_boolean_true_add(json, "flagBroadcast");
-
- if (ifp->flags & IFF_ALLMULTI)
- json_object_boolean_true_add(json, "flagAllMulticast");
-
- if (ifp->flags & IFF_PROMISC)
- json_object_boolean_true_add(json, "flagPromiscuous");
-
- if (PIM_IF_IS_DELETED(ifp))
- json_object_boolean_true_add(json, "flagDeleted");
-
- if (pim_if_lan_delay_enabled(ifp))
- json_object_boolean_true_add(json, "lanDelayEnabled");
-}
-
-static void pim_show_membership_helper(struct vty *vty,
- struct pim_interface *pim_ifp,
- struct pim_ifchannel *ch,
- struct json_object *json)
-{
- char ch_grp_str[PIM_ADDRSTRLEN];
- json_object *json_iface = NULL;
- json_object *json_row = NULL;
-
- json_object_object_get_ex(json, ch->interface->name, &json_iface);
- if (!json_iface) {
- json_iface = json_object_new_object();
- json_object_pim_ifp_add(json_iface, ch->interface);
- json_object_object_add(json, ch->interface->name, json_iface);
- }
-
- snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", &ch->sg.grp);
-
- json_row = json_object_new_object();
- json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
- json_object_string_add(json_row, "group", ch_grp_str);
- json_object_string_add(json_row, "localMembership",
- ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
- ? "NOINFO"
- : "INCLUDE");
- json_object_object_add(json_iface, ch_grp_str, json_row);
-}
-
-static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
- bool uj)
-{
- struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
- struct interface *ifp;
- enum json_type type;
- json_object *json = NULL;
- json_object *json_tmp = NULL;
-
- json = json_object_new_object();
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
- if (!pim_ifp)
- continue;
-
- RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
- pim_show_membership_helper(vty, pim_ifp, ch, json);
- } /* scan interface channels */
- }
-
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- } else {
- vty_out(vty,
- "Interface Address Source Group Membership\n");
-
- /*
- * Example of the json data we are traversing
- *
- * {
- * "swp3":{
- * "name":"swp3",
- * "state":"up",
- * "address":"10.1.20.1",
- * "index":5,
- * "flagMulticast":true,
- * "flagBroadcast":true,
- * "lanDelayEnabled":true,
- * "226.10.10.10":{
- * "source":"*",
- * "group":"226.10.10.10",
- * "localMembership":"INCLUDE"
- * }
- * }
- * }
- */
-
- /* foreach interface */
- json_object_object_foreach(json, key, val)
- {
-
- /* Find all of the keys where the val is an object. In
- * the example
- * above the only one is 226.10.10.10
- */
- json_object_object_foreach(val, if_field_key,
- if_field_val)
- {
- type = json_object_get_type(if_field_val);
-
- if (type == json_type_object) {
- vty_out(vty, "%-16s ", key);
-
- json_object_object_get_ex(
- val, "address", &json_tmp);
- vty_out(vty, "%-15s ",
- json_object_get_string(
- json_tmp));
-
- json_object_object_get_ex(if_field_val,
- "source",
- &json_tmp);
- vty_out(vty, "%-15s ",
- json_object_get_string(
- json_tmp));
-
- /* Group */
- vty_out(vty, "%-15s ", if_field_key);
-
- json_object_object_get_ex(
- if_field_val, "localMembership",
- &json_tmp);
- vty_out(vty, "%-10s\n",
- json_object_get_string(
- json_tmp));
- }
- }
- }
- }
-
- json_object_free(json);
-}
-
-static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
-{
- vty_out(vty, "Flags\n");
- vty_out(vty, "-----\n");
- vty_out(vty, "All Multicast : %s\n",
- (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
- vty_out(vty, "Broadcast : %s\n",
- if_is_broadcast(ifp) ? "yes" : "no");
- vty_out(vty, "Deleted : %s\n",
- PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
- vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
- vty_out(vty, "Multicast : %s\n",
- if_is_multicast(ifp) ? "yes" : "no");
- vty_out(vty, "Promiscuous : %s\n",
- (ifp->flags & IFF_PROMISC) ? "yes" : "no");
- vty_out(vty, "\n");
- vty_out(vty, "\n");
-}
-
static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
bool uj)
{
vty_json(vty, json);
}
-static void pim_show_interfaces_single(struct pim_instance *pim,
- struct vty *vty, const char *ifname,
- bool mlag, bool uj)
-{
- struct in_addr ifaddr;
- struct interface *ifp;
- struct listnode *neighnode;
- struct pim_interface *pim_ifp;
- struct pim_neighbor *neigh;
- struct pim_upstream *up;
- time_t now;
- char dr_str[INET_ADDRSTRLEN];
- char dr_uptime[10];
- char expire[10];
- char grp_str[INET_ADDRSTRLEN];
- char hello_period[10];
- char hello_timer[10];
- char neigh_src_str[INET_ADDRSTRLEN];
- char src_str[INET_ADDRSTRLEN];
- char stat_uptime[10];
- char uptime[10];
- int found_ifname = 0;
- int print_header;
- json_object *json = NULL;
- json_object *json_row = NULL;
- json_object *json_pim_neighbor = NULL;
- json_object *json_pim_neighbors = NULL;
- json_object *json_group = NULL;
- json_object *json_group_source = NULL;
- json_object *json_fhr_sources = NULL;
- struct pim_secondary_addr *sec_addr;
- struct listnode *sec_node;
-
- now = pim_time_monotonic_sec();
-
- if (uj)
- json = json_object_new_object();
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
-
- if (!pim_ifp)
- continue;
-
- if (mlag == true && pim_ifp->activeactive == false)
- continue;
-
- if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
- continue;
-
- found_ifname = 1;
- ifaddr = pim_ifp->primary_address;
- pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str,
- sizeof(dr_str));
- pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
- pim_ifp->pim_dr_election_last);
- pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
- pim_ifp->t_pim_hello_timer);
- pim_time_mmss(hello_period, sizeof(hello_period),
- pim_ifp->pim_hello_period);
- pim_time_uptime(stat_uptime, sizeof(stat_uptime),
- now - pim_ifp->pim_ifstat_start);
-
- if (uj) {
- char pbuf[PREFIX2STR_BUFFER];
- json_row = json_object_new_object();
- json_object_pim_ifp_add(json_row, ifp);
-
- if (pim_ifp->update_source.s_addr != INADDR_ANY) {
- json_object_string_addf(
- json_row, "useSource", "%pI4",
- &pim_ifp->update_source);
- }
- if (pim_ifp->sec_addr_list) {
- json_object *sec_list = NULL;
-
- sec_list = json_object_new_array();
- for (ALL_LIST_ELEMENTS_RO(
- pim_ifp->sec_addr_list, sec_node,
- sec_addr)) {
- json_object_array_add(
- sec_list,
- json_object_new_string(
- prefix2str(
- &sec_addr->addr,
- pbuf,
- sizeof(pbuf))));
- }
- json_object_object_add(json_row,
- "secondaryAddressList",
- sec_list);
- }
-
- // PIM neighbors
- if (pim_ifp->pim_neighbor_list->count) {
- json_pim_neighbors = json_object_new_object();
-
- for (ALL_LIST_ELEMENTS_RO(
- pim_ifp->pim_neighbor_list,
- neighnode, neigh)) {
- json_pim_neighbor =
- json_object_new_object();
- pim_inet4_dump("<src?>",
- neigh->source_addr,
- neigh_src_str,
- sizeof(neigh_src_str));
- pim_time_uptime(uptime, sizeof(uptime),
- now - neigh->creation);
- pim_time_timer_to_hhmmss(
- expire, sizeof(expire),
- neigh->t_expire_timer);
-
- json_object_string_add(
- json_pim_neighbor, "address",
- neigh_src_str);
- json_object_string_add(
- json_pim_neighbor, "upTime",
- uptime);
- json_object_string_add(
- json_pim_neighbor, "holdtime",
- expire);
-
- json_object_object_add(
- json_pim_neighbors,
- neigh_src_str,
- json_pim_neighbor);
- }
-
- json_object_object_add(json_row, "neighbors",
- json_pim_neighbors);
- }
-
- json_object_string_add(json_row, "drAddress", dr_str);
- json_object_int_add(json_row, "drPriority",
- pim_ifp->pim_dr_priority);
- json_object_string_add(json_row, "drUptime", dr_uptime);
- json_object_int_add(json_row, "drElections",
- pim_ifp->pim_dr_election_count);
- json_object_int_add(json_row, "drChanges",
- pim_ifp->pim_dr_election_changes);
-
- // FHR
- frr_each (rb_pim_upstream, &pim->upstream_head, up) {
- if (ifp != up->rpf.source_nexthop.interface)
- continue;
-
- if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
- continue;
-
- if (!json_fhr_sources)
- json_fhr_sources =
- json_object_new_object();
-
- snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
- &up->sg.grp);
- snprintfrr(src_str, sizeof(src_str), "%pPAs",
- &up->sg.src);
- pim_time_uptime(uptime, sizeof(uptime),
- now - up->state_transition);
-
- /*
- * Does this group live in json_fhr_sources?
- * If not create it.
- */
- json_object_object_get_ex(json_fhr_sources,
- grp_str, &json_group);
-
- if (!json_group) {
- json_group = json_object_new_object();
- json_object_object_add(json_fhr_sources,
- grp_str,
- json_group);
- }
-
- json_group_source = json_object_new_object();
- json_object_string_add(json_group_source,
- "source", src_str);
- json_object_string_add(json_group_source,
- "group", grp_str);
- json_object_string_add(json_group_source,
- "upTime", uptime);
- json_object_object_add(json_group, src_str,
- json_group_source);
- }
-
- if (json_fhr_sources) {
- json_object_object_add(json_row,
- "firstHopRouter",
- json_fhr_sources);
- }
-
- json_object_int_add(json_row, "helloPeriod",
- pim_ifp->pim_hello_period);
- json_object_int_add(json_row, "holdTime",
- PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
- json_object_string_add(json_row, "helloTimer",
- hello_timer);
- json_object_string_add(json_row, "helloStatStart",
- stat_uptime);
- json_object_int_add(json_row, "helloReceived",
- pim_ifp->pim_ifstat_hello_recv);
- json_object_int_add(json_row, "helloReceivedFailed",
- pim_ifp->pim_ifstat_hello_recvfail);
- json_object_int_add(json_row, "helloSend",
- pim_ifp->pim_ifstat_hello_sent);
- json_object_int_add(json_row, "hellosendFailed",
- pim_ifp->pim_ifstat_hello_sendfail);
- json_object_int_add(json_row, "helloGenerationId",
- pim_ifp->pim_generation_id);
-
- json_object_int_add(
- json_row, "effectivePropagationDelay",
- pim_if_effective_propagation_delay_msec(ifp));
- json_object_int_add(
- json_row, "effectiveOverrideInterval",
- pim_if_effective_override_interval_msec(ifp));
- json_object_int_add(
- json_row, "joinPruneOverrideInterval",
- pim_if_jp_override_interval_msec(ifp));
-
- json_object_int_add(
- json_row, "propagationDelay",
- pim_ifp->pim_propagation_delay_msec);
- json_object_int_add(
- json_row, "propagationDelayHighest",
- pim_ifp->pim_neighbors_highest_propagation_delay_msec);
- json_object_int_add(
- json_row, "overrideInterval",
- pim_ifp->pim_override_interval_msec);
- json_object_int_add(
- json_row, "overrideIntervalHighest",
- pim_ifp->pim_neighbors_highest_override_interval_msec);
- if (pim_ifp->bsm_enable)
- json_object_boolean_true_add(json_row,
- "bsmEnabled");
- if (pim_ifp->ucast_bsm_accept)
- json_object_boolean_true_add(json_row,
- "ucastBsmEnabled");
- json_object_object_add(json, ifp->name, json_row);
-
- } else {
- vty_out(vty, "Interface : %s\n", ifp->name);
- vty_out(vty, "State : %s\n",
- if_is_up(ifp) ? "up" : "down");
- if (pim_ifp->update_source.s_addr != INADDR_ANY) {
- vty_out(vty, "Use Source : %pI4\n",
- &pim_ifp->update_source);
- }
- if (pim_ifp->sec_addr_list) {
- vty_out(vty, "Address : %pI4 (primary)\n",
- &ifaddr);
- for (ALL_LIST_ELEMENTS_RO(
- pim_ifp->sec_addr_list, sec_node,
- sec_addr))
- vty_out(vty, " %pFX\n",
- &sec_addr->addr);
- } else {
- vty_out(vty, "Address : %pI4\n",
- &ifaddr);
- }
- vty_out(vty, "\n");
-
- // PIM neighbors
- print_header = 1;
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
- neighnode, neigh)) {
-
- if (print_header) {
- vty_out(vty, "PIM Neighbors\n");
- vty_out(vty, "-------------\n");
- print_header = 0;
- }
-
- pim_inet4_dump("<src?>", neigh->source_addr,
- neigh_src_str,
- sizeof(neigh_src_str));
- pim_time_uptime(uptime, sizeof(uptime),
- now - neigh->creation);
- pim_time_timer_to_hhmmss(expire, sizeof(expire),
- neigh->t_expire_timer);
- vty_out(vty,
- "%-15s : up for %s, holdtime expires in %s\n",
- neigh_src_str, uptime, expire);
- }
-
- if (!print_header) {
- vty_out(vty, "\n");
- vty_out(vty, "\n");
- }
-
- vty_out(vty, "Designated Router\n");
- vty_out(vty, "-----------------\n");
- vty_out(vty, "Address : %s\n", dr_str);
- vty_out(vty, "Priority : %u(%d)\n",
- pim_ifp->pim_dr_priority,
- pim_ifp->pim_dr_num_nondrpri_neighbors);
- vty_out(vty, "Uptime : %s\n", dr_uptime);
- vty_out(vty, "Elections : %d\n",
- pim_ifp->pim_dr_election_count);
- vty_out(vty, "Changes : %d\n",
- pim_ifp->pim_dr_election_changes);
- vty_out(vty, "\n");
- vty_out(vty, "\n");
-
- // FHR
- print_header = 1;
- frr_each (rb_pim_upstream, &pim->upstream_head, up) {
- if (!up->rpf.source_nexthop.interface)
- continue;
-
- if (strcmp(ifp->name,
- up->rpf.source_nexthop
- .interface->name)
- != 0)
- continue;
-
- if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
- continue;
-
- if (print_header) {
- vty_out(vty,
- "FHR - First Hop Router\n");
- vty_out(vty,
- "----------------------\n");
- print_header = 0;
- }
-
- pim_time_uptime(uptime, sizeof(uptime),
- now - up->state_transition);
- vty_out(vty,
- "%pPAs : %pPAs is a source, uptime is %s\n",
- &up->sg.grp, &up->sg.src, uptime);
- }
-
- if (!print_header) {
- vty_out(vty, "\n");
- vty_out(vty, "\n");
- }
-
- vty_out(vty, "Hellos\n");
- vty_out(vty, "------\n");
- vty_out(vty, "Period : %d\n",
- pim_ifp->pim_hello_period);
- vty_out(vty, "HoldTime : %d\n",
- PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
- vty_out(vty, "Timer : %s\n", hello_timer);
- vty_out(vty, "StatStart : %s\n", stat_uptime);
- vty_out(vty, "Receive : %d\n",
- pim_ifp->pim_ifstat_hello_recv);
- vty_out(vty, "Receive Failed : %d\n",
- pim_ifp->pim_ifstat_hello_recvfail);
- vty_out(vty, "Send : %d\n",
- pim_ifp->pim_ifstat_hello_sent);
- vty_out(vty, "Send Failed : %d\n",
- pim_ifp->pim_ifstat_hello_sendfail);
- vty_out(vty, "Generation ID : %08x\n",
- pim_ifp->pim_generation_id);
- vty_out(vty, "\n");
- vty_out(vty, "\n");
-
- pim_print_ifp_flags(vty, ifp);
-
- vty_out(vty, "Join Prune Interval\n");
- vty_out(vty, "-------------------\n");
- vty_out(vty, "LAN Delay : %s\n",
- pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
- vty_out(vty, "Effective Propagation Delay : %d msec\n",
- pim_if_effective_propagation_delay_msec(ifp));
- vty_out(vty, "Effective Override Interval : %d msec\n",
- pim_if_effective_override_interval_msec(ifp));
- vty_out(vty, "Join Prune Override Interval : %d msec\n",
- pim_if_jp_override_interval_msec(ifp));
- vty_out(vty, "\n");
- vty_out(vty, "\n");
-
- vty_out(vty, "LAN Prune Delay\n");
- vty_out(vty, "---------------\n");
- vty_out(vty, "Propagation Delay : %d msec\n",
- pim_ifp->pim_propagation_delay_msec);
- vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
- pim_ifp->pim_neighbors_highest_propagation_delay_msec);
- vty_out(vty, "Override Interval : %d msec\n",
- pim_ifp->pim_override_interval_msec);
- vty_out(vty, "Override Interval (Highest) : %d msec\n",
- pim_ifp->pim_neighbors_highest_override_interval_msec);
- vty_out(vty, "\n");
- vty_out(vty, "\n");
-
- vty_out(vty, "BSM Status\n");
- vty_out(vty, "----------\n");
- vty_out(vty, "Bsm Enabled : %s\n",
- pim_ifp->bsm_enable ? "yes" : "no");
- vty_out(vty, "Unicast Bsm Enabled : %s\n",
- pim_ifp->ucast_bsm_accept ? "yes" : "no");
- vty_out(vty, "\n");
- vty_out(vty, "\n");
- }
- }
-
- if (uj)
- vty_json(vty, json);
- else if (!found_ifname)
- vty_out(vty, "%% No such interface\n");
-}
-
static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
const char *ifname, bool uj)
{
}
}
-static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
- bool mlag, bool uj)
-{
- struct interface *ifp;
- struct pim_interface *pim_ifp;
- struct pim_upstream *up;
- int fhr = 0;
- int pim_nbrs = 0;
- int pim_ifchannels = 0;
- json_object *json = NULL;
- json_object *json_row = NULL;
- json_object *json_tmp;
-
- json = json_object_new_object();
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
-
- if (!pim_ifp)
- continue;
-
- if (mlag == true && pim_ifp->activeactive == false)
- continue;
-
- pim_nbrs = pim_ifp->pim_neighbor_list->count;
- pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
- fhr = 0;
-
- frr_each (rb_pim_upstream, &pim->upstream_head, up)
- if (ifp == up->rpf.source_nexthop.interface)
- if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
- fhr++;
-
- json_row = json_object_new_object();
- json_object_pim_ifp_add(json_row, ifp);
- json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
- json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
- json_object_int_add(json_row, "firstHopRouterCount", fhr);
- json_object_string_addf(json_row, "pimDesignatedRouter", "%pI4",
- &pim_ifp->pim_dr_addr);
-
- if (pim_ifp->pim_dr_addr.s_addr
- == pim_ifp->primary_address.s_addr)
- json_object_boolean_true_add(
- json_row, "pimDesignatedRouterLocal");
-
- json_object_object_add(json, ifp->name, json_row);
- }
-
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- } else {
- vty_out(vty,
- "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
-
- json_object_object_foreach(json, key, val)
- {
- vty_out(vty, "%-16s ", key);
-
- json_object_object_get_ex(val, "state", &json_tmp);
- vty_out(vty, "%5s ", json_object_get_string(json_tmp));
-
- json_object_object_get_ex(val, "address", &json_tmp);
- vty_out(vty, "%15s ",
- json_object_get_string(json_tmp));
-
- json_object_object_get_ex(val, "pimNeighbors",
- &json_tmp);
- vty_out(vty, "%8d ", json_object_get_int(json_tmp));
-
- if (json_object_object_get_ex(
- val, "pimDesignatedRouterLocal",
- &json_tmp)) {
- vty_out(vty, "%15s ", "local");
- } else {
- json_object_object_get_ex(
- val, "pimDesignatedRouter", &json_tmp);
- vty_out(vty, "%15s ",
- json_object_get_string(json_tmp));
- }
-
- json_object_object_get_ex(val, "firstHopRouter",
- &json_tmp);
- vty_out(vty, "%3d ", json_object_get_int(json_tmp));
-
- json_object_object_get_ex(val, "pimIfChannels",
- &json_tmp);
- vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
- }
- }
-
- json_object_free(json);
-}
-
-static void pim_show_interface_traffic(struct pim_instance *pim,
- struct vty *vty, bool uj)
-{
- struct interface *ifp = NULL;
- struct pim_interface *pim_ifp = NULL;
- json_object *json = NULL;
- json_object *json_row = NULL;
-
- if (uj)
- json = json_object_new_object();
- else {
- vty_out(vty, "\n");
- vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
- "Interface", " HELLO", " JOIN",
- " PRUNE", " REGISTER", "REGISTER-STOP",
- " 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");
- vty_out(vty,
- "---------------------------------------------------------------------------------------------------------------\n");
- }
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
-
- if (!pim_ifp)
- continue;
-
- if (pim_ifp->pim_sock_fd < 0)
- continue;
- if (uj) {
- json_row = json_object_new_object();
- json_object_pim_ifp_add(json_row, ifp);
- json_object_int_add(json_row, "helloRx",
- pim_ifp->pim_ifstat_hello_recv);
- json_object_int_add(json_row, "helloTx",
- pim_ifp->pim_ifstat_hello_sent);
- json_object_int_add(json_row, "joinRx",
- pim_ifp->pim_ifstat_join_recv);
- json_object_int_add(json_row, "joinTx",
- pim_ifp->pim_ifstat_join_send);
- json_object_int_add(json_row, "pruneTx",
- pim_ifp->pim_ifstat_prune_send);
- json_object_int_add(json_row, "pruneRx",
- pim_ifp->pim_ifstat_prune_recv);
- json_object_int_add(json_row, "registerRx",
- pim_ifp->pim_ifstat_reg_recv);
- json_object_int_add(json_row, "registerTx",
- pim_ifp->pim_ifstat_reg_recv);
- json_object_int_add(json_row, "registerStopRx",
- pim_ifp->pim_ifstat_reg_stop_recv);
- json_object_int_add(json_row, "registerStopTx",
- pim_ifp->pim_ifstat_reg_stop_send);
- 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);
- 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 %7" PRIu64 "/%-7" PRIu64 "\n",
- ifp->name, pim_ifp->pim_ifstat_hello_recv,
- pim_ifp->pim_ifstat_hello_sent,
- pim_ifp->pim_ifstat_join_recv,
- pim_ifp->pim_ifstat_join_send,
- pim_ifp->pim_ifstat_prune_recv,
- pim_ifp->pim_ifstat_prune_send,
- pim_ifp->pim_ifstat_reg_recv,
- pim_ifp->pim_ifstat_reg_send,
- 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_bsm_rx,
- pim_ifp->pim_ifstat_bsm_tx);
- }
- }
- if (uj)
- vty_json(vty, json);
-}
-
-static void pim_show_interface_traffic_single(struct pim_instance *pim,
- struct vty *vty,
- const char *ifname, bool uj)
-{
- struct interface *ifp = NULL;
- struct pim_interface *pim_ifp = NULL;
- json_object *json = NULL;
- json_object *json_row = NULL;
- uint8_t found_ifname = 0;
-
- if (uj)
- json = json_object_new_object();
- else {
- vty_out(vty, "\n");
- vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
- "Interface", " HELLO", " JOIN", " PRUNE",
- " 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");
- vty_out(vty,
- "-------------------------------------------------------------------------------------------------------------------------------\n");
- }
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- if (strcmp(ifname, ifp->name))
- continue;
-
- pim_ifp = ifp->info;
-
- if (!pim_ifp)
- continue;
-
- if (pim_ifp->pim_sock_fd < 0)
- continue;
-
- found_ifname = 1;
- if (uj) {
- json_row = json_object_new_object();
- json_object_pim_ifp_add(json_row, ifp);
- json_object_int_add(json_row, "helloRx",
- pim_ifp->pim_ifstat_hello_recv);
- json_object_int_add(json_row, "helloTx",
- pim_ifp->pim_ifstat_hello_sent);
- json_object_int_add(json_row, "joinRx",
- pim_ifp->pim_ifstat_join_recv);
- json_object_int_add(json_row, "joinTx",
- pim_ifp->pim_ifstat_join_send);
- json_object_int_add(json_row, "pruneRx",
- pim_ifp->pim_ifstat_prune_recv);
- json_object_int_add(json_row, "pruneTx",
- pim_ifp->pim_ifstat_prune_send);
- json_object_int_add(json_row, "registerRx",
- pim_ifp->pim_ifstat_reg_recv);
- json_object_int_add(json_row, "registerTx",
- pim_ifp->pim_ifstat_reg_recv);
- json_object_int_add(json_row, "registerStopRx",
- pim_ifp->pim_ifstat_reg_stop_recv);
- json_object_int_add(json_row, "registerStopTx",
- pim_ifp->pim_ifstat_reg_stop_send);
- 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);
- 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 %7" PRIu64 "/%-7" PRIu64 "\n",
- ifp->name, pim_ifp->pim_ifstat_hello_recv,
- pim_ifp->pim_ifstat_hello_sent,
- pim_ifp->pim_ifstat_join_recv,
- pim_ifp->pim_ifstat_join_send,
- pim_ifp->pim_ifstat_prune_recv,
- pim_ifp->pim_ifstat_prune_send,
- pim_ifp->pim_ifstat_reg_recv,
- pim_ifp->pim_ifstat_reg_send,
- 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_bsm_rx,
- pim_ifp->pim_ifstat_bsm_tx);
- }
- }
- if (uj)
- vty_json(vty, json);
- else if (!found_ifname)
- vty_out(vty, "%% No such interface\n");
-}
-
-static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
- struct pim_ifchannel *ch, json_object *json,
- time_t now, bool uj)
-{
- json_object *json_iface = NULL;
- json_object *json_row = NULL;
- json_object *json_grp = NULL;
- struct in_addr ifaddr;
- char uptime[10];
- char expire[10];
- char prune[10];
- char buf[PREFIX_STRLEN];
-
- ifaddr = pim_ifp->primary_address;
-
- pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
- pim_time_timer_to_mmss(expire, sizeof(expire),
- ch->t_ifjoin_expiry_timer);
- pim_time_timer_to_mmss(prune, sizeof(prune),
- ch->t_ifjoin_prune_pending_timer);
-
- if (uj) {
- char ch_grp_str[PIM_ADDRSTRLEN];
- char ch_src_str[PIM_ADDRSTRLEN];
-
- snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
- &ch->sg.grp);
- snprintfrr(ch_src_str, sizeof(ch_src_str), "%pPAs",
- &ch->sg.src);
-
- json_object_object_get_ex(json, ch->interface->name,
- &json_iface);
-
- if (!json_iface) {
- json_iface = json_object_new_object();
- json_object_pim_ifp_add(json_iface, ch->interface);
- json_object_object_add(json, ch->interface->name,
- json_iface);
- }
-
- json_row = json_object_new_object();
- json_object_string_add(json_row, "source", ch_src_str);
- json_object_string_add(json_row, "group", ch_grp_str);
- json_object_string_add(json_row, "upTime", uptime);
- json_object_string_add(json_row, "expire", expire);
- json_object_string_add(json_row, "prune", prune);
- json_object_string_add(
- json_row, "channelJoinName",
- pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
- if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
-#if CONFDATE > 20230131
-CPP_NOTICE("Remove JSON object commands with keys starting with capital")
-#endif
- json_object_int_add(json_row, "SGRpt", 1);
- json_object_int_add(json_row, "sgRpt", 1);
- }
- if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
- json_object_int_add(json_row, "protocolPim", 1);
- if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
- json_object_int_add(json_row, "protocolIgmp", 1);
- json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
- if (!json_grp) {
- json_grp = json_object_new_object();
- json_object_object_add(json_grp, ch_src_str, json_row);
- json_object_object_add(json_iface, ch_grp_str,
- json_grp);
- } else
- json_object_object_add(json_grp, ch_src_str, json_row);
- } else {
- vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
- ch->interface->name,
- inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
- &ch->sg.src, &ch->sg.grp,
- pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
- uptime, expire, prune);
- }
-}
-
-static void pim_show_join(struct pim_instance *pim, struct vty *vty,
- pim_sgaddr *sg, bool uj)
-{
- struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
- struct interface *ifp;
- time_t now;
- json_object *json = NULL;
-
- now = pim_time_monotonic_sec();
-
- if (uj)
- json = json_object_new_object();
- else
- vty_out(vty,
- "Interface Address Source Group State Uptime Expire Prune\n");
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
- if (!pim_ifp)
- continue;
-
- RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
- if (!pim_sgaddr_match(ch->sg, *sg))
- continue;
- pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
- } /* scan interface channels */
- }
-
- if (uj)
- vty_json(vty, json);
-}
-
-static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
- const char *neighbor, bool uj)
-{
- struct listnode *neighnode;
- struct interface *ifp;
- struct pim_interface *pim_ifp;
- struct pim_neighbor *neigh;
- time_t now;
- int found_neighbor = 0;
- int option_address_list;
- int option_dr_priority;
- int option_generation_id;
- int option_holdtime;
- int option_lan_prune_delay;
- int option_t_bit;
- char uptime[10];
- char expire[10];
- char neigh_src_str[INET_ADDRSTRLEN];
-
- json_object *json = NULL;
- json_object *json_ifp = NULL;
- json_object *json_row = NULL;
-
- now = pim_time_monotonic_sec();
-
- if (uj)
- json = json_object_new_object();
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
-
- if (!pim_ifp)
- continue;
-
- if (pim_ifp->pim_sock_fd < 0)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
- neigh)) {
- pim_inet4_dump("<src?>", neigh->source_addr,
- neigh_src_str, sizeof(neigh_src_str));
-
- /*
- * The user can specify either the interface name or the
- * PIM neighbor IP.
- * If this pim_ifp matches neither then skip.
- */
- if (strcmp(neighbor, "detail")
- && strcmp(neighbor, ifp->name)
- && strcmp(neighbor, neigh_src_str))
- continue;
-
- found_neighbor = 1;
- pim_time_uptime(uptime, sizeof(uptime),
- now - neigh->creation);
- pim_time_timer_to_hhmmss(expire, sizeof(expire),
- neigh->t_expire_timer);
-
- option_address_list = 0;
- option_dr_priority = 0;
- option_generation_id = 0;
- option_holdtime = 0;
- option_lan_prune_delay = 0;
- option_t_bit = 0;
-
- if (PIM_OPTION_IS_SET(neigh->hello_options,
- PIM_OPTION_MASK_ADDRESS_LIST))
- option_address_list = 1;
-
- if (PIM_OPTION_IS_SET(neigh->hello_options,
- PIM_OPTION_MASK_DR_PRIORITY))
- option_dr_priority = 1;
-
- if (PIM_OPTION_IS_SET(neigh->hello_options,
- PIM_OPTION_MASK_GENERATION_ID))
- option_generation_id = 1;
-
- if (PIM_OPTION_IS_SET(neigh->hello_options,
- PIM_OPTION_MASK_HOLDTIME))
- option_holdtime = 1;
-
- if (PIM_OPTION_IS_SET(neigh->hello_options,
- PIM_OPTION_MASK_LAN_PRUNE_DELAY))
- option_lan_prune_delay = 1;
-
- if (PIM_OPTION_IS_SET(
- neigh->hello_options,
- PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
- option_t_bit = 1;
-
- if (uj) {
-
- /* Does this ifp live in json? If not create
- * it. */
- json_object_object_get_ex(json, ifp->name,
- &json_ifp);
-
- if (!json_ifp) {
- json_ifp = json_object_new_object();
- json_object_pim_ifp_add(json_ifp, ifp);
- json_object_object_add(json, ifp->name,
- json_ifp);
- }
-
- json_row = json_object_new_object();
- json_object_string_add(json_row, "interface",
- ifp->name);
- json_object_string_add(json_row, "address",
- neigh_src_str);
- json_object_string_add(json_row, "upTime",
- uptime);
- json_object_string_add(json_row, "holdtime",
- expire);
- json_object_int_add(json_row, "drPriority",
- neigh->dr_priority);
- json_object_int_add(json_row, "generationId",
- neigh->generation_id);
-
- if (option_address_list)
- json_object_boolean_true_add(
- json_row,
- "helloOptionAddressList");
-
- if (option_dr_priority)
- json_object_boolean_true_add(
- json_row,
- "helloOptionDrPriority");
-
- if (option_generation_id)
- json_object_boolean_true_add(
- json_row,
- "helloOptionGenerationId");
-
- if (option_holdtime)
- json_object_boolean_true_add(
- json_row,
- "helloOptionHoldtime");
-
- if (option_lan_prune_delay)
- json_object_boolean_true_add(
- json_row,
- "helloOptionLanPruneDelay");
-
- if (option_t_bit)
- json_object_boolean_true_add(
- json_row, "helloOptionTBit");
-
- json_object_object_add(json_ifp, neigh_src_str,
- json_row);
-
- } else {
- vty_out(vty, "Interface : %s\n", ifp->name);
- vty_out(vty, "Neighbor : %s\n", neigh_src_str);
- vty_out(vty,
- " Uptime : %s\n",
- uptime);
- vty_out(vty,
- " Holdtime : %s\n",
- expire);
- vty_out(vty,
- " DR Priority : %d\n",
- neigh->dr_priority);
- vty_out(vty,
- " Generation ID : %08x\n",
- neigh->generation_id);
- vty_out(vty,
- " Override Interval (msec) : %d\n",
- neigh->override_interval_msec);
- vty_out(vty,
- " Propagation Delay (msec) : %d\n",
- neigh->propagation_delay_msec);
- vty_out(vty,
- " Hello Option - Address List : %s\n",
- option_address_list ? "yes" : "no");
- vty_out(vty,
- " Hello Option - DR Priority : %s\n",
- option_dr_priority ? "yes" : "no");
- vty_out(vty,
- " Hello Option - Generation ID : %s\n",
- option_generation_id ? "yes" : "no");
- vty_out(vty,
- " Hello Option - Holdtime : %s\n",
- option_holdtime ? "yes" : "no");
- vty_out(vty,
- " Hello Option - LAN Prune Delay : %s\n",
- option_lan_prune_delay ? "yes" : "no");
- vty_out(vty,
- " Hello Option - T-bit : %s\n",
- option_t_bit ? "yes" : "no");
- bfd_sess_show(vty, json_ifp,
- neigh->bfd_session);
- vty_out(vty, "\n");
- }
- }
- }
-
- if (uj)
- vty_json(vty, json);
- else if (!found_neighbor)
- vty_out(vty, "%% No such interface or neighbor\n");
-}
-
-static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
- bool uj)
+static void pim_show_interface_traffic(struct pim_instance *pim,
+ struct vty *vty, bool uj)
{
- struct listnode *neighnode;
- struct interface *ifp;
- struct pim_interface *pim_ifp;
- struct pim_neighbor *neigh;
- time_t now;
- char uptime[10];
- char expire[10];
- char neigh_src_str[INET_ADDRSTRLEN];
+ struct interface *ifp = NULL;
+ struct pim_interface *pim_ifp = NULL;
json_object *json = NULL;
- json_object *json_ifp_rows = NULL;
json_object *json_row = NULL;
- now = pim_time_monotonic_sec();
-
- if (uj) {
+ if (uj)
json = json_object_new_object();
- } else {
+ else {
+ vty_out(vty, "\n");
+ vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+ "Interface", " HELLO", " JOIN",
+ " PRUNE", " REGISTER", "REGISTER-STOP",
+ " 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");
vty_out(vty,
- "Interface Neighbor Uptime Holdtime DR Pri\n");
+ "---------------------------------------------------------------------------------------------------------------\n");
}
FOR_ALL_INTERFACES (pim->vrf, ifp) {
if (pim_ifp->pim_sock_fd < 0)
continue;
-
- if (uj)
- json_ifp_rows = json_object_new_object();
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
- neigh)) {
- pim_inet4_dump("<src?>", neigh->source_addr,
- neigh_src_str, sizeof(neigh_src_str));
- pim_time_uptime(uptime, sizeof(uptime),
- now - neigh->creation);
- pim_time_timer_to_hhmmss(expire, sizeof(expire),
- neigh->t_expire_timer);
-
- if (uj) {
- json_row = json_object_new_object();
- json_object_string_add(json_row, "interface",
- ifp->name);
- json_object_string_add(json_row, "neighbor",
- neigh_src_str);
- json_object_string_add(json_row, "upTime",
- uptime);
- json_object_string_add(json_row, "holdTime",
- expire);
- json_object_int_add(json_row, "holdTimeMax",
- neigh->holdtime);
- json_object_int_add(json_row, "drPriority",
- neigh->dr_priority);
- json_object_object_add(json_ifp_rows,
- neigh_src_str, json_row);
-
- } else {
- vty_out(vty, "%-16s %15s %8s %8s %6d\n",
- ifp->name, neigh_src_str, uptime,
- expire, neigh->dr_priority);
- }
- }
-
if (uj) {
- json_object_object_add(json, ifp->name, json_ifp_rows);
- json_ifp_rows = NULL;
+ json_row = json_object_new_object();
+ json_object_pim_ifp_add(json_row, ifp);
+ json_object_int_add(json_row, "helloRx",
+ pim_ifp->pim_ifstat_hello_recv);
+ json_object_int_add(json_row, "helloTx",
+ pim_ifp->pim_ifstat_hello_sent);
+ json_object_int_add(json_row, "joinRx",
+ pim_ifp->pim_ifstat_join_recv);
+ json_object_int_add(json_row, "joinTx",
+ pim_ifp->pim_ifstat_join_send);
+ json_object_int_add(json_row, "pruneTx",
+ pim_ifp->pim_ifstat_prune_send);
+ json_object_int_add(json_row, "pruneRx",
+ pim_ifp->pim_ifstat_prune_recv);
+ json_object_int_add(json_row, "registerRx",
+ pim_ifp->pim_ifstat_reg_recv);
+ json_object_int_add(json_row, "registerTx",
+ pim_ifp->pim_ifstat_reg_recv);
+ json_object_int_add(json_row, "registerStopRx",
+ pim_ifp->pim_ifstat_reg_stop_recv);
+ json_object_int_add(json_row, "registerStopTx",
+ pim_ifp->pim_ifstat_reg_stop_send);
+ 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);
+ 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 %7" PRIu64 "/%-7" PRIu64 "\n",
+ ifp->name, pim_ifp->pim_ifstat_hello_recv,
+ pim_ifp->pim_ifstat_hello_sent,
+ pim_ifp->pim_ifstat_join_recv,
+ pim_ifp->pim_ifstat_join_send,
+ pim_ifp->pim_ifstat_prune_recv,
+ pim_ifp->pim_ifstat_prune_send,
+ pim_ifp->pim_ifstat_reg_recv,
+ pim_ifp->pim_ifstat_reg_send,
+ 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_bsm_rx,
+ pim_ifp->pim_ifstat_bsm_tx);
}
}
-
if (uj)
vty_json(vty, json);
}
-static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
- struct pim_interface *pim_ifp,
- struct pim_ifchannel *ch, json_object *json,
- bool uj)
-{
- struct pim_upstream *up = ch->upstream;
- json_object *json_group = NULL;
- json_object *json_row = NULL;
-
- if (uj) {
- char grp_str[PIM_ADDRSTRLEN];
- char src_str[PIM_ADDRSTRLEN];
-
- snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
- snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
-
- 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);
- }
-
- json_row = json_object_new_object();
- json_object_pim_upstream_add(json_row, up);
- json_object_string_add(json_row, "interface",
- ch->interface->name);
- json_object_string_add(json_row, "source", src_str);
- json_object_string_add(json_row, "group", grp_str);
-
- if (pim_macro_ch_lost_assert(ch))
- json_object_boolean_true_add(json_row, "lostAssert");
-
- if (pim_macro_chisin_joins(ch))
- json_object_boolean_true_add(json_row, "joins");
-
- if (pim_macro_chisin_pim_include(ch))
- json_object_boolean_true_add(json_row, "pimInclude");
-
- if (pim_upstream_evaluate_join_desired(pim, up))
- json_object_boolean_true_add(json_row,
- "evaluateJoinDesired");
-
- json_object_object_add(json_group, src_str, json_row);
-
- } else {
- vty_out(vty, "%-16s %-15pPAs %-15pPAs %-10s %-5s %-10s %-11s %-6s\n",
- ch->interface->name, &up->sg.src, &up->sg.grp,
- pim_macro_ch_lost_assert(ch) ? "yes" : "no",
- pim_macro_chisin_joins(ch) ? "yes" : "no",
- pim_macro_chisin_pim_include(ch) ? "yes" : "no",
- PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
- ? "yes"
- : "no",
- pim_upstream_evaluate_join_desired(pim, up) ? "yes"
- : "no");
- }
-}
-
-static void pim_show_channel(struct pim_instance *pim, struct vty *vty,
- bool uj)
+static void pim_show_interface_traffic_single(struct pim_instance *pim,
+ struct vty *vty,
+ const char *ifname, bool uj)
{
- struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
- struct interface *ifp;
-
+ struct interface *ifp = NULL;
+ struct pim_interface *pim_ifp = NULL;
json_object *json = NULL;
+ json_object *json_row = NULL;
+ uint8_t found_ifname = 0;
if (uj)
json = json_object_new_object();
- else
+ else {
+ vty_out(vty, "\n");
+ vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+ "Interface", " HELLO", " JOIN", " PRUNE",
+ " 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");
vty_out(vty,
- "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
+ "-------------------------------------------------------------------------------------------------------------------------------\n");
+ }
- /* scan per-interface (S,G) state */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ if (strcmp(ifname, ifp->name))
+ continue;
+
pim_ifp = ifp->info;
+
if (!pim_ifp)
continue;
+ if (pim_ifp->pim_sock_fd < 0)
+ continue;
- RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
- /* scan all interfaces */
- pim_show_channel_helper(pim, vty, pim_ifp, ch,
- json, uj);
+ found_ifname = 1;
+ if (uj) {
+ json_row = json_object_new_object();
+ json_object_pim_ifp_add(json_row, ifp);
+ json_object_int_add(json_row, "helloRx",
+ pim_ifp->pim_ifstat_hello_recv);
+ json_object_int_add(json_row, "helloTx",
+ pim_ifp->pim_ifstat_hello_sent);
+ json_object_int_add(json_row, "joinRx",
+ pim_ifp->pim_ifstat_join_recv);
+ json_object_int_add(json_row, "joinTx",
+ pim_ifp->pim_ifstat_join_send);
+ json_object_int_add(json_row, "pruneRx",
+ pim_ifp->pim_ifstat_prune_recv);
+ json_object_int_add(json_row, "pruneTx",
+ pim_ifp->pim_ifstat_prune_send);
+ json_object_int_add(json_row, "registerRx",
+ pim_ifp->pim_ifstat_reg_recv);
+ json_object_int_add(json_row, "registerTx",
+ pim_ifp->pim_ifstat_reg_recv);
+ json_object_int_add(json_row, "registerStopRx",
+ pim_ifp->pim_ifstat_reg_stop_recv);
+ json_object_int_add(json_row, "registerStopTx",
+ pim_ifp->pim_ifstat_reg_stop_send);
+ 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);
+ 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 %7" PRIu64 "/%-7" PRIu64 "\n",
+ ifp->name, pim_ifp->pim_ifstat_hello_recv,
+ pim_ifp->pim_ifstat_hello_sent,
+ pim_ifp->pim_ifstat_join_recv,
+ pim_ifp->pim_ifstat_join_send,
+ pim_ifp->pim_ifstat_prune_recv,
+ pim_ifp->pim_ifstat_prune_send,
+ pim_ifp->pim_ifstat_reg_recv,
+ pim_ifp->pim_ifstat_reg_send,
+ 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_bsm_rx,
+ pim_ifp->pim_ifstat_bsm_tx);
}
}
-
if (uj)
vty_json(vty, json);
+ else if (!found_ifname)
+ vty_out(vty, "%% No such interface\n");
}
static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
uptime_mroute_del, (long long)pim->mroute_del_events);
}
-struct pnc_cache_walk_data {
- struct vty *vty;
- struct pim_instance *pim;
-};
-
-static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
-{
- struct pim_nexthop_cache *pnc = bucket->data;
- struct pnc_cache_walk_data *cwd = arg;
- struct vty *vty = cwd->vty;
- struct pim_instance *pim = cwd->pim;
- struct nexthop *nh_node = NULL;
- ifindex_t first_ifindex;
- struct interface *ifp = NULL;
- char buf[PREFIX_STRLEN];
-
- 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, "%-15s ", inet_ntop(AF_INET,
- &pnc->rpf.rpf_addr.u.prefix4,
- buf, sizeof(buf)));
- vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
- vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
- vty_out(vty, "\n");
- }
- return CMD_SUCCESS;
-}
-
-static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
-{
- struct pnc_cache_walk_data cwd;
-
- cwd.vty = vty;
- cwd.pim = pim;
- vty_out(vty, "Number of registered addresses: %lu\n",
- pim->rpf_hash->count);
- vty_out(vty, "Address Interface Nexthop\n");
- vty_out(vty, "---------------------------------------------\n");
-
- 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)
{
return CMD_WARNING;
}
-static void pim_show_jp_agg_helper(struct vty *vty,
- struct interface *ifp,
- struct pim_neighbor *neigh,
- struct pim_upstream *up,
- int is_join)
-{
- char rpf_str[INET_ADDRSTRLEN];
-
- /* pius->address.s_addr */
- pim_inet4_dump("<rpf?>", neigh->source_addr, rpf_str, sizeof(rpf_str));
-
- vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %5s\n", ifp->name, rpf_str,
- &up->sg.src, &up->sg.grp, is_join ? "J" : "P");
-}
-
-static void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
-{
- struct interface *ifp;
- struct pim_interface *pim_ifp;
- struct listnode *n_node;
- struct pim_neighbor *neigh;
- struct listnode *jag_node;
- struct pim_jp_agg_group *jag;
- struct listnode *js_node;
- struct pim_jp_sources *js;
-
- vty_out(vty,
- "Interface RPF Nbr Source Group State\n");
-
- FOR_ALL_INTERFACES (pim->vrf, ifp) {
- pim_ifp = ifp->info;
- if (!pim_ifp)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
- n_node, neigh)) {
- for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
- jag_node, jag)) {
- for (ALL_LIST_ELEMENTS_RO(jag->sources,
- js_node, js)) {
- pim_show_jp_agg_helper(vty,
- ifp, neigh, js->up,
- js->is_join);
- }
- }
- }
- }
-}
-
DEFPY (show_ip_pim_jp_agg,
show_ip_pim_jp_agg_cmd,
"show ip pim [vrf NAME] jp-agg",
return CMD_WARNING_CONFIG_FAILED;
}
-static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
- struct vty *vty, bool uj)
-{
- struct pim_ssm *ssm = pim->ssm_info;
- const char *range_str =
- ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
-
- if (uj) {
- json_object *json;
- json = json_object_new_object();
- json_object_string_add(json, "ssmGroups", range_str);
- vty_json(vty, json);
- } else
- vty_out(vty, "SSM group range : %s\n", range_str);
-}
-
DEFUN (show_ip_pim_ssm_range,
show_ip_pim_ssm_range_cmd,
"show ip pim [vrf NAME] group-type [json]",
#include "vrf.h"
#include "ferr.h"
#include "lib/srcdest_table.h"
+#include "lib/linklist.h"
#include "pimd.h"
#include "pim_vty.h"
#include "lib/northbound_cli.h"
#include "pim_errors.h"
#include "pim_nb.h"
-#include "pim_cmd_common.h"
#include "pim_mroute.h"
#include "pim_cmd.h"
#include "pim6_cmd.h"
#include "pim_zebra.h"
#include "pim_zlookup.h"
#include "pim_iface.h"
-#include "lib/linklist.h"
+#include "pim_macro.h"
#include "pim_neighbor.h"
+#include "pim_nht.h"
+#include "pim_sock.h"
+#include "pim_ssm.h"
/**
* Get current node VRF name.
!pim_addr_cmp(match.src, item.src));
}
+void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
+{
+ struct pim_interface *pim_ifp;
+
+ pim_ifp = ifp->info;
+ json_object_string_add(json, "name", ifp->name);
+ json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
+ json_object_string_addf(json, "address", "%pPA",
+ &pim_ifp->primary_address);
+ json_object_int_add(json, "index", ifp->ifindex);
+
+ if (if_is_multicast(ifp))
+ json_object_boolean_true_add(json, "flagMulticast");
+
+ if (if_is_broadcast(ifp))
+ json_object_boolean_true_add(json, "flagBroadcast");
+
+ if (ifp->flags & IFF_ALLMULTI)
+ json_object_boolean_true_add(json, "flagAllMulticast");
+
+ if (ifp->flags & IFF_PROMISC)
+ json_object_boolean_true_add(json, "flagPromiscuous");
+
+ if (PIM_IF_IS_DELETED(ifp))
+ json_object_boolean_true_add(json, "flagDeleted");
+
+ if (pim_if_lan_delay_enabled(ifp))
+ json_object_boolean_true_add(json, "lanDelayEnabled");
+}
+
+void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
+{
+ vty_out(vty, "Flags\n");
+ vty_out(vty, "-----\n");
+ vty_out(vty, "All Multicast : %s\n",
+ (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
+ vty_out(vty, "Broadcast : %s\n",
+ if_is_broadcast(ifp) ? "yes" : "no");
+ vty_out(vty, "Deleted : %s\n",
+ PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
+ vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
+ vty_out(vty, "Multicast : %s\n",
+ if_is_multicast(ifp) ? "yes" : "no");
+ vty_out(vty, "Promiscuous : %s\n",
+ (ifp->flags & IFF_PROMISC) ? "yes" : "no");
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+}
+
void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
{
json_object_boolean_add(
if (uj)
vty_json(vty, json);
}
+
+static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch, json_object *json,
+ time_t now, bool uj)
+{
+ json_object *json_iface = NULL;
+ json_object *json_row = NULL;
+ json_object *json_grp = NULL;
+ pim_addr ifaddr;
+ char uptime[10];
+ char expire[10];
+ char prune[10];
+ char buf[PREFIX_STRLEN];
+
+ ifaddr = pim_ifp->primary_address;
+
+ pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
+ pim_time_timer_to_mmss(expire, sizeof(expire),
+ ch->t_ifjoin_expiry_timer);
+ pim_time_timer_to_mmss(prune, sizeof(prune),
+ ch->t_ifjoin_prune_pending_timer);
+
+ if (uj) {
+ char ch_grp_str[PIM_ADDRSTRLEN];
+ char ch_src_str[PIM_ADDRSTRLEN];
+
+ snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
+ &ch->sg.grp);
+ snprintfrr(ch_src_str, sizeof(ch_src_str), "%pPAs",
+ &ch->sg.src);
+
+ json_object_object_get_ex(json, ch->interface->name,
+ &json_iface);
+
+ if (!json_iface) {
+ json_iface = json_object_new_object();
+ json_object_pim_ifp_add(json_iface, ch->interface);
+ json_object_object_add(json, ch->interface->name,
+ json_iface);
+ }
+
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "source", ch_src_str);
+ json_object_string_add(json_row, "group", ch_grp_str);
+ json_object_string_add(json_row, "upTime", uptime);
+ json_object_string_add(json_row, "expire", expire);
+ json_object_string_add(json_row, "prune", prune);
+ json_object_string_add(
+ json_row, "channelJoinName",
+ pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
+ if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
+#if CONFDATE > 20230131
+ CPP_NOTICE(
+ "Remove JSON object commands with keys starting with capital")
+#endif
+ json_object_int_add(json_row, "SGRpt", 1);
+ json_object_int_add(json_row, "sgRpt", 1);
+ }
+ if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+ json_object_int_add(json_row, "protocolPim", 1);
+ if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
+ json_object_int_add(json_row, "protocolIgmp", 1);
+ json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
+ if (!json_grp) {
+ json_grp = json_object_new_object();
+ json_object_object_add(json_grp, ch_src_str, json_row);
+ json_object_object_add(json_iface, ch_grp_str,
+ json_grp);
+ } else
+ json_object_object_add(json_grp, ch_src_str, json_row);
+ } else {
+ vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
+ ch->interface->name,
+ inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
+ &ch->sg.src, &ch->sg.grp,
+ pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
+ uptime, expire, prune);
+ }
+}
+
+void pim_show_join(struct pim_instance *pim, struct vty *vty,
+ pim_sgaddr *sg, bool uj)
+{
+ struct pim_interface *pim_ifp;
+ struct pim_ifchannel *ch;
+ struct interface *ifp;
+ time_t now;
+ json_object *json = NULL;
+
+ now = pim_time_monotonic_sec();
+
+ if (uj)
+ json = json_object_new_object();
+ else
+ vty_out(vty,
+ "Interface Address Source Group State Uptime Expire Prune\n");
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+ if (!pim_ifp)
+ continue;
+
+ RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ if (!pim_sgaddr_match(ch->sg, *sg))
+ continue;
+ pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
+ } /* scan interface channels */
+ }
+
+ if (uj)
+ vty_json(vty, json);
+}
+
+static void pim_show_jp_agg_helper(struct vty *vty, struct interface *ifp,
+ struct pim_neighbor *neigh,
+ struct pim_upstream *up, int is_join)
+{
+ char src_str[INET_ADDRSTRLEN];
+ char grp_str[INET_ADDRSTRLEN];
+ char rpf_str[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+ pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+ /* pius->address.s_addr */
+ pim_inet4_dump("<rpf?>", neigh->source_addr, rpf_str, sizeof(rpf_str));
+
+ vty_out(vty, "%-16s %-15s %-15s %-15s %5s\n", ifp->name, rpf_str,
+ src_str, grp_str, is_join ? "J" : "P");
+}
+
+void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
+{
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ struct listnode *n_node;
+ struct pim_neighbor *neigh;
+ struct listnode *jag_node;
+ struct pim_jp_agg_group *jag;
+ struct listnode *js_node;
+ struct pim_jp_sources *js;
+
+ vty_out(vty,
+ "Interface RPF Nbr Source Group State\n");
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+ if (!pim_ifp)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
+ neigh)) {
+ for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
+ jag_node, jag)) {
+ for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
+ js)) {
+ pim_show_jp_agg_helper(vty, ifp, neigh,
+ js->up,
+ js->is_join);
+ }
+ }
+ }
+ }
+}
+
+static void pim_show_membership_helper(struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch,
+ struct json_object *json)
+{
+ char ch_grp_str[PIM_ADDRSTRLEN];
+ json_object *json_iface = NULL;
+ json_object *json_row = NULL;
+
+ json_object_object_get_ex(json, ch->interface->name, &json_iface);
+ if (!json_iface) {
+ json_iface = json_object_new_object();
+ json_object_pim_ifp_add(json_iface, ch->interface);
+ json_object_object_add(json, ch->interface->name, json_iface);
+ }
+
+ snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", &ch->sg.grp);
+
+ json_row = json_object_new_object();
+ json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
+ json_object_string_add(json_row, "group", ch_grp_str);
+ json_object_string_add(json_row, "localMembership",
+ ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
+ ? "NOINFO"
+ : "INCLUDE");
+ json_object_object_add(json_iface, ch_grp_str, json_row);
+}
+
+void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+ struct pim_interface *pim_ifp;
+ struct pim_ifchannel *ch;
+ struct interface *ifp;
+ enum json_type type;
+ json_object *json = NULL;
+ json_object *json_tmp = NULL;
+
+ json = json_object_new_object();
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+ if (!pim_ifp)
+ continue;
+
+ RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ pim_show_membership_helper(vty, pim_ifp, ch, json);
+ } /* scan interface channels */
+ }
+
+ if (uj) {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ } else {
+ vty_out(vty,
+ "Interface Address Source Group Membership\n");
+
+ /*
+ * Example of the json data we are traversing
+ *
+ * {
+ * "swp3":{
+ * "name":"swp3",
+ * "state":"up",
+ * "address":"10.1.20.1",
+ * "index":5,
+ * "flagMulticast":true,
+ * "flagBroadcast":true,
+ * "lanDelayEnabled":true,
+ * "226.10.10.10":{
+ * "source":"*",
+ * "group":"226.10.10.10",
+ * "localMembership":"INCLUDE"
+ * }
+ * }
+ * }
+ */
+
+ /* foreach interface */
+ json_object_object_foreach(json, key, val)
+ {
+
+ /* Find all of the keys where the val is an object. In
+ * the example
+ * above the only one is 226.10.10.10
+ */
+ json_object_object_foreach(val, if_field_key,
+ if_field_val)
+ {
+ type = json_object_get_type(if_field_val);
+
+ if (type == json_type_object) {
+ vty_out(vty, "%-16s ", key);
+
+ json_object_object_get_ex(
+ val, "address", &json_tmp);
+ vty_out(vty, "%-15s ",
+ json_object_get_string(
+ json_tmp));
+
+ json_object_object_get_ex(if_field_val,
+ "source",
+ &json_tmp);
+ vty_out(vty, "%-15s ",
+ json_object_get_string(
+ json_tmp));
+
+ /* Group */
+ vty_out(vty, "%-15s ", if_field_key);
+
+ json_object_object_get_ex(
+ if_field_val, "localMembership",
+ &json_tmp);
+ vty_out(vty, "%-10s\n",
+ json_object_get_string(
+ json_tmp));
+ }
+ }
+ }
+ }
+
+ json_object_free(json);
+}
+
+static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
+ struct pim_interface *pim_ifp,
+ struct pim_ifchannel *ch, json_object *json,
+ bool uj)
+{
+ struct pim_upstream *up = ch->upstream;
+ json_object *json_group = NULL;
+ char src_str[INET_ADDRSTRLEN];
+ char grp_str[INET_ADDRSTRLEN];
+ json_object *json_row = NULL;
+
+ pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+ pim_inet4_dump("<grp?>", up->sg.grp, 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);
+ }
+
+ json_row = json_object_new_object();
+ json_object_pim_upstream_add(json_row, up);
+ json_object_string_add(json_row, "interface",
+ ch->interface->name);
+ json_object_string_add(json_row, "source", src_str);
+ json_object_string_add(json_row, "group", grp_str);
+
+ if (pim_macro_ch_lost_assert(ch))
+ json_object_boolean_true_add(json_row, "lostAssert");
+
+ if (pim_macro_chisin_joins(ch))
+ json_object_boolean_true_add(json_row, "joins");
+
+ if (pim_macro_chisin_pim_include(ch))
+ json_object_boolean_true_add(json_row, "pimInclude");
+
+ if (pim_upstream_evaluate_join_desired(pim, up))
+ json_object_boolean_true_add(json_row,
+ "evaluateJoinDesired");
+
+ json_object_object_add(json_group, src_str, json_row);
+
+ } else {
+ vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
+ ch->interface->name, src_str, grp_str,
+ pim_macro_ch_lost_assert(ch) ? "yes" : "no",
+ pim_macro_chisin_joins(ch) ? "yes" : "no",
+ pim_macro_chisin_pim_include(ch) ? "yes" : "no",
+ PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
+ ? "yes"
+ : "no",
+ pim_upstream_evaluate_join_desired(pim, up) ? "yes"
+ : "no");
+ }
+}
+
+void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+ struct pim_interface *pim_ifp;
+ struct pim_ifchannel *ch;
+ struct interface *ifp;
+
+ json_object *json = NULL;
+
+ if (uj)
+ json = json_object_new_object();
+ else
+ vty_out(vty,
+ "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
+
+ /* scan per-interface (S,G) state */
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+ if (!pim_ifp)
+ continue;
+
+
+ RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
+ /* scan all interfaces */
+ pim_show_channel_helper(pim, vty, pim_ifp, ch, json,
+ uj);
+ }
+ }
+
+ if (uj)
+ vty_json(vty, json);
+}
+
+void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
+ bool uj)
+{
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ struct pim_upstream *up;
+ int fhr = 0;
+ int pim_nbrs = 0;
+ int pim_ifchannels = 0;
+ json_object *json = NULL;
+ json_object *json_row = NULL;
+ json_object *json_tmp;
+
+ json = json_object_new_object();
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ continue;
+
+ if (mlag == true && pim_ifp->activeactive == false)
+ continue;
+
+ pim_nbrs = pim_ifp->pim_neighbor_list->count;
+ pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
+ fhr = 0;
+
+ frr_each (rb_pim_upstream, &pim->upstream_head, up)
+ if (ifp == up->rpf.source_nexthop.interface)
+ if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
+ fhr++;
+
+ json_row = json_object_new_object();
+ json_object_pim_ifp_add(json_row, ifp);
+ json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
+ json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
+ json_object_int_add(json_row, "firstHopRouterCount", fhr);
+ json_object_string_addf(json_row, "pimDesignatedRouter", "%pPAs",
+ &pim_ifp->pim_dr_addr);
+
+ if (pim_addr_cmp(pim_ifp->pim_dr_addr,
+ pim_ifp->primary_address))
+ json_object_boolean_true_add(
+ json_row, "pimDesignatedRouterLocal");
+
+ json_object_object_add(json, ifp->name, json_row);
+ }
+
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ } else {
+ vty_out(vty,
+ "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
+
+ json_object_object_foreach(json, key, val)
+ {
+ vty_out(vty, "%-16s ", key);
+
+ json_object_object_get_ex(val, "state", &json_tmp);
+ vty_out(vty, "%5s ", json_object_get_string(json_tmp));
+
+ json_object_object_get_ex(val, "address", &json_tmp);
+ vty_out(vty, "%15s ",
+ json_object_get_string(json_tmp));
+
+ json_object_object_get_ex(val, "pimNeighbors",
+ &json_tmp);
+ vty_out(vty, "%8d ", json_object_get_int(json_tmp));
+
+ if (json_object_object_get_ex(
+ val, "pimDesignatedRouterLocal",
+ &json_tmp)) {
+ vty_out(vty, "%15s ", "local");
+ } else {
+ json_object_object_get_ex(
+ val, "pimDesignatedRouter", &json_tmp);
+ vty_out(vty, "%15s ",
+ json_object_get_string(json_tmp));
+ }
+
+ json_object_object_get_ex(val, "firstHopRouter",
+ &json_tmp);
+ vty_out(vty, "%3d ", json_object_get_int(json_tmp));
+
+ json_object_object_get_ex(val, "pimIfChannels",
+ &json_tmp);
+ vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
+ }
+ }
+
+ json_object_free(json);
+}
+
+void pim_show_interfaces_single(struct pim_instance *pim,
+ struct vty *vty, const char *ifname,
+ bool mlag, bool uj)
+{
+ pim_addr ifaddr;
+ struct interface *ifp;
+ struct listnode *neighnode;
+ struct pim_interface *pim_ifp;
+ struct pim_neighbor *neigh;
+ struct pim_upstream *up;
+ time_t now;
+ char dr_str[INET_ADDRSTRLEN];
+ char dr_uptime[10];
+ char expire[10];
+ char grp_str[INET_ADDRSTRLEN];
+ char hello_period[10];
+ char hello_timer[10];
+ char neigh_src_str[INET_ADDRSTRLEN];
+ char src_str[INET_ADDRSTRLEN];
+ char stat_uptime[10];
+ char uptime[10];
+ int found_ifname = 0;
+ int print_header;
+ json_object *json = NULL;
+ json_object *json_row = NULL;
+ json_object *json_pim_neighbor = NULL;
+ json_object *json_pim_neighbors = NULL;
+ json_object *json_group = NULL;
+ json_object *json_group_source = NULL;
+ json_object *json_fhr_sources = NULL;
+ struct pim_secondary_addr *sec_addr;
+ struct listnode *sec_node;
+
+ now = pim_time_monotonic_sec();
+
+ if (uj)
+ json = json_object_new_object();
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ continue;
+
+ if (mlag == true && pim_ifp->activeactive == false)
+ continue;
+
+ if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
+ continue;
+
+ found_ifname = 1;
+ ifaddr = pim_ifp->primary_address;
+ pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str,
+ sizeof(dr_str));
+ pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
+ pim_ifp->pim_dr_election_last);
+ pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
+ pim_ifp->t_pim_hello_timer);
+ pim_time_mmss(hello_period, sizeof(hello_period),
+ pim_ifp->pim_hello_period);
+ pim_time_uptime(stat_uptime, sizeof(stat_uptime),
+ now - pim_ifp->pim_ifstat_start);
+
+ if (uj) {
+ char pbuf[PREFIX2STR_BUFFER];
+
+ json_row = json_object_new_object();
+ json_object_pim_ifp_add(json_row, ifp);
+
+ if (pim_ifp->update_source.s_addr != INADDR_ANY) {
+ json_object_string_addf(
+ json_row, "useSource", "%pI4",
+ &pim_ifp->update_source);
+ }
+ if (pim_ifp->sec_addr_list) {
+ json_object *sec_list = NULL;
+
+ sec_list = json_object_new_array();
+ for (ALL_LIST_ELEMENTS_RO(
+ pim_ifp->sec_addr_list, sec_node,
+ sec_addr)) {
+ json_object_array_add(
+ sec_list,
+ json_object_new_string(
+ prefix2str(
+ &sec_addr->addr,
+ pbuf,
+ sizeof(pbuf))));
+ }
+ json_object_object_add(json_row,
+ "secondaryAddressList",
+ sec_list);
+ }
+
+ /* PIM neighbors */
+ if (pim_ifp->pim_neighbor_list->count) {
+ json_pim_neighbors = json_object_new_object();
+
+ for (ALL_LIST_ELEMENTS_RO(
+ pim_ifp->pim_neighbor_list,
+ neighnode, neigh)) {
+ json_pim_neighbor =
+ json_object_new_object();
+ pim_inet4_dump("<src?>",
+ neigh->source_addr,
+ neigh_src_str,
+ sizeof(neigh_src_str));
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - neigh->creation);
+ pim_time_timer_to_hhmmss(
+ expire, sizeof(expire),
+ neigh->t_expire_timer);
+
+ json_object_string_add(
+ json_pim_neighbor, "address",
+ neigh_src_str);
+ json_object_string_add(
+ json_pim_neighbor, "upTime",
+ uptime);
+ json_object_string_add(
+ json_pim_neighbor, "holdtime",
+ expire);
+
+ json_object_object_add(
+ json_pim_neighbors,
+ neigh_src_str,
+ json_pim_neighbor);
+ }
+
+ json_object_object_add(json_row, "neighbors",
+ json_pim_neighbors);
+ }
+
+ json_object_string_add(json_row, "drAddress", dr_str);
+ json_object_int_add(json_row, "drPriority",
+ pim_ifp->pim_dr_priority);
+ json_object_string_add(json_row, "drUptime", dr_uptime);
+ json_object_int_add(json_row, "drElections",
+ pim_ifp->pim_dr_election_count);
+ json_object_int_add(json_row, "drChanges",
+ pim_ifp->pim_dr_election_changes);
+
+ /* FHR */
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (ifp != up->rpf.source_nexthop.interface)
+ continue;
+
+ if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
+ continue;
+
+ if (!json_fhr_sources)
+ json_fhr_sources =
+ json_object_new_object();
+
+ snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
+ &up->sg.grp);
+ snprintfrr(src_str, sizeof(src_str), "%pPAs",
+ &up->sg.src);
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - up->state_transition);
+
+ /*
+ * Does this group live in json_fhr_sources?
+ * If not create it.
+ */
+ json_object_object_get_ex(json_fhr_sources,
+ grp_str, &json_group);
+
+ if (!json_group) {
+ json_group = json_object_new_object();
+ json_object_object_add(json_fhr_sources,
+ grp_str,
+ json_group);
+ }
+
+ json_group_source = json_object_new_object();
+ json_object_string_add(json_group_source,
+ "source", src_str);
+ json_object_string_add(json_group_source,
+ "group", grp_str);
+ json_object_string_add(json_group_source,
+ "upTime", uptime);
+ json_object_object_add(json_group, src_str,
+ json_group_source);
+ }
+
+ if (json_fhr_sources) {
+ json_object_object_add(json_row,
+ "firstHopRouter",
+ json_fhr_sources);
+ }
+
+ json_object_int_add(json_row, "helloPeriod",
+ pim_ifp->pim_hello_period);
+ json_object_int_add(json_row, "holdTime",
+ PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
+ json_object_string_add(json_row, "helloTimer",
+ hello_timer);
+ json_object_string_add(json_row, "helloStatStart",
+ stat_uptime);
+ json_object_int_add(json_row, "helloReceived",
+ pim_ifp->pim_ifstat_hello_recv);
+ json_object_int_add(json_row, "helloReceivedFailed",
+ pim_ifp->pim_ifstat_hello_recvfail);
+ json_object_int_add(json_row, "helloSend",
+ pim_ifp->pim_ifstat_hello_sent);
+ json_object_int_add(json_row, "hellosendFailed",
+ pim_ifp->pim_ifstat_hello_sendfail);
+ json_object_int_add(json_row, "helloGenerationId",
+ pim_ifp->pim_generation_id);
+
+ json_object_int_add(
+ json_row, "effectivePropagationDelay",
+ pim_if_effective_propagation_delay_msec(ifp));
+ json_object_int_add(
+ json_row, "effectiveOverrideInterval",
+ pim_if_effective_override_interval_msec(ifp));
+ json_object_int_add(
+ json_row, "joinPruneOverrideInterval",
+ pim_if_jp_override_interval_msec(ifp));
+
+ json_object_int_add(
+ json_row, "propagationDelay",
+ pim_ifp->pim_propagation_delay_msec);
+ json_object_int_add(
+ json_row, "propagationDelayHighest",
+ pim_ifp->pim_neighbors_highest_propagation_delay_msec);
+ json_object_int_add(
+ json_row, "overrideInterval",
+ pim_ifp->pim_override_interval_msec);
+ json_object_int_add(
+ json_row, "overrideIntervalHighest",
+ pim_ifp->pim_neighbors_highest_override_interval_msec);
+ if (pim_ifp->bsm_enable)
+ json_object_boolean_true_add(json_row,
+ "bsmEnabled");
+ if (pim_ifp->ucast_bsm_accept)
+ json_object_boolean_true_add(json_row,
+ "ucastBsmEnabled");
+ json_object_object_add(json, ifp->name, json_row);
+
+ } else {
+ vty_out(vty, "Interface : %s\n", ifp->name);
+ vty_out(vty, "State : %s\n",
+ if_is_up(ifp) ? "up" : "down");
+ if (pim_ifp->update_source.s_addr != INADDR_ANY) {
+ vty_out(vty, "Use Source : %pI4\n",
+ &pim_ifp->update_source);
+ }
+ if (pim_ifp->sec_addr_list) {
+ vty_out(vty, "Address : %pI4 (primary)\n",
+ &ifaddr);
+ for (ALL_LIST_ELEMENTS_RO(
+ pim_ifp->sec_addr_list, sec_node,
+ sec_addr))
+ vty_out(vty, " %pFX\n",
+ &sec_addr->addr);
+ } else {
+ vty_out(vty, "Address : %pI4\n",
+ &ifaddr);
+ }
+ vty_out(vty, "\n");
+
+ /* PIM neighbors */
+ print_header = 1;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
+ neighnode, neigh)) {
+
+ if (print_header) {
+ vty_out(vty, "PIM Neighbors\n");
+ vty_out(vty, "-------------\n");
+ print_header = 0;
+ }
+
+ pim_inet4_dump("<src?>", neigh->source_addr,
+ neigh_src_str,
+ sizeof(neigh_src_str));
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - neigh->creation);
+ pim_time_timer_to_hhmmss(expire, sizeof(expire),
+ neigh->t_expire_timer);
+ vty_out(vty,
+ "%-15s : up for %s, holdtime expires in %s\n",
+ neigh_src_str, uptime, expire);
+ }
+
+ if (!print_header) {
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+ }
+
+ vty_out(vty, "Designated Router\n");
+ vty_out(vty, "-----------------\n");
+ vty_out(vty, "Address : %s\n", dr_str);
+ vty_out(vty, "Priority : %u(%d)\n",
+ pim_ifp->pim_dr_priority,
+ pim_ifp->pim_dr_num_nondrpri_neighbors);
+ vty_out(vty, "Uptime : %s\n", dr_uptime);
+ vty_out(vty, "Elections : %d\n",
+ pim_ifp->pim_dr_election_count);
+ vty_out(vty, "Changes : %d\n",
+ pim_ifp->pim_dr_election_changes);
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+
+ /* FHR */
+ print_header = 1;
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (!up->rpf.source_nexthop.interface)
+ continue;
+
+ if (strcmp(ifp->name,
+ up->rpf.source_nexthop
+ .interface->name) != 0)
+ continue;
+
+ if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
+ continue;
+
+ if (print_header) {
+ vty_out(vty,
+ "FHR - First Hop Router\n");
+ vty_out(vty,
+ "----------------------\n");
+ print_header = 0;
+ }
+
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - up->state_transition);
+ vty_out(vty,
+ "%pPAs : %pPAs is a source, uptime is %s\n",
+ &up->sg.grp, &up->sg.src, uptime);
+ }
+
+ if (!print_header) {
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+ }
+
+ vty_out(vty, "Hellos\n");
+ vty_out(vty, "------\n");
+ vty_out(vty, "Period : %d\n",
+ pim_ifp->pim_hello_period);
+ vty_out(vty, "HoldTime : %d\n",
+ PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
+ vty_out(vty, "Timer : %s\n", hello_timer);
+ vty_out(vty, "StatStart : %s\n", stat_uptime);
+ vty_out(vty, "Receive : %d\n",
+ pim_ifp->pim_ifstat_hello_recv);
+ vty_out(vty, "Receive Failed : %d\n",
+ pim_ifp->pim_ifstat_hello_recvfail);
+ vty_out(vty, "Send : %d\n",
+ pim_ifp->pim_ifstat_hello_sent);
+ vty_out(vty, "Send Failed : %d\n",
+ pim_ifp->pim_ifstat_hello_sendfail);
+ vty_out(vty, "Generation ID : %08x\n",
+ pim_ifp->pim_generation_id);
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+
+ pim_print_ifp_flags(vty, ifp);
+
+ vty_out(vty, "Join Prune Interval\n");
+ vty_out(vty, "-------------------\n");
+ vty_out(vty, "LAN Delay : %s\n",
+ pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
+ vty_out(vty, "Effective Propagation Delay : %d msec\n",
+ pim_if_effective_propagation_delay_msec(ifp));
+ vty_out(vty, "Effective Override Interval : %d msec\n",
+ pim_if_effective_override_interval_msec(ifp));
+ vty_out(vty, "Join Prune Override Interval : %d msec\n",
+ pim_if_jp_override_interval_msec(ifp));
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+
+ vty_out(vty, "LAN Prune Delay\n");
+ vty_out(vty, "---------------\n");
+ vty_out(vty, "Propagation Delay : %d msec\n",
+ pim_ifp->pim_propagation_delay_msec);
+ vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
+ pim_ifp->pim_neighbors_highest_propagation_delay_msec);
+ vty_out(vty, "Override Interval : %d msec\n",
+ pim_ifp->pim_override_interval_msec);
+ vty_out(vty, "Override Interval (Highest) : %d msec\n",
+ pim_ifp->pim_neighbors_highest_override_interval_msec);
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+
+ vty_out(vty, "BSM Status\n");
+ vty_out(vty, "----------\n");
+ vty_out(vty, "Bsm Enabled : %s\n",
+ pim_ifp->bsm_enable ? "yes" : "no");
+ vty_out(vty, "Unicast Bsm Enabled : %s\n",
+ pim_ifp->ucast_bsm_accept ? "yes" : "no");
+ vty_out(vty, "\n");
+ vty_out(vty, "\n");
+ }
+ }
+
+ if (uj)
+ vty_json(vty, json);
+ else if (!found_ifname)
+ vty_out(vty, "%% No such interface\n");
+}
+
+void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
+ bool uj)
+{
+ struct pim_ssm *ssm = pim->ssm_info;
+ const char *range_str =
+ ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
+
+ if (uj) {
+ json_object *json;
+
+ json = json_object_new_object();
+ json_object_string_add(json, "ssmGroups", range_str);
+ vty_json(vty, json);
+ } else
+ vty_out(vty, "SSM group range : %s\n", range_str);
+}
+
+struct pnc_cache_walk_data {
+ struct vty *vty;
+ struct pim_instance *pim;
+};
+
+static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
+{
+ struct pim_nexthop_cache *pnc = bucket->data;
+ struct pnc_cache_walk_data *cwd = arg;
+ struct vty *vty = cwd->vty;
+ struct pim_instance *pim = cwd->pim;
+ struct nexthop *nh_node = NULL;
+ ifindex_t first_ifindex;
+ struct interface *ifp = NULL;
+ char buf[PREFIX_STRLEN];
+
+ 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, "%-15s ",
+ inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, buf,
+ sizeof(buf)));
+ vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
+ vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
+ vty_out(vty, "\n");
+ }
+ return CMD_SUCCESS;
+}
+
+void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
+{
+ struct pnc_cache_walk_data cwd;
+
+ cwd.vty = vty;
+ cwd.pim = pim;
+ vty_out(vty, "Number of registered addresses: %lu\n",
+ pim->rpf_hash->count);
+ vty_out(vty, "Address Interface Nexthop\n");
+ vty_out(vty, "---------------------------------------------\n");
+
+ hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
+}
+
+void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
+ const char *neighbor, json_object *json)
+{
+ struct listnode *neighnode;
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ struct pim_neighbor *neigh;
+ time_t now;
+ int found_neighbor = 0;
+ int option_address_list;
+ int option_dr_priority;
+ int option_generation_id;
+ int option_holdtime;
+ int option_lan_prune_delay;
+ int option_t_bit;
+ char uptime[10];
+ char expire[10];
+ char neigh_src_str[PIM_ADDRSTRLEN];
+
+ json_object *json_ifp = NULL;
+ json_object *json_row = NULL;
+
+ now = pim_time_monotonic_sec();
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ continue;
+
+ if (pim_ifp->pim_sock_fd < 0)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
+ neigh)) {
+ snprintfrr(neigh_src_str, sizeof(neigh_src_str),
+ "%pPAs", &neigh->source_addr);
+
+ /*
+ * The user can specify either the interface name or the
+ * PIM neighbor IP.
+ * If this pim_ifp matches neither then skip.
+ */
+ if (strcmp(neighbor, "detail") &&
+ strcmp(neighbor, ifp->name) &&
+ strcmp(neighbor, neigh_src_str))
+ continue;
+
+ found_neighbor = 1;
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - neigh->creation);
+ pim_time_timer_to_hhmmss(expire, sizeof(expire),
+ neigh->t_expire_timer);
+
+ option_address_list = 0;
+ option_dr_priority = 0;
+ option_generation_id = 0;
+ option_holdtime = 0;
+ option_lan_prune_delay = 0;
+ option_t_bit = 0;
+
+ if (PIM_OPTION_IS_SET(neigh->hello_options,
+ PIM_OPTION_MASK_ADDRESS_LIST))
+ option_address_list = 1;
+
+ if (PIM_OPTION_IS_SET(neigh->hello_options,
+ PIM_OPTION_MASK_DR_PRIORITY))
+ option_dr_priority = 1;
+
+ if (PIM_OPTION_IS_SET(neigh->hello_options,
+ PIM_OPTION_MASK_GENERATION_ID))
+ option_generation_id = 1;
+
+ if (PIM_OPTION_IS_SET(neigh->hello_options,
+ PIM_OPTION_MASK_HOLDTIME))
+ option_holdtime = 1;
+
+ if (PIM_OPTION_IS_SET(neigh->hello_options,
+ PIM_OPTION_MASK_LAN_PRUNE_DELAY))
+ option_lan_prune_delay = 1;
+
+ if (PIM_OPTION_IS_SET(
+ neigh->hello_options,
+ PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
+ option_t_bit = 1;
+
+ if (json) {
+
+ /* Does this ifp live in json? If not create it
+ */
+ json_object_object_get_ex(json, ifp->name,
+ &json_ifp);
+
+ if (!json_ifp) {
+ json_ifp = json_object_new_object();
+ json_object_pim_ifp_add(json_ifp, ifp);
+ json_object_object_add(json, ifp->name,
+ json_ifp);
+ }
+
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "interface",
+ ifp->name);
+ json_object_string_add(json_row, "address",
+ neigh_src_str);
+ json_object_string_add(json_row, "upTime",
+ uptime);
+ json_object_string_add(json_row, "holdtime",
+ expire);
+ json_object_int_add(json_row, "drPriority",
+ neigh->dr_priority);
+ json_object_int_add(json_row, "generationId",
+ neigh->generation_id);
+
+ if (option_address_list)
+ json_object_boolean_true_add(
+ json_row,
+ "helloOptionAddressList");
+
+ if (option_dr_priority)
+ json_object_boolean_true_add(
+ json_row,
+ "helloOptionDrPriority");
+
+ if (option_generation_id)
+ json_object_boolean_true_add(
+ json_row,
+ "helloOptionGenerationId");
+
+ if (option_holdtime)
+ json_object_boolean_true_add(
+ json_row,
+ "helloOptionHoldtime");
+
+ if (option_lan_prune_delay)
+ json_object_boolean_true_add(
+ json_row,
+ "helloOptionLanPruneDelay");
+
+ if (option_t_bit)
+ json_object_boolean_true_add(
+ json_row, "helloOptionTBit");
+
+ json_object_object_add(json_ifp, neigh_src_str,
+ json_row);
+
+ } else {
+ vty_out(vty, "Interface : %s\n", ifp->name);
+ vty_out(vty, "Neighbor : %s\n", neigh_src_str);
+ vty_out(vty,
+ " Uptime : %s\n",
+ uptime);
+ vty_out(vty,
+ " Holdtime : %s\n",
+ expire);
+ vty_out(vty,
+ " DR Priority : %d\n",
+ neigh->dr_priority);
+ vty_out(vty,
+ " Generation ID : %08x\n",
+ neigh->generation_id);
+ vty_out(vty,
+ " Override Interval (msec) : %d\n",
+ neigh->override_interval_msec);
+ vty_out(vty,
+ " Propagation Delay (msec) : %d\n",
+ neigh->propagation_delay_msec);
+ vty_out(vty,
+ " Hello Option - Address List : %s\n",
+ option_address_list ? "yes" : "no");
+ vty_out(vty,
+ " Hello Option - DR Priority : %s\n",
+ option_dr_priority ? "yes" : "no");
+ vty_out(vty,
+ " Hello Option - Generation ID : %s\n",
+ option_generation_id ? "yes" : "no");
+ vty_out(vty,
+ " Hello Option - Holdtime : %s\n",
+ option_holdtime ? "yes" : "no");
+ vty_out(vty,
+ " Hello Option - LAN Prune Delay : %s\n",
+ option_lan_prune_delay ? "yes" : "no");
+ vty_out(vty,
+ " Hello Option - T-bit : %s\n",
+ option_t_bit ? "yes" : "no");
+ bfd_sess_show(vty, json_ifp,
+ neigh->bfd_session);
+ vty_out(vty, "\n");
+ }
+ }
+ }
+
+ if (!found_neighbor)
+ vty_out(vty, "%% No such interface or neighbor\n");
+}
+
+void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, bool uj)
+{
+ struct listnode *neighnode;
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ struct pim_neighbor *neigh;
+ time_t now;
+ char uptime[10];
+ char expire[10];
+ char neigh_src_str[INET_ADDRSTRLEN];
+ json_object *json = NULL;
+ json_object *json_ifp_rows = NULL;
+ json_object *json_row = NULL;
+
+ now = pim_time_monotonic_sec();
+
+ if (uj) {
+ json = json_object_new_object();
+ } else {
+ vty_out(vty,
+ "Interface Neighbor Uptime Holdtime DR Pri\n");
+ }
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ continue;
+
+ if (pim_ifp->pim_sock_fd < 0)
+ continue;
+
+ if (uj)
+ json_ifp_rows = json_object_new_object();
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
+ neigh)) {
+ pim_inet4_dump("<src?>", neigh->source_addr,
+ neigh_src_str, sizeof(neigh_src_str));
+ pim_time_uptime(uptime, sizeof(uptime),
+ now - neigh->creation);
+ pim_time_timer_to_hhmmss(expire, sizeof(expire),
+ neigh->t_expire_timer);
+
+ if (uj) {
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "interface",
+ ifp->name);
+ json_object_string_add(json_row, "neighbor",
+ neigh_src_str);
+ json_object_string_add(json_row, "upTime",
+ uptime);
+ json_object_string_add(json_row, "holdTime",
+ expire);
+ json_object_int_add(json_row, "holdTimeMax",
+ neigh->holdtime);
+ json_object_int_add(json_row, "drPriority",
+ neigh->dr_priority);
+ json_object_object_add(json_ifp_rows,
+ neigh_src_str, json_row);
+
+ } else {
+ vty_out(vty, "%-16s %15s %8s %8s %6d\n",
+ ifp->name, neigh_src_str, uptime,
+ expire, neigh->dr_priority);
+ }
+ }
+
+ if (uj) {
+ json_object_object_add(json, ifp->name, json_ifp_rows);
+ json_ifp_rows = NULL;
+ }
+ }
+
+ if (uj)
+ vty_json(vty, json);
+}