From 339f76953034064934df5ff02702138f2d039803 Mon Sep 17 00:00:00 2001 From: saravanank Date: Tue, 31 Mar 2020 19:34:13 -0700 Subject: [PATCH 1/3] pimd: Implement watermark warning for igmp group count and add igmp group count This CLI will allow user to configure a igmp group limit which will generate a watermark warning when reached. Though watermark may not make sense without setting a limit, this implementation shall serve as a base to implementing limit in future and helps tracking a particular scale currently. Testing: ======= ip igmp watermark-warn <10-60000> on reaching the configured number of group, pim will issue warning 2019/09/18 18:30:55 PIM: SCALE ALERT: igmp group count reached watermak limit: 210(vrf: default) Also added group count and watermark limit configured on cli - show ip igmp groups [json] Sw3# sh ip igmp groups json { "Total Groups":221, <===== "Watermark limit":210, <========= "ens224":{ "name":"ens224", "state":"up", "address":"40.0.0.1", "index":6, "flagMulticast":true, "flagBroadcast":true, "lanDelayEnabled":true, "groups":[ { "source":"40.0.0.1", "group":"225.1.1.122", "timer":"00:03:56", "sourcesCount":1, "version":2, "uptime":"00:00:24" <\snip> Sw3(config)# do sh ip igmp group Total IGMP groups: 221 Watermark warn limit(Set) : 210 Interface Address Group Mode Timer Srcs V Uptime ens224 40.0.0.1 225.1.1.122 ---- 00:04:06 1 2 00:13:22 ens224 40.0.0.1 225.1.1.144 ---- 00:04:02 1 2 00:13:22 ens224 40.0.0.1 225.1.1.57 ---- 00:04:01 1 2 00:13:22 ens224 40.0.0.1 225.1.1.210 ---- 00:04:06 1 2 00:13:22 <\snip> Signed-off-by: Saravanan K --- pimd/pim_cmd.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- pimd/pim_igmp.c | 36 ++++++++++++++++++++++++++++++++++++ pimd/pim_instance.h | 2 ++ pimd/pim_vty.c | 7 +++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0c14aff9ff..2958f720e7 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3419,11 +3419,19 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) now = pim_time_monotonic_sec(); - if (uj) + if (uj) { json = json_object_new_object(); - else + json_object_int_add(json, "totalGroups", pim->igmp_group_count); + json_object_int_add(json, "watermarkLimit", + pim->igmp_watermark_limit); + } else { + vty_out(vty, "Total IGMP groups: %u\n", pim->igmp_group_count); + vty_out(vty, "Watermark warn limit(%s): %u\n", + pim->igmp_watermark_limit ? "Set" : "Not Set", + pim->igmp_watermark_limit); vty_out(vty, "Interface Address Group Mode Timer Srcs V Uptime \n"); + } /* scan interfaces */ FOR_ALL_INTERFACES (pim->vrf, ifp) { @@ -6861,6 +6869,35 @@ DEFUN (no_ip_pim_packets, return CMD_SUCCESS; } +DEFPY (igmp_group_watermark, + igmp_group_watermark_cmd, + "ip igmp watermark-warn (10-60000)$limit", + IP_STR + IGMP_STR + "Configure group limit for watermark warning\n" + "Group count to generate watermark warning\n") +{ + PIM_DECLVAR_CONTEXT(vrf, pim); + pim->igmp_watermark_limit = limit; + + return CMD_SUCCESS; +} + +DEFPY (no_igmp_group_watermark, + no_igmp_group_watermark_cmd, + "no ip igmp watermark-warn [(10-60000)$limit]", + NO_STR + IP_STR + IGMP_STR + "Unconfigure group limit for watermark warning\n" + "Group count to generate watermark warning\n") +{ + PIM_DECLVAR_CONTEXT(vrf, pim); + pim->igmp_watermark_limit = 0; + + return CMD_SUCCESS; +} + DEFUN (ip_pim_v6_secondary, ip_pim_v6_secondary_cmd, "ip pim send-v6-secondary", @@ -10893,6 +10930,10 @@ void pim_cmd_init(void) install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd); install_element(CONFIG_NODE, &ip_pim_mlag_cmd); install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd); + install_element(CONFIG_NODE, &igmp_group_watermark_cmd); + install_element(VRF_NODE, &igmp_group_watermark_cmd); + install_element(CONFIG_NODE, &no_igmp_group_watermark_cmd); + install_element(VRF_NODE, &no_igmp_group_watermark_cmd); install_element(INTERFACE_NODE, &interface_ip_igmp_cmd); install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 8d39d7e800..461c2698d5 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -753,6 +753,39 @@ static void igmp_group_free(struct igmp_group *group) XFREE(MTYPE_PIM_IGMP_GROUP, group); } +static void igmp_group_count_incr(struct igmp_sock *igmp) +{ + struct pim_interface *pim_ifp = igmp->interface->info; + + if (!pim_ifp) + return; + + ++pim_ifp->pim->igmp_group_count; + if (pim_ifp->pim->igmp_group_count + == pim_ifp->pim->igmp_watermark_limit) { + zlog_warn( + "IGMP group count reached watermark limit: %u(vrf: %s)", + pim_ifp->pim->igmp_group_count, + VRF_LOGNAME(pim_ifp->pim->vrf)); + } +} + +static void igmp_group_count_decr(struct igmp_sock *igmp) +{ + struct pim_interface *pim_ifp = igmp->interface->info; + + if (!pim_ifp) + return; + + if (pim_ifp->pim->igmp_group_count == 0) { + zlog_warn("Cannot decrement igmp group count below 0(vrf: %s)", + VRF_LOGNAME(pim_ifp->pim->vrf)); + return; + } + + --pim_ifp->pim->igmp_group_count; +} + void igmp_group_delete(struct igmp_group *group) { struct listnode *src_node; @@ -778,6 +811,7 @@ void igmp_group_delete(struct igmp_group *group) } group_timer_off(group); + igmp_group_count_decr(group->group_igmp_sock); listnode_delete(group->group_igmp_sock->igmp_group_list, group); hash_release(group->group_igmp_sock->igmp_group_hash, group); @@ -1158,6 +1192,8 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, group_str, igmp->fd, igmp->interface->name); } + igmp_group_count_incr(igmp); + /* RFC 3376: 6.2.2. Definition of Group Timers diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 71bd7c1089..2b76da21b2 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -178,6 +178,8 @@ struct pim_instance { struct list *ssmpingd_list; struct in_addr ssmpingd_group_addr; + unsigned int igmp_group_count; + unsigned int igmp_watermark_limit; unsigned int keep_alive_time; unsigned int rp_keep_alive_time; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 72540903be..fee8d6ed1b 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -239,6 +239,13 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) vty_out(vty, "%sip pim ecmp\n", spaces); ++writes; } + + if (pim->igmp_watermark_limit != 0) { + vty_out(vty, "%sip igmp watermark-warn %u\n", spaces, + pim->igmp_watermark_limit); + ++writes; + } + if (pim->ssmpingd_list) { struct listnode *node; struct ssmpingd_sock *ss; From 4d360968887657eba49b3a494356433dabeb8bb0 Mon Sep 17 00:00:00 2001 From: saravanank Date: Tue, 31 Mar 2020 22:13:13 -0700 Subject: [PATCH 2/3] pimd: show ip igmp groups json output - Make group array for each interface JSON output for igmp group display is modified as follows for better python handling. 1. Under each interface make array of group as an object 2. Include source and group inside each group object These improvements are required for the set of topotest cases which will be upstreamed shortly. Signed-off-by: Saravanan K --- pimd/pim_cmd.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 2958f720e7..871606414e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3415,7 +3415,8 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) time_t now; json_object *json = NULL; json_object *json_iface = NULL; - json_object *json_row = NULL; + json_object *json_group = NULL; + json_object *json_groups = NULL; now = pim_time_monotonic_sec(); @@ -3478,37 +3479,44 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) json_object_object_add( json, ifp->name, json_iface); + json_groups = + json_object_new_array(); + json_object_object_add( + json_iface, + "groups", + json_groups); } - json_row = json_object_new_object(); - json_object_string_add( - json_row, "source", ifaddr_str); - json_object_string_add( - json_row, "group", group_str); + json_group = json_object_new_object(); + json_object_string_add(json_group, + "source", + ifaddr_str); + json_object_string_add(json_group, + "group", + group_str); if (grp->igmp_version == 3) json_object_string_add( - json_row, "mode", + json_group, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); - json_object_string_add(json_row, + json_object_string_add(json_group, "timer", hhmmss); json_object_int_add( - json_row, "sourcesCount", + json_group, "sourcesCount", grp->group_source_list ? listcount( grp->group_source_list) : 0); - json_object_int_add(json_row, "version", - grp->igmp_version); + json_object_int_add( + json_group, "version", + grp->igmp_version); json_object_string_add( - json_row, "uptime", uptime); - json_object_object_add(json_iface, - group_str, - json_row); - + json_group, "uptime", uptime); + json_object_array_add(json_groups, + json_group); } else { vty_out(vty, "%-16s %-15s %-15s %4s %8s %4d %d %8s\n", From daeda8dd5770a0afa17f3384d76ed2becb7ec5d9 Mon Sep 17 00:00:00 2001 From: saravanank Date: Tue, 31 Mar 2020 23:34:03 -0700 Subject: [PATCH 3/3] doc: Add 'ip igmp watermark-warn (10-60000)' command to pim user documentation Signed-off-by: Saravanan K --- doc/user/pim.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/user/pim.rst b/doc/user/pim.rst index f480c6bdc4..2aa66d9dd9 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -173,6 +173,14 @@ Certain signals have special meanings to *pimd*. the existing IGMP general query timer.If no version is provided in the cli, it will be considered as default v2 query.This is a hidden command. +.. index:: [no] ip igmp watermark-warn (10-60000) +.. clicmd:: [no] ip igmp watermark-warn (10-60000) + + Configure watermark warning generation for an igmp group limit. Generates + warning once the configured group limit is reached while adding new groups. + 'no' form of the command disables the warning generation. This command is + vrf aware. To configure per vrf, enter vrf submode. + .. _pim-interface-configuration: PIM Interface Configuration