Add reaper functions to want events APIs (VPP-1304)
[vpp.git] / src / plugins / igmp / igmp.h
1 /*
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:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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  *------------------------------------------------------------------
16  */
17
18 #ifndef _IGMP_H_
19 #define _IGMP_H_
20
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>
27
28 #define IGMP_QUERY_TIMER                        (60)
29 #define IGMP_SRC_TIMER                          (3 * IGMP_QUERY_TIMER)
30 #define IGMP_DEFAULT_ROBUSTNESS_VARIABLE        (2)
31
32 #define ENABLE_IGMP_DBG 0
33
34 #if ENABLE_IGMP_DBG == 1
35 #define IGMP_DBG(...) clib_warning(__VA_ARGS__)
36 #else
37 #define IGMP_DBG(...)
38 #endif /* ENABLE_IGMP_DBG */
39
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)
44
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))
47
48 enum
49 {
50   IGMP_PROCESS_EVENT_UPDATE_TIMER = 1,
51 } igmp_process_event_t;
52
53 /*! Igmp versions */
54 typedef enum
55 {
56   IGMP_V1,
57   IGMP_V2,
58   IGMP_V3,
59 } igmp_ver_t;
60
61 struct igmp_config_t_;
62
63 typedef struct igmp_config_t_ igmp_config_t;
64
65 struct igmp_group_t_;
66
67 typedef struct igmp_group_t_ igmp_group_t;
68
69 /** \brief create message
70     @param b - vlib buffer
71     @param config - igmp configuration
72     @param group - igmp group
73
74     Populate supplied bufefr with IGMP message.
75 */
76 typedef void (create_msg_t) (vlib_buffer_t * b, igmp_config_t * config,
77                              igmp_group_t * group);
78
79 /** \brief igmp key
80     @param data - key data
81     @param group_type - membership group type
82 */
83 typedef struct
84 {
85   u64 data[2];                  /*!< ip46_address_t.as_u64 */
86   u64 group_type;               /*!< zero in case of source key */
87 } igmp_key_t;
88
89 /** \brief igmp source
90     @param addr - ip4/6 source address
91     @param exp_time - expiration time
92     @param key - pointer to key
93 */
94 typedef struct
95 {
96   ip46_address_t addr;
97
98   f64 exp_time;
99
100   igmp_key_t *key;
101 } igmp_src_t;
102
103 /** \brief igmp group
104     @param addr - ip4/6 group address
105     @param exp_time - expiration time
106     @param key - pointer to key
107     @param type - membership group type
108     @param n_srcs - number of sources
109     @param flags - igmp group flags
110     @param igmp_src_by_key - source by key hash
111     @param srcs - pool of sources
112 */
113 typedef struct igmp_group_t_
114 {
115   ip46_address_t addr;
116
117   f64 exp_time;
118
119   igmp_key_t *key;
120
121   igmp_membership_group_v3_type_t type;
122
123   u16 n_srcs;
124
125   u8 flags;
126 /** reponse to query was received */
127 #define IGMP_GROUP_FLAG_QUERY_RESP_RECVED       (1 << 0)
128
129   uword *igmp_src_by_key;
130   igmp_src_t *srcs;
131 } igmp_group_t;
132
133 /** \brief igmp configuration
134     @param sw_if_index - interface sw_if_index
135     @param adj_index - adjacency index
136     @param cli_api_configured - if zero, an igmp report was received
137     @param next_create_msg - specify next igmp message
138     @param igmp_ver - igmp version
139     @param robustness_var - robustness variable
140     @param flags - igmp configuration falgs
141     @param igmp_group_by_key - group by key hash
142     @param groups - pool of groups
143 */
144 typedef struct igmp_config_t_
145 {
146   u32 sw_if_index;
147
148   adj_index_t adj_index;
149
150   u8 cli_api_configured;
151
152   create_msg_t *next_create_msg;
153
154   igmp_ver_t igmp_ver;
155
156   u8 robustness_var;
157
158   u8 flags;
159 #define IGMP_CONFIG_FLAG_QUERY_RESP_RECVED      (1 << 0)
160 #define IGMP_CONFIG_FLAG_CAN_SEND_REPORT        (1 << 1)
161
162   uword *igmp_group_by_key;
163
164   igmp_group_t *groups;
165 } igmp_config_t;
166
167 struct igmp_timer_t_;
168
169 typedef struct igmp_timer_t_ igmp_timer_t;
170
171 typedef struct
172 {
173   u8 *name;
174   igmp_type_t type;
175 } igmp_type_info_t;
176
177 typedef struct
178 {
179   u8 *name;
180   igmp_membership_group_v3_type_t type;
181 } igmp_report_type_info_t;
182
183 /** \brief igmp main
184     @param msg_id_base - API message ID base
185     @param igmp_api_client_by_client_index - get api client by client_index
186     @param api_clients -  pool of api clients registered for join/leave notifications
187     @param igmp_config_by_sw_if_index - get config index by config key
188     @param configs - pool of igmp configurations
189     @param buffers - buffer cache
190     @param timers - pool of igmp timers
191     @param type_infos - igmp type info
192     @param report_type_infos - igmp report type info
193     @param type_info_by_type -
194     @param report_type_info_by_report_type -
195     @param general_query_address - 224.0.0.1
196     @param membership_report_address - 224.0.0.22
197 */
198 typedef struct igmp_main_t_
199 {
200   u16 msg_id_base;
201
202   uword *igmp_api_client_by_client_index;
203
204   vpe_client_registration_t *api_clients;
205
206   uword *igmp_config_by_sw_if_index;
207
208   igmp_config_t *configs;
209
210   u32 **buffers;
211
212   igmp_timer_t *timers;
213
214   igmp_type_info_t *type_infos;
215   igmp_report_type_info_t *report_type_infos;
216
217   uword *type_info_by_type;
218   uword *report_type_info_by_report_type;
219 } igmp_main_t;
220
221 extern igmp_main_t igmp_main;
222
223 /** \brief igmp timer function
224     @param vm - vlib main
225     @param rt - vlib runtime node
226     @param im - igmp main
227     @param timer - igmp timer
228 */
229 typedef void (igmp_timer_function_t) (vlib_main_t * vm,
230                                       vlib_node_runtime_t * rt,
231                                       igmp_main_t * im, igmp_timer_t * timer);
232
233 /** \brief igmp timer
234     @param exp_time - expiration time
235     @param func - function to call on timer expiration
236     @param sw_if_index - interface sw_if_index
237     @param data - custom data
238 */
239 typedef struct igmp_timer_t_
240 {
241   f64 exp_time;
242   igmp_timer_function_t *func;
243
244   u32 sw_if_index;
245   void *data;
246 } igmp_timer_t;
247
248 extern vlib_node_registration_t igmp_timer_process_node;
249 extern vlib_node_registration_t igmp_input_node;
250 extern vlib_node_registration_t igmp_parse_query_node;
251 extern vlib_node_registration_t igmp_parse_report_node;
252
253 /** \brief igmp listen
254     @param vm - vlib main
255     @param enable - 0 == remove (S,G), else add (S,G)
256     @param sw_if_index - interface sw_if_index
257     @param saddr - source address
258     @param gaddr - group address
259     @param cli_api_configured - if zero, an igmp report has been received on interface
260
261     Add/del (S,G) on an interface. If user configured,
262     send a status change report from the interface.
263     If a report was received on interface notify registered api clients.
264 */
265 int igmp_listen (vlib_main_t * vm, u8 enable, u32 sw_if_index,
266                  ip46_address_t saddr, ip46_address_t gaddr,
267                  u8 cli_api_configured);
268
269 /** \brief igmp clear config
270     @param config - igmp configuration
271
272     Clear all (S,G)s on specified config and remove this config from pool.
273 */
274 void igmp_clear_config (igmp_config_t * config);
275
276 /** \brief igmp clear group
277     @param config - igmp configuration
278     @param group - the group to be removed
279
280     Remove this group from interface (specified by configuration).
281 */
282 void igmp_clear_group (igmp_config_t * config, igmp_group_t * group);
283
284 /** \brief igmp sort timers
285     @param timers - pool of igmp timers
286
287     Sort igmp timers, so that the first to expire is at end.
288 */
289 void igmp_sort_timers (igmp_timer_t * timers);
290
291 /** \brief igmp create int timer
292     @param time - expiration time (at this time the timer will expire)
293     @param sw_if_index - interface sw_if_index
294     @param func - function to all after timer expiration
295
296
297     Creates new interface timer. Delayed reports, query msg, query resp.
298 */
299 void igmp_create_int_timer (f64 time, u32 sw_if_index,
300                             igmp_timer_function_t * func);
301
302 /** \brief igmp create group timer
303     @param time - expiration time (at this time the timer will expire)
304     @param sw_if_index - interface sw_if_index
305     @param gkey - key to find the group by
306     @param func - function to all after timer expiration
307
308     Creates new group timer.
309 */
310 void igmp_create_group_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
311                               igmp_timer_function_t * func);
312
313 /** \brief igmp create group timer
314     @param time - expiration time (at this time the timer will expire)
315     @param sw_if_index - interface sw_if_index
316     @param gkey - key to find the group by
317     @param skey - key to find the source by
318     @param func - function to all after timer expiration
319
320     Creates new source timer.
321 */
322 void igmp_create_src_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
323                             igmp_key_t * skey, igmp_timer_function_t * func);
324
325 /** \brief igmp send query (igmp_timer_function_t)
326
327     Send an igmp query.
328     If the timer holds group key, send Group-Specific query,
329     else send General query.
330 */
331 void igmp_send_query (vlib_main_t * vm, vlib_node_runtime_t * rt,
332                       igmp_main_t * im, igmp_timer_t * timer);
333
334 /** \brief igmp query response expiration (igmp_timer_function_t)
335
336     If a response to a query didn't come in time, remove (S,G)s.
337 */
338 void igmp_query_resp_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
339                           igmp_main_t * im, igmp_timer_t * timer);
340
341 /** \brief igmp send report (igmp_timer_function_t)
342
343     Send igmp membership report.
344 */
345 void igmp_send_report (vlib_main_t * vm, vlib_node_runtime_t * rt,
346                        igmp_main_t * im, igmp_timer_t * timer);
347
348 /** \brief igmp send state changed (igmp_timer_function_t)
349
350     Send report if an (S,G) filter has changed.
351 */
352 void igmp_send_state_changed (vlib_main_t * vm, vlib_node_runtime_t * rt,
353                               igmp_main_t * im, igmp_timer_t * timer);
354
355 /** \brief igmp source expiration (igmp_timer_function_t)
356
357     Remove expired (S,G) from group.
358 */
359 void igmp_src_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
360                    igmp_main_t * im, igmp_timer_t * timer);
361
362 static inline igmp_type_info_t *
363 igmp_get_type_info (igmp_main_t * im, u32 type)
364 {
365   uword *p;
366
367   p = hash_get (im->type_info_by_type, type);
368   return p ? vec_elt_at_index (im->type_infos, p[0]) : 0;
369 }
370
371 static inline igmp_report_type_info_t *
372 igmp_get_report_type_info (igmp_main_t * im, u8 report_type)
373 {
374   uword *p;
375
376   p = hash_get (im->report_type_info_by_report_type, report_type);
377   return p ? vec_elt_at_index (im->report_type_infos, p[0]) : 0;
378 }
379
380 /** \brief igmp event
381     @param im - igmp main
382     @param config - igmp configuration
383     @param group - igmp group
384     @param src - source
385
386     Notify registered api clients of (S,G) filter update.
387 */
388 void igmp_event (igmp_main_t * im, igmp_config_t * config,
389                  igmp_group_t * group, igmp_src_t * src);
390
391 typedef enum
392 {
393   IGMP_NEXT_IP4_REWRITE_MCAST_NODE,
394   IGMP_NEXT_IP6_REWRITE_MCAST_NODE,
395   IGMP_N_NEXT,
396 } igmp_next_t;
397
398 /** \brief igmp config lookup
399     @param im - igmp main
400     @param sw_if_index - interface sw_if_index
401 */
402 always_inline igmp_config_t *
403 igmp_config_lookup (igmp_main_t * im, u32 sw_if_index)
404 {
405   uword *p;
406   igmp_config_t *config = NULL;
407
408   p = hash_get_mem (im->igmp_config_by_sw_if_index, &sw_if_index);
409   if (p)
410     config = vec_elt_at_index (im->configs, p[0]);
411
412   return config;
413 }
414
415 /** \brief igmp group lookup
416     @param config - igmp configuration
417     @param key - igmp key
418 */
419 always_inline igmp_group_t *
420 igmp_group_lookup (igmp_config_t * config, igmp_key_t * key)
421 {
422   uword *p;
423   igmp_group_t *group = NULL;
424   if (!config)
425     return NULL;
426
427   p = hash_get_mem (config->igmp_group_by_key, key);
428   if (p)
429     group = vec_elt_at_index (config->groups, p[0]);
430
431   return group;
432 }
433
434 /** \brief igmp group lookup
435     @param group - igmp group
436     @param key - igmp key
437 */
438 always_inline igmp_src_t *
439 igmp_src_lookup (igmp_group_t * group, igmp_key_t * key)
440 {
441   uword *p;
442   igmp_src_t *src = NULL;
443   if (!group)
444     return NULL;
445
446   p = hash_get_mem (group->igmp_src_by_key, key);
447   if (p)
448     src = vec_elt_at_index (group->srcs, p[0]);
449
450   return src;
451 }
452
453 #endif /* _IGMP_H_ */
454
455 /*
456  * fd.io coding-style-patch-verification: ON
457  *
458  * Local Variables:
459  * eval: (c-set-style "gnu")
460  * End:
461  */