pimd: Option to get IGMP groups and sources for a particular interface

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>
This commit is contained in:
Pooja Jagadeesh Doijode 2023-04-10 14:34:35 -07:00
parent d246726b5e
commit 5519cabe4c
11 changed files with 774 additions and 220 deletions

View 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.

View 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)
{
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;
json_object *json_iface = NULL;
json_object *json_group = NULL;
json_object *json_groups = 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];
if (grp_str) {
struct in_addr group_addr;
struct gm_sock *igmp;
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 (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;

View File

@ -60,4 +60,5 @@
void pim_cmd_init(void);
#define PIM_TIME_STRLEN 10
#endif /* PIM_CMD_H */

View File

@ -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":"*"}]}]}}

View File

@ -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":"*"
}
]
}
}

View File

@ -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":"*"}]}]}}

View File

@ -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":"*"
}
]
}
}

View File

@ -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":"*"}]}]}}

View File

@ -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":"*"
}
]
}
}
}

View File

@ -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":"*"
}
]
}
}
}

View File

@ -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"