]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Option to get IGMP groups and sources for a particular interface 13183/head
authorPooja Jagadeesh Doijode <pdoijode@nvidia.com>
Mon, 10 Apr 2023 21:34:35 +0000 (14:34 -0700)
committerPooja Jagadeesh Doijode <pdoijode@nvidia.com>
Tue, 11 Apr 2023 18:00:39 +0000 (11:00 -0700)
1. Added interface name, group address and detail option to existing
   "show ip igmp groups" so that user can retrieve all the groups
   or a particular group for an interface. Detail option shows the source
   information for the group. With that, the show command
   looks like:

   "show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail$detail] [json$json]"

2. Changed pim_cmd_lookup_vrf() to return empty JSON if VRF is not present

3. Changed "detail" option to print non pretty JSON

4. Added interface name and group address to existing
   "show ip igmp sources" so that user can retrieve all the sources for
   all the groups or, all the sorces for a particular group for an
   interface. With that, the show command looks like:

   "show ip igmp [vrf NAME$vrf_name] sourcess [INTERFACE$ifname [GROUP$grp_str]] [json$json]"

Signed-off-by: Pooja Jagadeesh Doijode <pdoijode@nvidia.com>
doc/user/pim.rst
pimd/pim_cmd.c
pimd/pim_cmd.h
tests/topotests/multicast_pim_sm_topo3/igmp_group_all_detail.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_brief.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_detail.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_brief.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_detail.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_group_all.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_single_group.json [new file with mode: 0644]
tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py

index 72471d7af0e23ac11270ebf1e29a3258c03f37ca..d70c3c0e64e9bc8c6c19235e5d10a0a893d4bb74 100644 (file)
@@ -387,9 +387,14 @@ cause great confusion.
 .. clicmd:: show ip igmp [vrf NAME] join [json]
 
    Display IGMP static join information for a specific vrf.
-   If "vrf all" is provided, it displays information for all the vrfs present.
+   
+.. index:: show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail] [json$json]
+.. clicmd:: show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail] [json$json]
 
-.. clicmd:: show ip igmp groups
+   Display IGMP static join information for all the vrfs present.
+
+.. index:: show ip igmp vrf all groups [GROUP$grp_str] [detail$detail] [json$json]
+.. clicmd:: show ip igmp vrf all groups [GROUP$grp_str] [detail$detail] [json$json]
 
    Display IGMP groups information.
 
index 8c75b0a5b59def844a3eeb07a9185c7bd95e312a..2e90cf9053379c341c90374908fbdb3705c55c50 100644 (file)
@@ -67,7 +67,7 @@ static struct cmd_node debug_node = {
 };
 
 static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[],
-                                     const int argc, int *idx)
+                                     const int argc, int *idx, bool uj)
 {
        struct vrf *vrf;
 
@@ -76,9 +76,13 @@ static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[],
        else
                vrf = vrf_lookup_by_id(VRF_DEFAULT);
 
-       if (!vrf)
-               vty_out(vty, "Specified VRF: %s does not exist\n",
-                       argv[*idx]->arg);
+       if (!vrf) {
+               if (uj)
+                       vty_json_empty(vty);
+               else
+                       vty_out(vty, "Specified VRF: %s does not exist\n",
+                               argv[*idx]->arg);
+       }
 
        return vrf;
 }
@@ -822,19 +826,172 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
        }
 }
 
-static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
+static void igmp_source_json_helper(struct gm_source *src,
+                                   json_object *json_sources, char *source_str,
+                                   char *mmss, char *uptime)
+{
+       json_object *json_source = NULL;
+
+       json_source = json_object_new_object();
+       if (!json_source)
+               return;
+
+       json_object_string_add(json_source, "source", source_str);
+       json_object_string_add(json_source, "timer", mmss);
+       json_object_boolean_add(json_source, "forwarded",
+                               IGMP_SOURCE_TEST_FORWARDING(src->source_flags));
+       json_object_string_add(json_source, "uptime", uptime);
+       json_object_array_add(json_sources, json_source);
+}
+
+static void igmp_group_print(struct interface *ifp, struct vty *vty, bool uj,
+                            json_object *json, struct gm_group *grp,
+                            time_t now, bool detail)
 {
-       struct interface *ifp;
-       time_t now;
-       json_object *json = NULL;
        json_object *json_iface = NULL;
        json_object *json_group = NULL;
        json_object *json_groups = NULL;
+       char group_str[INET_ADDRSTRLEN];
+       char hhmmss[PIM_TIME_STRLEN];
+       char uptime[PIM_TIME_STRLEN];
+
+       pim_inet4_dump("<group?>", grp->group_addr, group_str,
+                      sizeof(group_str));
+       pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer);
+       pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation);
+
+       if (uj) {
+               json_object_object_get_ex(json, ifp->name, &json_iface);
+               if (!json_iface) {
+                       json_iface = json_object_new_object();
+                       if (!json_iface)
+                               return;
+                       json_object_pim_ifp_add(json_iface, ifp);
+                       json_object_object_add(json, ifp->name, json_iface);
+                       json_groups = json_object_new_array();
+                       if (!json_groups)
+                               return;
+                       json_object_object_add(json_iface, "groups",
+                                              json_groups);
+               }
+
+               json_object_object_get_ex(json_iface, "groups", &json_groups);
+               if (json_groups) {
+                       json_group = json_object_new_object();
+                       if (!json_group)
+                               return;
+
+                       json_object_string_add(json_group, "group", group_str);
+                       if (grp->igmp_version == IGMP_DEFAULT_VERSION)
+                               json_object_string_add(
+                                       json_group, "mode",
+                                       grp->group_filtermode_isexcl
+                                               ? "EXCLUDE"
+                                               : "INCLUDE");
+
+                       json_object_string_add(json_group, "timer", hhmmss);
+                       json_object_int_add(
+                               json_group, "sourcesCount",
+                               grp->group_source_list
+                                       ? listcount(grp->group_source_list)
+                                       : 0);
+                       json_object_int_add(json_group, "version",
+                                           grp->igmp_version);
+                       json_object_string_add(json_group, "uptime", uptime);
+                       json_object_array_add(json_groups, json_group);
+
+                       if (detail) {
+                               struct listnode *srcnode;
+                               struct gm_source *src;
+                               json_object *json_sources = NULL;
+
+                               json_sources = json_object_new_array();
+                               if (!json_sources)
+                                       return;
+
+                               json_object_object_add(json_group, "sources",
+                                                      json_sources);
+
+                               for (ALL_LIST_ELEMENTS_RO(
+                                            grp->group_source_list, srcnode,
+                                            src)) {
+                                       char source_str[INET_ADDRSTRLEN];
+                                       char mmss[PIM_TIME_STRLEN];
+                                       char src_uptime[PIM_TIME_STRLEN];
+
+                                       pim_inet4_dump(
+                                               "<source?>", src->source_addr,
+                                               source_str, sizeof(source_str));
+                                       pim_time_timer_to_mmss(
+                                               mmss, sizeof(mmss),
+                                               src->t_source_timer);
+                                       pim_time_uptime(
+                                               src_uptime, sizeof(src_uptime),
+                                               now - src->source_creation);
+
+                                       igmp_source_json_helper(
+                                               src, json_sources, source_str,
+                                               mmss, src_uptime);
+                               }
+                       }
+               }
+       } else {
+               if (detail) {
+                       struct listnode *srcnode;
+                       struct gm_source *src;
+
+                       for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
+                                                 srcnode, src)) {
+                               char source_str[INET_ADDRSTRLEN];
+
+                               pim_inet4_dump("<source?>", src->source_addr,
+                                              source_str, sizeof(source_str));
+
+                               vty_out(vty,
+                                       "%-16s %-15s %4s %8s %-15s %d %8s\n",
+                                       ifp->name, group_str,
+                                       grp->igmp_version == 3
+                                               ? (grp->group_filtermode_isexcl
+                                                          ? "EXCL"
+                                                          : "INCL")
+                                               : "----",
+                                       hhmmss, source_str, grp->igmp_version,
+                                       uptime);
+                       }
+                       return;
+               }
+
+               vty_out(vty, "%-16s %-15s %4s %8s %4d %d %8s\n", ifp->name,
+                       group_str,
+                       grp->igmp_version == 3
+                               ? (grp->group_filtermode_isexcl ? "EXCL"
+                                                               : "INCL")
+                               : "----",
+                       hhmmss,
+                       grp->group_source_list
+                               ? listcount(grp->group_source_list)
+                               : 0,
+                       grp->igmp_version, uptime);
+       }
+}
+
+static void igmp_show_groups_interface_single(struct pim_instance *pim,
+                                             struct vty *vty, bool uj,
+                                             const char *ifname,
+                                             const char *grp_str, bool detail)
+{
+       struct interface *ifp;
+       time_t now;
+       json_object *json = NULL;
+       struct pim_interface *pim_ifp = NULL;
+       struct gm_group *grp;
 
        now = pim_time_monotonic_sec();
 
        if (uj) {
                json = json_object_new_object();
+               if (!json)
+                       return;
                json_object_int_add(json, "totalGroups", pim->gm_group_count);
                json_object_int_add(json, "watermarkLimit",
                                    pim->gm_watermark_limit);
@@ -843,8 +1000,87 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
                vty_out(vty, "Watermark warn limit(%s): %u\n",
                        pim->gm_watermark_limit ? "Set" : "Not Set",
                        pim->gm_watermark_limit);
-               vty_out(vty,
-                       "Interface        Group           Mode Timer    Srcs V Uptime  \n");
+
+               if (!detail)
+                       vty_out(vty,
+                               "Interface        Group           Mode Timer    Srcs V Uptime\n");
+               else
+                       vty_out(vty,
+                               "Interface        Group           Mode Timer    Source          V Uptime\n");
+       }
+
+       ifp = if_lookup_by_name(ifname, pim->vrf->vrf_id);
+       if (!ifp) {
+               if (uj)
+                       vty_json(vty, json);
+               return;
+       }
+
+       pim_ifp = ifp->info;
+       if (!pim_ifp) {
+               if (uj)
+                       vty_json(vty, json);
+               return;
+       }
+
+       if (grp_str) {
+               struct in_addr group_addr;
+               struct gm_sock *igmp;
+
+               if (inet_pton(AF_INET, grp_str, &group_addr) == 1) {
+                       igmp = pim_igmp_sock_lookup_ifaddr(
+                               pim_ifp->gm_socket_list,
+                               pim_ifp->primary_address);
+                       if (igmp) {
+                               grp = find_group_by_addr(igmp, group_addr);
+                               if (grp)
+                                       igmp_group_print(ifp, vty, uj, json,
+                                                        grp, now, detail);
+                       }
+               }
+       } else {
+               struct listnode *grpnode;
+
+               /* scan igmp groups */
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, grp))
+                       igmp_group_print(ifp, vty, uj, json, grp, now, detail);
+       }
+
+       if (uj) {
+               if (detail)
+                       vty_json_no_pretty(vty, json);
+               else
+                       vty_json(vty, json);
+       }
+}
+
+static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj,
+                            const char *grp_str, bool detail)
+{
+       struct interface *ifp;
+       time_t now;
+       json_object *json = NULL;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj) {
+               json = json_object_new_object();
+               if (!json)
+                       return;
+               json_object_int_add(json, "totalGroups", pim->gm_group_count);
+               json_object_int_add(json, "watermarkLimit",
+                                   pim->gm_watermark_limit);
+       } else {
+               vty_out(vty, "Total IGMP groups: %u\n", pim->gm_group_count);
+               vty_out(vty, "Watermark warn limit(%s): %u\n",
+                       pim->gm_watermark_limit ? "Set" : "Not Set",
+                       pim->gm_watermark_limit);
+               if (!detail)
+                       vty_out(vty,
+                               "Interface        Group           Mode Timer    Srcs V Uptime\n");
+               else
+                       vty_out(vty,
+                               "Interface        Group           Mode Timer    Source          V Uptime\n");
        }
 
        /* scan interfaces */
@@ -856,78 +1092,38 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
                if (!pim_ifp)
                        continue;
 
-               /* scan igmp groups */
-               for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode,
-                                         grp)) {
-                       char group_str[INET_ADDRSTRLEN];
-                       char hhmmss[10];
-                       char uptime[10];
-
-                       pim_inet4_dump("<group?>", grp->group_addr, group_str,
-                                      sizeof(group_str));
-                       pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss),
-                                                grp->t_group_timer);
-                       pim_time_uptime(uptime, sizeof(uptime),
-                                       now - grp->group_creation);
-
-                       if (uj) {
-                               json_object_object_get_ex(json, ifp->name,
-                                                         &json_iface);
-
-                               if (!json_iface) {
-                                       json_iface = json_object_new_object();
-                                       json_object_pim_ifp_add(json_iface,
-                                                               ifp);
-                                       json_object_object_add(json, ifp->name,
-                                                              json_iface);
-                                       json_groups = json_object_new_array();
-                                       json_object_object_add(json_iface,
-                                                              "groups",
-                                                              json_groups);
+               if (grp_str) {
+                       struct in_addr group_addr;
+                       struct gm_sock *igmp;
+
+                       if (inet_pton(AF_INET, grp_str, &group_addr) == 1) {
+                               igmp = pim_igmp_sock_lookup_ifaddr(
+                                       pim_ifp->gm_socket_list,
+                                       pim_ifp->primary_address);
+                               if (igmp) {
+                                       grp = find_group_by_addr(igmp,
+                                                                group_addr);
+                                       if (grp)
+                                               igmp_group_print(ifp, vty, uj,
+                                                                json, grp, now,
+                                                                detail);
                                }
-
-                               json_group = json_object_new_object();
-                               json_object_string_add(json_group, "group",
-                                                      group_str);
-
-                               if (grp->igmp_version == 3)
-                                       json_object_string_add(
-                                               json_group, "mode",
-                                               grp->group_filtermode_isexcl
-                                                       ? "EXCLUDE"
-                                                       : "INCLUDE");
-
-                               json_object_string_add(json_group, "timer",
-                                                      hhmmss);
-                               json_object_int_add(
-                                       json_group, "sourcesCount",
-                                       grp->group_source_list ? listcount(
-                                               grp->group_source_list)
-                                                              : 0);
-                               json_object_int_add(json_group, "version",
-                                                   grp->igmp_version);
-                               json_object_string_add(json_group, "uptime",
-                                                      uptime);
-                               json_object_array_add(json_groups, json_group);
-                       } else {
-                               vty_out(vty, "%-16s %-15s %4s %8s %4d %d %8s\n",
-                                       ifp->name, group_str,
-                                       grp->igmp_version == 3
-                                               ? (grp->group_filtermode_isexcl
-                                                          ? "EXCL"
-                                                          : "INCL")
-                                               : "----",
-                                       hhmmss,
-                                       grp->group_source_list ? listcount(
-                                               grp->group_source_list)
-                                                              : 0,
-                                       grp->igmp_version, uptime);
                        }
-               } /* scan igmp groups */
-       }         /* scan interfaces */
+               } else {
+                       /* scan igmp groups */
+                       for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list,
+                                                 grpnode, grp))
+                               igmp_group_print(ifp, vty, uj, json, grp, now,
+                                                detail);
+               }
+       } /* scan interfaces */
 
-       if (uj)
-               vty_json(vty, json);
+       if (uj) {
+               if (detail)
+                       vty_json_no_pretty(vty, json);
+               else
+                       vty_json(vty, json);
+       }
 }
 
 static void igmp_show_group_retransmission(struct pim_instance *pim,
@@ -981,24 +1177,175 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
        }         /* scan interfaces */
 }
 
+static void igmp_sources_print(struct interface *ifp, char *group_str,
+                              struct gm_source *src, time_t now,
+                              json_object *json, struct vty *vty, bool uj)
+{
+       json_object *json_iface = NULL;
+       json_object *json_group = NULL;
+       json_object *json_sources = NULL;
+       char source_str[INET_ADDRSTRLEN];
+       char mmss[PIM_TIME_STRLEN];
+       char uptime[PIM_TIME_STRLEN];
+
+       pim_inet4_dump("<source?>", src->source_addr, source_str,
+                      sizeof(source_str));
+       pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer);
+       pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation);
+
+       if (uj) {
+               json_object_object_get_ex(json, ifp->name, &json_iface);
+               if (!json_iface) {
+                       json_iface = json_object_new_object();
+                       if (!json_iface)
+                               return;
+                       json_object_string_add(json_iface, "name", ifp->name);
+                       json_object_object_add(json, ifp->name, json_iface);
+               }
+
+               json_object_object_get_ex(json_iface, group_str, &json_group);
+               if (!json_group) {
+                       json_group = json_object_new_object();
+                       if (!json_group)
+                               return;
+                       json_object_string_add(json_group, "group", group_str);
+                       json_object_object_add(json_iface, group_str,
+                                              json_group);
+                       json_sources = json_object_new_array();
+                       if (!json_sources)
+                               return;
+                       json_object_object_add(json_group, "sources",
+                                              json_sources);
+               }
+
+               json_object_object_get_ex(json_group, "sources", &json_sources);
+               if (json_sources)
+                       igmp_source_json_helper(src, json_sources, source_str,
+                                               mmss, uptime);
+       } else {
+               vty_out(vty, "%-16s %-15s %-15s %5s %3s %8s\n", ifp->name,
+                       group_str, source_str, mmss,
+                       IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y"
+                                                                      : "N",
+                       uptime);
+       }
+}
+
+static void igmp_show_sources_interface_single(struct pim_instance *pim,
+                                              struct vty *vty, bool uj,
+                                              const char *ifname,
+                                              const char *grp_str)
+{
+       struct interface *ifp;
+       time_t now;
+       json_object *json = NULL;
+       struct pim_interface *pim_ifp;
+       struct gm_group *grp;
+
+       now = pim_time_monotonic_sec();
+
+       if (uj) {
+               json = json_object_new_object();
+               if (!json)
+                       return;
+       } else {
+               vty_out(vty,
+                       "Interface        Group           Source          Timer Fwd Uptime  \n");
+       }
+
+       ifp = if_lookup_by_name(ifname, pim->vrf->vrf_id);
+       if (!ifp) {
+               if (uj)
+                       vty_json(vty, json);
+               return;
+       }
+
+       pim_ifp = ifp->info;
+       if (!pim_ifp) {
+               if (uj)
+                       vty_json(vty, json);
+               return;
+       }
+
+       if (grp_str) {
+               struct in_addr group_addr;
+               struct gm_sock *igmp;
+               struct listnode *srcnode;
+               struct gm_source *src;
+               char group_str[INET_ADDRSTRLEN];
+               int res;
+
+               res = inet_pton(AF_INET, grp_str, &group_addr);
+               if (res <= 0) {
+                       if (uj)
+                               vty_json(vty, json);
+                       return;
+               }
+
+               igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
+                                                  pim_ifp->primary_address);
+               if (!igmp) {
+                       if (uj)
+                               vty_json(vty, json);
+                       return;
+               }
+
+               grp = find_group_by_addr(igmp, group_addr);
+               if (!grp) {
+                       if (uj)
+                               vty_json(vty, json);
+                       return;
+               }
+               pim_inet4_dump("<group?>", grp->group_addr, group_str,
+                              sizeof(group_str));
+
+               /* scan group sources */
+               for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src))
+                       igmp_sources_print(ifp, group_str, src, now, json, vty,
+                                          uj);
+       } else {
+               struct listnode *grpnode;
+
+               /* scan igmp groups */
+               for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode,
+                                         grp)) {
+                       char group_str[INET_ADDRSTRLEN];
+                       struct listnode *srcnode;
+                       struct gm_source *src;
+
+                       pim_inet4_dump("<group?>", grp->group_addr, group_str,
+                                      sizeof(group_str));
+
+                       /* scan group sources */
+                       for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
+                                                 srcnode, src))
+                               igmp_sources_print(ifp, group_str, src, now,
+                                                  json, vty, uj);
+
+               } /* scan igmp groups */
+       }
+
+       if (uj)
+               vty_json(vty, json);
+}
+
 static void igmp_show_sources(struct pim_instance *pim, struct vty *vty,
                              bool uj)
 {
        struct interface *ifp;
        time_t now;
        json_object *json = NULL;
-       json_object *json_iface = NULL;
-       json_object *json_group = NULL;
-       json_object *json_source = NULL;
-       json_object *json_sources = NULL;
 
        now = pim_time_monotonic_sec();
 
-       if (uj)
+       if (uj) {
                json = json_object_new_object();
-       else
+               if (!json)
+                       return;
+       } else {
                vty_out(vty,
-                       "Interface        Group           Source          Timer Fwd Uptime  \n");
+                       "Interface        Group           Source          Timer Fwd Uptime\n");
+       }
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -1021,82 +1368,12 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty,
 
                        /* scan group sources */
                        for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
-                                                 srcnode, src)) {
-                               char source_str[INET_ADDRSTRLEN];
-                               char mmss[10];
-                               char uptime[10];
-
-                               pim_inet4_dump("<source?>", src->source_addr,
-                                              source_str, sizeof(source_str));
-
-                               pim_time_timer_to_mmss(mmss, sizeof(mmss),
-                                                      src->t_source_timer);
-
-                               pim_time_uptime(uptime, sizeof(uptime),
-                                               now - src->source_creation);
-
-                               if (uj) {
-                                       json_object_object_get_ex(
-                                               json, ifp->name, &json_iface);
-                                       if (!json_iface) {
-                                               json_iface =
-                                                       json_object_new_object();
-                                               json_object_string_add(
-                                                       json_iface, "name",
-                                                       ifp->name);
-                                               json_object_object_add(
-                                                       json, ifp->name,
-                                                       json_iface);
-                                       }
-                                       json_object_object_get_ex(json_iface,
-                                                                 group_str,
-                                                                 &json_group);
-
-                                       if (!json_group) {
-                                               json_group =
-                                                       json_object_new_object();
-                                               json_object_string_add(
-                                                       json_group, "group",
-                                                       group_str);
-                                               json_object_object_add(
-                                                       json_iface, group_str,
-                                                       json_group);
-                                               json_sources =
-                                                       json_object_new_array();
-                                               json_object_object_add(
-                                                       json_group, "sources",
-                                                       json_sources);
-                                       }
-                                       json_source = json_object_new_object();
-                                       json_object_string_add(json_source,
-                                                              "source",
-                                                              source_str);
-                                       json_object_string_add(json_source,
-                                                              "timer", mmss);
-                                       json_object_boolean_add(
-                                               json_source, "forwarded",
-                                               IGMP_SOURCE_TEST_FORWARDING(
-                                                       src->source_flags));
-                                       json_object_string_add(
-                                               json_source, "uptime", uptime);
-                                       json_object_array_add(json_sources,
-                                                             json_source);
-
-                               } else {
-                                       vty_out(vty,
-                                               "%-16s %-15s %-15s %5s %3s %8s\n",
-                                               ifp->name, group_str,
-                                               source_str, mmss,
-                                               IGMP_SOURCE_TEST_FORWARDING(
-                                                       src->source_flags)
-                                                       ? "Y"
-                                                       : "N",
-                                               uptime);
-                               }
-
-                       } /* scan group sources */
+                                                 srcnode, src))
+                               igmp_sources_print(ifp, group_str, src, now,
+                                                  json, vty, uj);
                }        /* scan igmp groups */
        }                 /* scan interfaces */
+
        if (uj)
                vty_json(vty, json);
 }
@@ -1227,7 +1504,7 @@ DEFUN (clear_ip_interfaces,
        VRF_CMD_HELP_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1247,7 +1524,7 @@ DEFUN (clear_ip_igmp_interfaces,
        "Reset IGMP interfaces\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1355,7 +1632,7 @@ DEFUN (clear_ip_pim_bsr_db,
        "Reset pim bsr data\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1378,8 +1655,8 @@ DEFUN (show_ip_igmp_interface,
        JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
        bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1444,8 +1721,8 @@ DEFUN (show_ip_igmp_join,
        JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
        bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1487,39 +1764,47 @@ DEFUN (show_ip_igmp_join_vrf_all,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_igmp_groups,
-       show_ip_igmp_groups_cmd,
-       "show ip igmp [vrf NAME] groups [json]",
-       SHOW_STR
-       IP_STR
-       IGMP_STR
-       VRF_CMD_HELP_STR
-       IGMP_GROUP_STR
-       JSON_STR)
+DEFPY(show_ip_igmp_groups,
+      show_ip_igmp_groups_cmd,
+      "show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail$detail] [json$json]",
+      SHOW_STR
+      IP_STR
+      IGMP_STR
+      VRF_CMD_HELP_STR
+      IGMP_GROUP_STR
+      "Interface name\n"
+      "Group address\n"
+      "Detailed Information\n"
+      JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
-       bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, !!json);
 
        if (!vrf)
                return CMD_WARNING;
 
-       igmp_show_groups(vrf->info, vty, uj);
+       if (ifname)
+               igmp_show_groups_interface_single(vrf->info, vty, !!json,
+                                                 ifname, grp_str, !!detail);
+       else
+               igmp_show_groups(vrf->info, vty, !!json, NULL, !!detail);
 
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_igmp_groups_vrf_all,
-       show_ip_igmp_groups_vrf_all_cmd,
-       "show ip igmp vrf all groups [json]",
-       SHOW_STR
-       IP_STR
-       IGMP_STR
-       VRF_CMD_HELP_STR
-       IGMP_GROUP_STR
-       JSON_STR)
+DEFPY(show_ip_igmp_groups_vrf_all,
+      show_ip_igmp_groups_vrf_all_cmd,
+      "show ip igmp vrf all groups [GROUP$grp_str] [detail$detail] [json$json]",
+      SHOW_STR
+      IP_STR
+      IGMP_STR
+      VRF_CMD_HELP_STR
+      IGMP_GROUP_STR
+      "Group address\n"
+      "Detailed Information\n"
+      JSON_STR)
 {
-       bool uj = use_json(argc, argv);
+       bool uj = !!json;
        struct vrf *vrf;
        bool first = true;
 
@@ -1533,7 +1818,7 @@ DEFUN (show_ip_igmp_groups_vrf_all,
                        first = false;
                } else
                        vty_out(vty, "VRF: %s\n", vrf->name);
-               igmp_show_groups(vrf->info, vty, uj);
+               igmp_show_groups(vrf->info, vty, uj, grp_str, !!detail);
        }
        if (uj)
                vty_out(vty, "}\n");
@@ -1552,7 +1837,7 @@ DEFUN (show_ip_igmp_groups_retransmissions,
        "IGMP group retransmissions\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1562,23 +1847,29 @@ DEFUN (show_ip_igmp_groups_retransmissions,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_igmp_sources,
-       show_ip_igmp_sources_cmd,
-       "show ip igmp [vrf NAME] sources [json]",
-       SHOW_STR
-       IP_STR
-       IGMP_STR
-       VRF_CMD_HELP_STR
-       IGMP_SOURCE_STR
-       JSON_STR)
+DEFPY(show_ip_igmp_sources,
+      show_ip_igmp_sources_cmd,
+      "show ip igmp [vrf NAME$vrf_name] sources [INTERFACE$ifname [GROUP$grp_str]] [json$json]",
+      SHOW_STR
+      IP_STR
+      IGMP_STR
+      VRF_CMD_HELP_STR
+      IGMP_SOURCE_STR
+      "Interface name\n"
+      "Group address\n"
+      JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, !!json);
 
        if (!vrf)
                return CMD_WARNING;
 
-       igmp_show_sources(vrf->info, vty, use_json(argc, argv));
+       if (ifname)
+               igmp_show_sources_interface_single(vrf->info, vty, !!json,
+                                                  ifname, grp_str);
+       else
+               igmp_show_sources(vrf->info, vty, !!json);
 
        return CMD_SUCCESS;
 }
@@ -1594,7 +1885,7 @@ DEFUN (show_ip_igmp_sources_retransmissions,
        "IGMP source retransmissions\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1617,8 +1908,8 @@ DEFUN (show_ip_igmp_statistics,
        JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
        bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1746,7 +2037,7 @@ DEFUN (show_ip_pim_assert,
        "PIM interface assert\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1766,7 +2057,7 @@ DEFUN (show_ip_pim_assert_internal,
        "PIM interface internal assert state\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1786,7 +2077,7 @@ DEFUN (show_ip_pim_assert_metric,
        "PIM interface assert metric\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -1806,7 +2097,7 @@ DEFUN (show_ip_pim_assert_winner_metric,
        "PIM interface assert winner metric\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -2125,8 +2416,8 @@ DEFUN(show_ip_pim_mlag_up, show_ip_pim_mlag_up_cmd,
        const char *src_or_group = NULL;
        const char *group = NULL;
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
        bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf || !vrf->info) {
                vty_out(vty, "%s: VRF or Info missing\n", __func__);
@@ -2598,7 +2889,7 @@ DEFUN (show_ip_rib,
        "Unicast address\n")
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
        struct in_addr addr;
        const char *addr_str;
        struct pim_nexthop nexthop;
@@ -2686,7 +2977,7 @@ DEFUN (show_ip_ssmpingd,
        VRF_CMD_HELP_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false);
 
        if (!vrf)
                return CMD_WARNING;
@@ -3141,8 +3432,8 @@ DEFUN (show_ip_pim_ssm_range,
        JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
        bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -3192,8 +3483,8 @@ DEFUN (show_ip_pim_group_type,
        JSON_STR)
 {
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
        bool uj = use_json(argc, argv);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -5086,7 +5377,7 @@ DEFUN (show_ip_msdp_mesh_group,
        bool uj = use_json(argc, argv);
        int idx = 2;
        struct pim_msdp_mg *mg;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
        struct pim_instance *pim;
        struct json_object *json = NULL;
 
@@ -5322,7 +5613,7 @@ DEFUN (show_ip_msdp_peer_detail,
 {
        bool uj = use_json(argc, argv);
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -5562,7 +5853,7 @@ DEFUN (show_ip_msdp_sa_detail,
 {
        bool uj = use_json(argc, argv);
        int idx = 2;
-       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -5677,7 +5968,7 @@ DEFUN (show_ip_msdp_sa_sg,
        struct vrf *vrf;
        int idx = 2;
 
-       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -5947,7 +6238,7 @@ DEFUN (show_ip_pim_vxlan_sg,
        struct vrf *vrf;
        int idx = 2;
 
-       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
@@ -6007,7 +6298,7 @@ DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work,
        struct vrf *vrf;
        int idx = 2;
 
-       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
 
        if (!vrf)
                return CMD_WARNING;
index fb6693491ba5dc7acb6ee520d01c86ccbb94f986..d39d77cd2fde34fc1332c03468362328bb7295b7 100644 (file)
@@ -60,4 +60,5 @@
 
 void pim_cmd_init(void);
 
+#define PIM_TIME_STRLEN 10
 #endif /* PIM_CMD_H */
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_group_all_detail.json b/tests/topotests/multicast_pim_sm_topo3/igmp_group_all_detail.json
new file mode 100644 (file)
index 0000000..715aa1d
--- /dev/null
@@ -0,0 +1 @@
+{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_brief.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_brief.json
new file mode 100644 (file)
index 0000000..3bbcce1
--- /dev/null
@@ -0,0 +1,51 @@
+{
+  "totalGroups":5,
+  "watermarkLimit":0,
+  "l1-i1-eth1":{
+    "name":"l1-i1-eth1",
+    "state":"up",
+    "address":"10.0.8.2",
+    "index":"*",
+    "flagMulticast":true,
+    "flagBroadcast":true,
+    "lanDelayEnabled":true,
+    "groups":[
+      {
+        "group":"225.1.1.1",
+        "timer":"*",
+        "sourcesCount":1,
+        "version":2,
+        "uptime":"*"
+      },
+      {
+        "group":"225.1.1.2",
+        "timer":"*",
+        "sourcesCount":1,
+        "version":2,
+        "uptime":"*"
+      },
+      {
+        "group":"225.1.1.3",
+        "timer":"*",
+        "sourcesCount":1,
+        "version":2,
+        "uptime":"*"
+      },
+      {
+        "group":"225.1.1.4",
+        "timer":"*",
+        "sourcesCount":1,
+        "version":2,
+        "uptime":"*"
+      },
+      {
+        "group":"225.1.1.5",
+        "timer":"*",
+        "sourcesCount":1,
+        "version":2,
+        "uptime":"*"
+      }
+    ]
+  }
+}
+
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_detail.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_detail.json
new file mode 100644 (file)
index 0000000..876befa
--- /dev/null
@@ -0,0 +1 @@
+{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_brief.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_brief.json
new file mode 100644 (file)
index 0000000..a3fb496
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "totalGroups":5,
+  "watermarkLimit":0,
+  "l1-i1-eth1":{
+    "name":"l1-i1-eth1",
+    "state":"up",
+    "address":"10.0.8.2",
+    "index":"*",
+    "flagMulticast":true,
+    "flagBroadcast":true,
+    "lanDelayEnabled":true,
+    "groups":[
+      {
+        "group":"225.1.1.5",
+        "timer":"*",
+        "sourcesCount":1,
+        "version":2,
+        "uptime":"*"
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_detail.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_detail.json
new file mode 100644 (file)
index 0000000..11ac5a0
--- /dev/null
@@ -0,0 +1 @@
+{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_group_all.json b/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_group_all.json
new file mode 100644 (file)
index 0000000..10ae1af
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "l1-i1-eth1":{
+    "name":"l1-i1-eth1",
+    "225.1.1.1":{
+      "group":"225.1.1.1",
+      "sources":[
+        {
+          "source":"*",
+          "timer":"*",
+          "forwarded":true,
+          "uptime":"*"
+        }
+      ]
+    },
+    "225.1.1.2":{
+      "group":"225.1.1.2",
+      "sources":[
+        {
+          "source":"*",
+          "timer":"*",
+          "forwarded":true,
+          "uptime":"*"
+        }
+      ]
+    },
+    "225.1.1.3":{
+      "group":"225.1.1.3",
+      "sources":[
+        {
+          "source":"*",
+          "timer":"*",
+          "forwarded":true,
+          "uptime":"*"
+        }
+      ]
+    },
+    "225.1.1.4":{
+      "group":"225.1.1.4",
+      "sources":[
+        {
+          "source":"*",
+          "timer":"*",
+          "forwarded":true,
+          "uptime":"*"
+        }
+      ]
+    },
+    "225.1.1.5":{
+      "group":"225.1.1.5",
+      "sources":[
+        {
+          "source":"*",
+          "timer":"*",
+          "forwarded":true,
+          "uptime":"*"
+        }
+      ]
+    }
+  }
+}
+
diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_single_group.json b/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_single_group.json
new file mode 100644 (file)
index 0000000..7a19975
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "l1-i1-eth1":{
+    "name":"l1-i1-eth1",
+    "225.1.1.4":{
+      "group":"225.1.1.4",
+      "sources":[
+        {
+          "source":"*",
+          "timer":"*",
+          "forwarded":true,
+          "uptime":"*"
+        }
+      ]
+    }
+  }
+}
index 2ffd3a3ac0ef914188eb37449d827ef1b1c358e9..2c1241c0ccc9db342428671dc4c557c3c3a3edbc 100755 (executable)
@@ -42,6 +42,8 @@ import time
 import datetime
 import pytest
 from time import sleep
+import json
+import functools
 
 pytestmark = pytest.mark.pimd
 
@@ -54,8 +56,8 @@ sys.path.append(os.path.join(CWD, "../lib/"))
 
 # pylint: disable=C0413
 # Import topogen and topotest helpers
-from lib.topogen import Topogen, get_topogen
-
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
 from lib.common_config import (
     start_topology,
     write_test_header,
@@ -1510,6 +1512,108 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
         )
         assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
 
+    # IGMP JSON verification
+    step("Verify IGMP group and source JSON for single interface and group")
+    router = tgen.gears["l1"]
+
+    reffile = os.path.join(CWD, "igmp_group_all_detail.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp vrf default groups detail json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP group detailed output on l1 for all interfaces and all groups is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
+    reffile = os.path.join(CWD, "igmp_single_if_group_all_brief.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp vrf default groups l1-i1-eth1 json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP group output on l1 for all groups in interface l1-i1-eth1 is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
+    reffile = os.path.join(CWD, "igmp_single_if_group_all_detail.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp vrf default groups l1-i1-eth1 detail json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP group detailed output on l1 for all groups in interface l1-i1-eth1 is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
+    reffile = os.path.join(CWD, "igmp_single_if_single_group_brief.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp vrf default groups l1-i1-eth1 225.1.1.5 json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP group output on l1 for interface l1-i1-eth1 and group 225.1.1.5 is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
+    reffile = os.path.join(CWD, "igmp_single_if_single_group_detail.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp vrf default groups l1-i1-eth1 225.1.1.5 detail json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP group detailed output on l1 for interface l1-i1-eth1 and group 225.1.1.5 is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
+    reffile = os.path.join(CWD, "igmp_source_single_if_group_all.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp sources l1-i1-eth1 json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP source output on l1 for interface l1-i1-eth1 is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
+    reffile = os.path.join(CWD, "igmp_source_single_if_single_group.json")
+    expected = json.loads(open(reffile).read())
+    test_func = functools.partial(
+        topotest.router_json_cmp,
+        router,
+        "show ip igmp sources l1-i1-eth1 225.1.1.4 json",
+        expected,
+    )
+    _, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
+    assertmsg = "IGMP source output on l1 for interface l1-i1-eth1 and group 225.1.1.4 is not as expected. Expected: {}".format(
+        expected
+    )
+    assert res is None, assertmsg
+
     step(
         "Remove igmp 'no ip igmp' and 'no ip igmp version 2' from"
         " receiver interface of FRR1"