diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/igmp/igmp_report.c | 94 |
1 files changed, 74 insertions, 20 deletions
diff --git a/src/plugins/igmp/igmp_report.c b/src/plugins/igmp/igmp_report.c index 7c08f342199..2e73ee15375 100644 --- a/src/plugins/igmp/igmp_report.c +++ b/src/plugins/igmp/igmp_report.c @@ -53,35 +53,48 @@ igmp_group_mk_source_list (const igmp_membership_group_v3_t * r) } static void -igmp_handle_group_update (igmp_config_t * config, - const igmp_membership_group_v3_t * igmp_group) +igmp_handle_group_exclude (igmp_config_t * config, + const igmp_membership_group_v3_t * igmp_group) { - ip46_address_t *src, *srcs; - igmp_group_t *group; ip46_address_t key = { .ip4 = igmp_group->group_address, }; + u16 n; - srcs = igmp_group_mk_source_list (igmp_group); - group = igmp_group_lookup (config, &key); - - IGMP_DBG (" ..group-update: %U (%U, %U)", - format_vnet_sw_if_index_name, - vnet_get_main (), config->sw_if_index, - format_igmp_key, &key, format_igmp_src_addr_list, srcs); + /* + * treat an exclude all sources as a *,G join + */ + n = clib_net_to_host_u16 (igmp_group->n_src_addresses); - if (NULL == group) + if (0 == n) { - group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE); - } + ip46_address_t *src, *srcs; + igmp_group_t *group; - /* create or update all sources */ - vec_foreach (src, srcs) - { - igmp_group_src_update (group, src, IGMP_MODE_ROUTER); - } + group = igmp_group_lookup (config, &key); + srcs = igmp_group_mk_source_list (igmp_group); - vec_free (srcs); + IGMP_DBG (" ..group-update: %U (*, %U)", + format_vnet_sw_if_index_name, + vnet_get_main (), config->sw_if_index, format_igmp_key, &key); + + if (NULL == group) + { + group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE); + } + vec_foreach (src, srcs) + { + igmp_group_src_update (group, src, IGMP_MODE_ROUTER); + } + + vec_free (srcs); + } + else + { + IGMP_DBG (" ..group-update: %U (*, %U) source exclude ignored", + format_vnet_sw_if_index_name, + vnet_get_main (), config->sw_if_index, format_igmp_key, &key); + } } static void @@ -132,6 +145,46 @@ igmp_handle_group_block (igmp_config_t * config, } static void +igmp_handle_group_update (igmp_config_t * config, + const igmp_membership_group_v3_t * igmp_group) +{ + ip46_address_t *src, *srcs; + igmp_group_t *group; + ip46_address_t key = { + .ip4 = igmp_group->group_address, + }; + + /* + * treat a TO_INC({}) as a (*,G) leave + */ + if (0 == clib_net_to_host_u16 (igmp_group->n_src_addresses)) + { + return (igmp_handle_group_block (config, igmp_group)); + } + + srcs = igmp_group_mk_source_list (igmp_group); + group = igmp_group_lookup (config, &key); + + IGMP_DBG (" ..group-update: %U (%U, %U)", + format_vnet_sw_if_index_name, + vnet_get_main (), config->sw_if_index, + format_igmp_key, &key, format_igmp_src_addr_list, srcs); + + if (NULL == group) + { + group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE); + } + + /* create or update all sources */ + vec_foreach (src, srcs) + { + igmp_group_src_update (group, src, IGMP_MODE_ROUTER); + } + + vec_free (srcs); +} + +static void igmp_handle_group (igmp_config_t * config, const igmp_membership_group_v3_t * igmp_group) { @@ -151,6 +204,7 @@ igmp_handle_group (igmp_config_t * config, break; case IGMP_MEMBERSHIP_GROUP_mode_is_exclude: case IGMP_MEMBERSHIP_GROUP_change_to_exclude: + igmp_handle_group_exclude (config, igmp_group); break; /* * all other types ignored |