2 *------------------------------------------------------------------
3 * Copyright (c) 2017 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 *------------------------------------------------------------------
21 #include <vlib/vlib.h>
22 #include <vnet/ip/ip.h>
23 #include <vnet/ip/igmp_packet.h>
24 #include <vnet/adj/adj_mcast.h>
25 #include <igmp/igmp_format.h>
27 #define IGMP_QUERY_TIMER (60)
28 #define IGMP_SRC_TIMER (3 * IGMP_QUERY_TIMER)
29 #define IGMP_DEFAULT_ROBUSTNESS_VARIABLE (2)
31 #define ENABLE_IGMP_DBG 0
33 #if ENABLE_IGMP_DBG == 1
34 #define IGMP_DBG(...) clib_warning(__VA_ARGS__)
37 #endif /* ENABLE_IGMP_DBG */
39 /** General Query address - 224.0.0.1 */
40 #define IGMP_GENERAL_QUERY_ADDRESS (0xE0000001)
41 /** Membership Report address - 224.0.0.22 */
42 #define IGMP_MEMBERSHIP_REPORT_ADDRESS (0xE0000016)
44 /** helper macro to get igmp mebership group from pointer plus offset */
45 #define group_ptr(p, l) ((igmp_membership_group_v3_t *)((char*)p + l))
49 IGMP_PROCESS_EVENT_UPDATE_TIMER = 1,
50 } igmp_process_event_t;
60 struct igmp_config_t_;
62 typedef struct igmp_config_t_ igmp_config_t;
66 typedef struct igmp_group_t_ igmp_group_t;
68 /** \brief create message
69 @param b - vlib buffer
70 @param config - igmp configuration
71 @param group - igmp group
73 Populate supplied bufefr with IGMP message.
75 typedef void (create_msg_t) (vlib_buffer_t * b, igmp_config_t * config,
76 igmp_group_t * group);
79 @param data - key data
80 @param group_type - membership group type
84 u64 data[2]; /*!< ip46_address_t.as_u64 */
85 u64 group_type; /*!< zero in case of source key */
88 /** \brief igmp source
89 @param addr - ip4/6 source address
90 @param exp_time - expiration time
91 @param key - pointer to key
102 /** \brief igmp group
103 @param addr - ip4/6 group address
104 @param exp_time - expiration time
105 @param key - pointer to key
106 @param type - membership group type
107 @param n_srcs - number of sources
108 @param flags - igmp group flags
109 @param igmp_src_by_key - source by key hash
110 @param srcs - pool of sources
112 typedef struct igmp_group_t_
120 igmp_membership_group_v3_type_t type;
125 /** reponse to query was received */
126 #define IGMP_GROUP_FLAG_QUERY_RESP_RECVED (1 << 0)
128 uword *igmp_src_by_key;
132 /** \brief igmp configuration
133 @param sw_if_index - interface sw_if_index
134 @param adj_index - adjacency index
135 @param cli_api_configured - if zero, an igmp report was received
136 @param next_create_msg - specify next igmp message
137 @param igmp_ver - igmp version
138 @param robustness_var - robustness variable
139 @param flags - igmp configuration falgs
140 @param igmp_group_by_key - group by key hash
141 @param groups - pool of groups
143 typedef struct igmp_config_t_
147 adj_index_t adj_index;
149 u8 cli_api_configured;
151 create_msg_t *next_create_msg;
158 #define IGMP_CONFIG_FLAG_QUERY_RESP_RECVED (1 << 0)
159 #define IGMP_CONFIG_FLAG_CAN_SEND_REPORT (1 << 1)
161 uword *igmp_group_by_key;
163 igmp_group_t *groups;
166 struct igmp_timer_t_;
168 typedef struct igmp_timer_t_ igmp_timer_t;
170 /** \brief igmp api client
171 @param client_index - client index
174 typedef struct igmp_api_client_t_
189 igmp_membership_group_v3_type_t type;
190 } igmp_report_type_info_t;
193 @param msg_id_base - API message ID base
194 @param igmp_api_client_by_client_index - get api client by client_index
195 @param api_clients - pool of api clients registered for join/leave notifications
196 @param igmp_config_by_sw_if_index - get config index by config key
197 @param configs - pool of igmp configurations
198 @param buffers - buffer cache
199 @param timers - pool of igmp timers
200 @param type_infos - igmp type info
201 @param report_type_infos - igmp report type info
202 @param type_info_by_type -
203 @param report_type_info_by_report_type -
204 @param general_query_address - 224.0.0.1
205 @param membership_report_address - 224.0.0.22
207 typedef struct igmp_main_t_
211 uword *igmp_api_client_by_client_index;
213 igmp_api_client_t *api_clients;
215 uword *igmp_config_by_sw_if_index;
217 igmp_config_t *configs;
221 igmp_timer_t *timers;
223 igmp_type_info_t *type_infos;
224 igmp_report_type_info_t *report_type_infos;
226 uword *type_info_by_type;
227 uword *report_type_info_by_report_type;
230 extern igmp_main_t igmp_main;
232 /** \brief igmp timer function
233 @param vm - vlib main
234 @param rt - vlib runtime node
235 @param im - igmp main
236 @param timer - igmp timer
238 typedef void (igmp_timer_function_t) (vlib_main_t * vm,
239 vlib_node_runtime_t * rt,
240 igmp_main_t * im, igmp_timer_t * timer);
242 /** \brief igmp timer
243 @param exp_time - expiration time
244 @param func - function to call on timer expiration
245 @param sw_if_index - interface sw_if_index
246 @param data - custom data
248 typedef struct igmp_timer_t_
251 igmp_timer_function_t *func;
257 extern vlib_node_registration_t igmp_timer_process_node;
258 extern vlib_node_registration_t igmp_input_node;
259 extern vlib_node_registration_t igmp_parse_query_node;
260 extern vlib_node_registration_t igmp_parse_report_node;
262 /** \brief igmp listen
263 @param vm - vlib main
264 @param enable - 0 == remove (S,G), else add (S,G)
265 @param sw_if_index - interface sw_if_index
266 @param saddr - source address
267 @param gaddr - group address
268 @param cli_api_configured - if zero, an igmp report has been received on interface
270 Add/del (S,G) on an interface. If user configured,
271 send a status change report from the interface.
272 If a report was received on interface notify registered api clients.
274 int igmp_listen (vlib_main_t * vm, u8 enable, u32 sw_if_index,
275 ip46_address_t saddr, ip46_address_t gaddr,
276 u8 cli_api_configured);
278 /** \brief igmp clear config
279 @param config - igmp configuration
281 Clear all (S,G)s on specified config and remove this config from pool.
283 void igmp_clear_config (igmp_config_t * config);
285 /** \brief igmp clear group
286 @param config - igmp configuration
287 @param group - the group to be removed
289 Remove this group from interface (specified by configuration).
291 void igmp_clear_group (igmp_config_t * config, igmp_group_t * group);
293 /** \brief igmp sort timers
294 @param timers - pool of igmp timers
296 Sort igmp timers, so that the first to expire is at end.
298 void igmp_sort_timers (igmp_timer_t * timers);
300 /** \brief igmp create int timer
301 @param time - expiration time (at this time the timer will expire)
302 @param sw_if_index - interface sw_if_index
303 @param func - function to all after timer expiration
306 Creates new interface timer. Delayed reports, query msg, query resp.
308 void igmp_create_int_timer (f64 time, u32 sw_if_index,
309 igmp_timer_function_t * func);
311 /** \brief igmp create group timer
312 @param time - expiration time (at this time the timer will expire)
313 @param sw_if_index - interface sw_if_index
314 @param gkey - key to find the group by
315 @param func - function to all after timer expiration
317 Creates new group timer.
319 void igmp_create_group_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
320 igmp_timer_function_t * func);
322 /** \brief igmp create group timer
323 @param time - expiration time (at this time the timer will expire)
324 @param sw_if_index - interface sw_if_index
325 @param gkey - key to find the group by
326 @param skey - key to find the source by
327 @param func - function to all after timer expiration
329 Creates new source timer.
331 void igmp_create_src_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
332 igmp_key_t * skey, igmp_timer_function_t * func);
334 /** \brief igmp send query (igmp_timer_function_t)
337 If the timer holds group key, send Group-Specific query,
338 else send General query.
340 void igmp_send_query (vlib_main_t * vm, vlib_node_runtime_t * rt,
341 igmp_main_t * im, igmp_timer_t * timer);
343 /** \brief igmp query response expiration (igmp_timer_function_t)
345 If a response to a query didn't come in time, remove (S,G)s.
347 void igmp_query_resp_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
348 igmp_main_t * im, igmp_timer_t * timer);
350 /** \brief igmp send report (igmp_timer_function_t)
352 Send igmp membership report.
354 void igmp_send_report (vlib_main_t * vm, vlib_node_runtime_t * rt,
355 igmp_main_t * im, igmp_timer_t * timer);
357 /** \brief igmp send state changed (igmp_timer_function_t)
359 Send report if an (S,G) filter has changed.
361 void igmp_send_state_changed (vlib_main_t * vm, vlib_node_runtime_t * rt,
362 igmp_main_t * im, igmp_timer_t * timer);
364 /** \brief igmp source expiration (igmp_timer_function_t)
366 Remove expired (S,G) from group.
368 void igmp_src_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
369 igmp_main_t * im, igmp_timer_t * timer);
371 static inline igmp_type_info_t *
372 igmp_get_type_info (igmp_main_t * im, u32 type)
376 p = hash_get (im->type_info_by_type, type);
377 return p ? vec_elt_at_index (im->type_infos, p[0]) : 0;
380 static inline igmp_report_type_info_t *
381 igmp_get_report_type_info (igmp_main_t * im, u8 report_type)
385 p = hash_get (im->report_type_info_by_report_type, report_type);
386 return p ? vec_elt_at_index (im->report_type_infos, p[0]) : 0;
389 /** \brief igmp event
390 @param im - igmp main
391 @param config - igmp configuration
392 @param group - igmp group
395 Notify registered api clients of (S,G) filter update.
397 void igmp_event (igmp_main_t * im, igmp_config_t * config,
398 igmp_group_t * group, igmp_src_t * src);
402 IGMP_NEXT_IP4_REWRITE_MCAST_NODE,
403 IGMP_NEXT_IP6_REWRITE_MCAST_NODE,
407 /** \brief igmp config lookup
408 @param im - igmp main
409 @param sw_if_index - interface sw_if_index
411 always_inline igmp_config_t *
412 igmp_config_lookup (igmp_main_t * im, u32 sw_if_index)
415 igmp_config_t *config = NULL;
417 p = hash_get_mem (im->igmp_config_by_sw_if_index, &sw_if_index);
419 config = vec_elt_at_index (im->configs, p[0]);
424 /** \brief igmp group lookup
425 @param config - igmp configuration
426 @param key - igmp key
428 always_inline igmp_group_t *
429 igmp_group_lookup (igmp_config_t * config, igmp_key_t * key)
432 igmp_group_t *group = NULL;
436 p = hash_get_mem (config->igmp_group_by_key, key);
438 group = vec_elt_at_index (config->groups, p[0]);
443 /** \brief igmp group lookup
444 @param group - igmp group
445 @param key - igmp key
447 always_inline igmp_src_t *
448 igmp_src_lookup (igmp_group_t * group, igmp_key_t * key)
451 igmp_src_t *src = NULL;
455 p = hash_get_mem (group->igmp_src_by_key, key);
457 src = vec_elt_at_index (group->srcs, p[0]);
462 /** \brief igmp group lookup
463 @param im - igmp main
464 @param client_index - client index
466 always_inline igmp_api_client_t *
467 igmp_api_client_lookup (igmp_main_t * im, u32 client_index)
470 igmp_api_client_t *api_client = NULL;
472 p = hash_get_mem (im->igmp_api_client_by_client_index, &client_index);
474 api_client = vec_elt_at_index (im->api_clients, p[0]);
479 #endif /* _IGMP_H_ */
482 * fd.io coding-style-patch-verification: ON
485 * eval: (c-set-style "gnu")