2 *------------------------------------------------------------------
3 * Copyright (c) 2018 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
18 #include <igmp/igmp_report.h>
19 #include <igmp/igmp_pkt.h>
21 static ip46_address_t *
22 igmp_group_mk_source_list (const igmp_membership_group_v3_t * r)
24 ip46_address_t *srcs = NULL;
25 const ip4_address_t *s;
29 * we validated this packet when we accepted it in the DP, so
30 * this number is safe to use
32 n = clib_net_to_host_u16 (r->n_src_addresses);
37 vec_validate (srcs, n - 1);
40 for (ii = 0; ii < n; ii++)
50 igmp_handle_group_update (igmp_config_t * config,
51 const igmp_membership_group_v3_t * igmp_group)
53 ip46_address_t *src, *srcs;
55 ip46_address_t key = {
56 .ip4 = igmp_group->group_address,
59 srcs = igmp_group_mk_source_list (igmp_group);
60 group = igmp_group_lookup (config, &key);
62 IGMP_DBG (" ..group-update: %U (%U, %U)",
63 format_vnet_sw_if_index_name,
64 vnet_get_main (), config->sw_if_index,
65 format_igmp_key, &key, format_igmp_src_addr_list, srcs);
69 group = igmp_group_alloc (config, &key, IGMP_FILTER_MODE_INCLUDE);
72 /* create or update all sources */
73 vec_foreach (src, srcs)
75 igmp_group_src_update (group, src, IGMP_MODE_ROUTER);
82 igmp_handle_group_block (igmp_config_t * config,
83 const igmp_membership_group_v3_t * igmp_group)
85 ip46_address_t *s, *srcs;
86 igmp_pkt_build_query_t bq;
88 ip46_address_t key = {
89 .ip4 = igmp_group->group_address,
92 srcs = igmp_group_mk_source_list (igmp_group);
93 group = igmp_group_lookup (config, &key);
95 IGMP_DBG (" ..group-block: %U (%U, %U)",
96 format_vnet_sw_if_index_name,
97 vnet_get_main (), config->sw_if_index,
98 format_igmp_key, &key, format_igmp_src_addr_list, srcs);
104 * sned a group+source specific query
106 igmp_pkt_build_query_init (&bq, config->sw_if_index);
107 igmp_pkt_query_v3_add_group (&bq, group, srcs);
108 igmp_pkt_query_v3_send (&bq);
111 * for each source left/blocked drop the source expire timer to the leave
114 vec_foreach (s, srcs)
116 src = igmp_src_lookup (group, s);
118 igmp_src_blocked (src);
122 * a block/leave from a group for which we have no state
129 igmp_handle_group (igmp_config_t * config,
130 const igmp_membership_group_v3_t * igmp_group)
132 IGMP_DBG ("rx-group-report: %U",
133 format_vnet_sw_if_index_name,
134 vnet_get_main (), config->sw_if_index);
136 switch (igmp_group->type)
138 case IGMP_MEMBERSHIP_GROUP_mode_is_include:
139 case IGMP_MEMBERSHIP_GROUP_change_to_include:
140 case IGMP_MEMBERSHIP_GROUP_allow_new_sources:
141 igmp_handle_group_update (config, igmp_group);
143 case IGMP_MEMBERSHIP_GROUP_block_old_sources:
144 igmp_handle_group_block (config, igmp_group);
146 case IGMP_MEMBERSHIP_GROUP_mode_is_exclude:
147 case IGMP_MEMBERSHIP_GROUP_change_to_exclude:
150 * all other types ignored
156 igmp_handle_report (const igmp_report_args_t * args)
158 const igmp_membership_group_v3_t *igmp_group;
159 igmp_config_t *config;
162 config = igmp_config_lookup (args->sw_if_index);
166 * no IGMP config on the interface. quit
170 if (IGMP_MODE_HOST == config->mode)
173 * Hosts need not listen to the reports of other hosts.
180 * we validated this packet when we accepted it in the DP, so
181 * this number is safe to use
183 n_groups = clib_net_to_host_u16 (args->report[0].n_groups);
184 igmp_group = args->report[0].groups;
186 for (ii = 0; ii < n_groups; ii++)
188 igmp_handle_group (config, igmp_group);
190 igmp_group = group_cptr (igmp_group,
191 igmp_membership_group_v3_length (igmp_group));
196 * fd.io coding-style-patch-verification: ON
199 * eval: (c-set-style "gnu")