diff --git a/doc/user/pim.rst b/doc/user/pim.rst index f0ec2d26ff..2944e0b705 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -178,6 +178,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 diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f99888b3af..f6af98598b 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3419,15 +3419,24 @@ 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(); - 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) { @@ -3474,37 +3483,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", @@ -6865,6 +6881,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", @@ -10910,6 +10955,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;