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 <vlibapi/api_helper_macros.h>
24 #include <vnet/ip/igmp_packet.h>
25 #include <vnet/adj/adj_mcast.h>
26 #include <igmp/igmp_format.h>
28 #define IGMP_QUERY_TIMER (60)
29 #define IGMP_SRC_TIMER (3 * IGMP_QUERY_TIMER)
30 #define IGMP_DEFAULT_ROBUSTNESS_VARIABLE (2)
32 #define ENABLE_IGMP_DBG 0
34 #if ENABLE_IGMP_DBG == 1
35 #define IGMP_DBG(...) clib_warning(__VA_ARGS__)
38 #endif /* ENABLE_IGMP_DBG */
40 /** General Query address - 224.0.0.1 */
41 #define IGMP_GENERAL_QUERY_ADDRESS (0xE0000001)
42 /** Membership Report address - 224.0.0.22 */
43 #define IGMP_MEMBERSHIP_REPORT_ADDRESS (0xE0000016)
45 /** helper macro to get igmp mebership group from pointer plus offset */
46 #define group_ptr(p, l) ((igmp_membership_group_v3_t *)((char*)p + l))
48 #define foreach_igmp_config_flag \
49 _(0, QUERY_RESP_RECVED, "query_response_received") \
50 _(1, CAN_SEND_REPORT, "can_send_report") \
51 _(2, CLI_API_CONFIGURED, "cli/api")
55 #define _(a,b,c) IGMP_CONFIG_FLAG_##b = (1 << a),
56 foreach_igmp_config_flag
62 IGMP_PROCESS_EVENT_UPDATE_TIMER = 1,
63 } igmp_process_event_t;
73 struct igmp_config_t_;
75 typedef struct igmp_config_t_ igmp_config_t;
79 typedef struct igmp_group_t_ igmp_group_t;
81 /** \brief create message
82 @param b - vlib buffer
83 @param config - igmp configuration
84 @param group - igmp group
86 Populate supplied bufefr with IGMP message.
88 typedef void (create_msg_t) (vlib_buffer_t * b, igmp_config_t * config,
89 igmp_group_t * group);
92 @param data - key data
93 @param group_type - membership group type
97 u64 data[2]; /*!< ip46_address_t.as_u64 */
98 u64 group_type; /*!< zero in case of source key */
101 /** \brief igmp source
102 @param addr - ip4/6 source address
103 @param exp_time - expiration time
104 @param key - pointer to key
115 /** \brief igmp group
116 @param addr - ip4/6 group address
117 @param exp_time - expiration time
118 @param key - pointer to key
119 @param type - membership group type
120 @param n_srcs - number of sources
121 @param flags - igmp group flags
122 @param igmp_src_by_key - source by key hash
123 @param srcs - pool of sources
125 typedef struct igmp_group_t_
133 igmp_membership_group_v3_type_t type;
138 /** reponse to query was received */
139 #define IGMP_GROUP_FLAG_QUERY_RESP_RECVED (1 << 0)
141 uword *igmp_src_by_key;
145 /** \brief igmp configuration
146 @param sw_if_index - interface sw_if_index
147 @param adj_index - adjacency index
148 @param next_create_msg - specify next igmp message
149 @param igmp_ver - igmp version
150 @param robustness_var - robustness variable
151 @param flags - igmp configuration falgs
152 @param igmp_group_by_key - group by key hash
153 @param groups - pool of groups
155 typedef struct igmp_config_t_
159 adj_index_t adj_index;
161 create_msg_t *next_create_msg;
169 uword *igmp_group_by_key;
171 igmp_group_t *groups;
174 struct igmp_timer_t_;
176 typedef struct igmp_timer_t_ igmp_timer_t;
187 igmp_membership_group_v3_type_t type;
188 } igmp_report_type_info_t;
191 @param msg_id_base - API message ID base
192 @param igmp_api_client_by_client_index - get api client by client_index
193 @param api_clients - pool of api clients registered for join/leave notifications
194 @param igmp_config_by_sw_if_index - get config index by config key
195 @param configs - pool of igmp configurations
196 @param buffers - buffer cache
197 @param timers - pool of igmp timers
198 @param type_infos - igmp type info
199 @param report_type_infos - igmp report type info
200 @param type_info_by_type -
201 @param report_type_info_by_report_type -
202 @param general_query_address - 224.0.0.1
203 @param membership_report_address - 224.0.0.22
205 typedef struct igmp_main_t_
209 uword *igmp_api_client_by_client_index;
211 vpe_client_registration_t *api_clients;
213 uword *igmp_config_by_sw_if_index;
215 igmp_config_t *configs;
217 igmp_timer_t *timers;
219 igmp_type_info_t *type_infos;
220 igmp_report_type_info_t *report_type_infos;
222 uword *type_info_by_type;
223 uword *report_type_info_by_report_type;
226 extern igmp_main_t igmp_main;
228 /** \brief igmp timer function
229 @param vm - vlib main
230 @param rt - vlib runtime node
231 @param im - igmp main
232 @param timer - igmp timer
234 typedef void (igmp_timer_function_t) (vlib_main_t * vm,
235 vlib_node_runtime_t * rt,
236 igmp_main_t * im, igmp_timer_t * timer);
238 /** \brief igmp timer
239 @param exp_time - expiration time
240 @param func - function to call on timer expiration
241 @param sw_if_index - interface sw_if_index
242 @param data - custom data
244 typedef struct igmp_timer_t_
247 igmp_timer_function_t *func;
253 extern vlib_node_registration_t igmp_timer_process_node;
254 extern vlib_node_registration_t igmp_input_node;
255 extern vlib_node_registration_t igmp_parse_query_node;
256 extern vlib_node_registration_t igmp_parse_report_node;
258 /** \brief igmp listen
259 @param vm - vlib main
260 @param enable - 0 == remove (S,G), else add (S,G)
261 @param sw_if_index - interface sw_if_index
262 @param saddr - source address
263 @param gaddr - group address
264 @param flags - igmp configuration flags
266 Add/del (S,G) on an interface. If user configured,
267 send a status change report from the interface.
268 If a report was received on interface notify registered api clients.
270 int igmp_listen (vlib_main_t * vm, u8 enable, u32 sw_if_index,
271 ip46_address_t saddr, ip46_address_t gaddr, u8 flags);
273 /** \brief igmp clear config
274 @param config - igmp configuration
276 Clear all (S,G)s on specified config and remove this config from pool.
278 void igmp_clear_config (igmp_config_t * config);
280 /** \brief igmp clear group
281 @param config - igmp configuration
282 @param group - the group to be removed
284 Remove this group from interface (specified by configuration).
286 void igmp_clear_group (igmp_config_t * config, igmp_group_t * group);
288 /** \brief igmp sort timers
289 @param timers - pool of igmp timers
291 Sort igmp timers, so that the first to expire is at end.
293 void igmp_sort_timers (igmp_timer_t * timers);
295 /** \brief igmp create int timer
296 @param time - expiration time (at this time the timer will expire)
297 @param sw_if_index - interface sw_if_index
298 @param func - function to all after timer expiration
301 Creates new interface timer. Delayed reports, query msg, query resp.
303 void igmp_create_int_timer (f64 time, u32 sw_if_index,
304 igmp_timer_function_t * func);
306 /** \brief igmp create group timer
307 @param time - expiration time (at this time the timer will expire)
308 @param sw_if_index - interface sw_if_index
309 @param gkey - key to find the group by
310 @param func - function to all after timer expiration
312 Creates new group timer.
314 void igmp_create_group_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
315 igmp_timer_function_t * func);
317 /** \brief igmp create group timer
318 @param time - expiration time (at this time the timer will expire)
319 @param sw_if_index - interface sw_if_index
320 @param gkey - key to find the group by
321 @param skey - key to find the source by
322 @param func - function to all after timer expiration
324 Creates new source timer.
326 void igmp_create_src_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
327 igmp_key_t * skey, igmp_timer_function_t * func);
329 /** \brief igmp send query (igmp_timer_function_t)
332 If the timer holds group key, send Group-Specific query,
333 else send General query.
335 void igmp_send_query (vlib_main_t * vm, vlib_node_runtime_t * rt,
336 igmp_main_t * im, igmp_timer_t * timer);
338 /** \brief igmp query response expiration (igmp_timer_function_t)
340 If a response to a query didn't come in time, remove (S,G)s.
342 void igmp_query_resp_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
343 igmp_main_t * im, igmp_timer_t * timer);
345 /** \brief igmp send report (igmp_timer_function_t)
347 Send igmp membership report.
349 void igmp_send_report (vlib_main_t * vm, vlib_node_runtime_t * rt,
350 igmp_main_t * im, igmp_timer_t * timer);
352 /** \brief igmp send state changed (igmp_timer_function_t)
354 Send report if an (S,G) filter has changed.
356 void igmp_send_state_changed (vlib_main_t * vm, vlib_node_runtime_t * rt,
357 igmp_main_t * im, igmp_timer_t * timer);
359 /** \brief igmp source expiration (igmp_timer_function_t)
361 Remove expired (S,G) from group.
363 void igmp_src_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
364 igmp_main_t * im, igmp_timer_t * timer);
366 static inline igmp_type_info_t *
367 igmp_get_type_info (igmp_main_t * im, u32 type)
371 p = hash_get (im->type_info_by_type, type);
372 return p ? vec_elt_at_index (im->type_infos, p[0]) : 0;
375 static inline igmp_report_type_info_t *
376 igmp_get_report_type_info (igmp_main_t * im, u8 report_type)
380 p = hash_get (im->report_type_info_by_report_type, report_type);
381 return p ? vec_elt_at_index (im->report_type_infos, p[0]) : 0;
384 /** \brief igmp event
385 @param im - igmp main
386 @param config - igmp configuration
387 @param group - igmp group
390 Notify registered api clients of (S,G) filter update.
392 void igmp_event (igmp_main_t * im, igmp_config_t * config,
393 igmp_group_t * group, igmp_src_t * src);
397 IGMP_NEXT_IP4_REWRITE_MCAST_NODE,
398 IGMP_NEXT_IP6_REWRITE_MCAST_NODE,
402 /** \brief igmp config lookup
403 @param im - igmp main
404 @param sw_if_index - interface sw_if_index
406 always_inline igmp_config_t *
407 igmp_config_lookup (igmp_main_t * im, u32 sw_if_index)
410 igmp_config_t *config = NULL;
412 p = hash_get (im->igmp_config_by_sw_if_index, sw_if_index);
414 config = vec_elt_at_index (im->configs, p[0]);
419 /** \brief igmp group lookup
420 @param config - igmp configuration
421 @param key - igmp key
423 always_inline igmp_group_t *
424 igmp_group_lookup (igmp_config_t * config, igmp_key_t * key)
427 igmp_group_t *group = NULL;
431 p = hash_get_mem (config->igmp_group_by_key, key);
433 group = vec_elt_at_index (config->groups, p[0]);
438 /** \brief igmp group lookup
439 @param group - igmp group
440 @param key - igmp key
442 always_inline igmp_src_t *
443 igmp_src_lookup (igmp_group_t * group, igmp_key_t * key)
446 igmp_src_t *src = NULL;
450 p = hash_get_mem (group->igmp_src_by_key, key);
452 src = vec_elt_at_index (group->srcs, p[0]);
457 #endif /* _IGMP_H_ */
460 * fd.io coding-style-patch-verification: ON
463 * eval: (c-set-style "gnu")