igmp: disable debug messages
[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 <vnet/ip/igmp_packet.h>
24 #include <vnet/adj/adj_mcast.h>
25 #include <igmp/igmp_format.h>
26
27 #define IGMP_QUERY_TIMER                        (60)
28 #define IGMP_SRC_TIMER                          (3 * IGMP_QUERY_TIMER)
29 #define IGMP_DEFAULT_ROBUSTNESS_VARIABLE        (2)
30
31 #define ENABLE_IGMP_DBG 0
32
33 #if ENABLE_IGMP_DBG == 1
34 #define IGMP_DBG(...) clib_warning(__VA_ARGS__)
35 #else
36 #define IGMP_DBG(...)
37 #endif /* ENABLE_IGMP_DBG */
38
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)
43
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))
46
47 enum
48 {
49   IGMP_PROCESS_EVENT_UPDATE_TIMER = 1,
50 } igmp_process_event_t;
51
52 /*! Igmp versions */
53 typedef enum
54 {
55   IGMP_V1,
56   IGMP_V2,
57   IGMP_V3,
58 } igmp_ver_t;
59
60 struct igmp_config_t_;
61
62 typedef struct igmp_config_t_ igmp_config_t;
63
64 struct igmp_group_t_;
65
66 typedef struct igmp_group_t_ igmp_group_t;
67
68 /** \brief create message
69     @param b - vlib buffer
70     @param config - igmp configuration
71     @param group - igmp group
72
73     Populate supplied bufefr with IGMP message.
74 */
75 typedef void (create_msg_t) (vlib_buffer_t * b, igmp_config_t * config,
76                              igmp_group_t * group);
77
78 /** \brief igmp key
79     @param data - key data
80     @param group_type - membership group type
81 */
82 typedef struct
83 {
84   u64 data[2];                  /*!< ip46_address_t.as_u64 */
85   u64 group_type;               /*!< zero in case of source key */
86 } igmp_key_t;
87
88 /** \brief igmp source
89     @param addr - ip4/6 source address
90     @param exp_time - expiration time
91     @param key - pointer to key
92 */
93 typedef struct
94 {
95   ip46_address_t addr;
96
97   f64 exp_time;
98
99   igmp_key_t *key;
100 } igmp_src_t;
101
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
111 */
112 typedef struct igmp_group_t_
113 {
114   ip46_address_t addr;
115
116   f64 exp_time;
117
118   igmp_key_t *key;
119
120   igmp_membership_group_v3_type_t type;
121
122   u16 n_srcs;
123
124   u8 flags;
125 /** reponse to query was received */
126 #define IGMP_GROUP_FLAG_QUERY_RESP_RECVED       (1 << 0)
127
128   uword *igmp_src_by_key;
129   igmp_src_t *srcs;
130 } igmp_group_t;
131
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
142 */
143 typedef struct igmp_config_t_
144 {
145   u32 sw_if_index;
146
147   adj_index_t adj_index;
148
149   u8 cli_api_configured;
150
151   create_msg_t *next_create_msg;
152
153   igmp_ver_t igmp_ver;
154
155   u8 robustness_var;
156
157   u8 flags;
158 #define IGMP_CONFIG_FLAG_QUERY_RESP_RECVED      (1 << 0)
159 #define IGMP_CONFIG_FLAG_CAN_SEND_REPORT        (1 << 1)
160
161   uword *igmp_group_by_key;
162
163   igmp_group_t *groups;
164 } igmp_config_t;
165
166 struct igmp_timer_t_;
167
168 typedef struct igmp_timer_t_ igmp_timer_t;
169
170 /** \brief igmp api client
171     @param client_index - client index
172     @param pid - pid
173 */
174 typedef struct igmp_api_client_t_
175 {
176   u32 client_index;
177   u32 pid;
178 } igmp_api_client_t;
179
180 typedef struct
181 {
182   u8 *name;
183   igmp_type_t type;
184 } igmp_type_info_t;
185
186 typedef struct
187 {
188   u8 *name;
189   igmp_membership_group_v3_type_t type;
190 } igmp_report_type_info_t;
191
192 /** \brief igmp main
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
206 */
207 typedef struct igmp_main_t_
208 {
209   u16 msg_id_base;
210
211   uword *igmp_api_client_by_client_index;
212
213   igmp_api_client_t *api_clients;
214
215   uword *igmp_config_by_sw_if_index;
216
217   igmp_config_t *configs;
218
219   u32 **buffers;
220
221   igmp_timer_t *timers;
222
223   igmp_type_info_t *type_infos;
224   igmp_report_type_info_t *report_type_infos;
225
226   uword *type_info_by_type;
227   uword *report_type_info_by_report_type;
228 } igmp_main_t;
229
230 extern igmp_main_t igmp_main;
231
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
237 */
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);
241
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
247 */
248 typedef struct igmp_timer_t_
249 {
250   f64 exp_time;
251   igmp_timer_function_t *func;
252
253   u32 sw_if_index;
254   void *data;
255 } igmp_timer_t;
256
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;
261
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
269
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.
273 */
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);
277
278 /** \brief igmp clear config
279     @param config - igmp configuration
280
281     Clear all (S,G)s on specified config and remove this config from pool.
282 */
283 void igmp_clear_config (igmp_config_t * config);
284
285 /** \brief igmp clear group
286     @param config - igmp configuration
287     @param group - the group to be removed
288
289     Remove this group from interface (specified by configuration).
290 */
291 void igmp_clear_group (igmp_config_t * config, igmp_group_t * group);
292
293 /** \brief igmp sort timers
294     @param timers - pool of igmp timers
295
296     Sort igmp timers, so that the first to expire is at end.
297 */
298 void igmp_sort_timers (igmp_timer_t * timers);
299
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
304
305
306     Creates new interface timer. Delayed reports, query msg, query resp.
307 */
308 void igmp_create_int_timer (f64 time, u32 sw_if_index,
309                             igmp_timer_function_t * func);
310
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
316
317     Creates new group timer.
318 */
319 void igmp_create_group_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
320                               igmp_timer_function_t * func);
321
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
328
329     Creates new source timer.
330 */
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);
333
334 /** \brief igmp send query (igmp_timer_function_t)
335
336     Send an igmp query.
337     If the timer holds group key, send Group-Specific query,
338     else send General query.
339 */
340 void igmp_send_query (vlib_main_t * vm, vlib_node_runtime_t * rt,
341                       igmp_main_t * im, igmp_timer_t * timer);
342
343 /** \brief igmp query response expiration (igmp_timer_function_t)
344
345     If a response to a query didn't come in time, remove (S,G)s.
346 */
347 void igmp_query_resp_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
348                           igmp_main_t * im, igmp_timer_t * timer);
349
350 /** \brief igmp send report (igmp_timer_function_t)
351
352     Send igmp membership report.
353 */
354 void igmp_send_report (vlib_main_t * vm, vlib_node_runtime_t * rt,
355                        igmp_main_t * im, igmp_timer_t * timer);
356
357 /** \brief igmp send state changed (igmp_timer_function_t)
358
359     Send report if an (S,G) filter has changed.
360 */
361 void igmp_send_state_changed (vlib_main_t * vm, vlib_node_runtime_t * rt,
362                               igmp_main_t * im, igmp_timer_t * timer);
363
364 /** \brief igmp source expiration (igmp_timer_function_t)
365
366     Remove expired (S,G) from group.
367 */
368 void igmp_src_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
369                    igmp_main_t * im, igmp_timer_t * timer);
370
371 static inline igmp_type_info_t *
372 igmp_get_type_info (igmp_main_t * im, u32 type)
373 {
374   uword *p;
375
376   p = hash_get (im->type_info_by_type, type);
377   return p ? vec_elt_at_index (im->type_infos, p[0]) : 0;
378 }
379
380 static inline igmp_report_type_info_t *
381 igmp_get_report_type_info (igmp_main_t * im, u8 report_type)
382 {
383   uword *p;
384
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;
387 }
388
389 /** \brief igmp event
390     @param im - igmp main
391     @param config - igmp configuration
392     @param group - igmp group
393     @param src - source
394
395     Notify registered api clients of (S,G) filter update.
396 */
397 void igmp_event (igmp_main_t * im, igmp_config_t * config,
398                  igmp_group_t * group, igmp_src_t * src);
399
400 typedef enum
401 {
402   IGMP_NEXT_IP4_REWRITE_MCAST_NODE,
403   IGMP_NEXT_IP6_REWRITE_MCAST_NODE,
404   IGMP_N_NEXT,
405 } igmp_next_t;
406
407 /** \brief igmp config lookup
408     @param im - igmp main
409     @param sw_if_index - interface sw_if_index
410 */
411 always_inline igmp_config_t *
412 igmp_config_lookup (igmp_main_t * im, u32 sw_if_index)
413 {
414   uword *p;
415   igmp_config_t *config = NULL;
416
417   p = hash_get_mem (im->igmp_config_by_sw_if_index, &sw_if_index);
418   if (p)
419     config = vec_elt_at_index (im->configs, p[0]);
420
421   return config;
422 }
423
424 /** \brief igmp group lookup
425     @param config - igmp configuration
426     @param key - igmp key
427 */
428 always_inline igmp_group_t *
429 igmp_group_lookup (igmp_config_t * config, igmp_key_t * key)
430 {
431   uword *p;
432   igmp_group_t *group = NULL;
433   if (!config)
434     return NULL;
435
436   p = hash_get_mem (config->igmp_group_by_key, key);
437   if (p)
438     group = vec_elt_at_index (config->groups, p[0]);
439
440   return group;
441 }
442
443 /** \brief igmp group lookup
444     @param group - igmp group
445     @param key - igmp key
446 */
447 always_inline igmp_src_t *
448 igmp_src_lookup (igmp_group_t * group, igmp_key_t * key)
449 {
450   uword *p;
451   igmp_src_t *src = NULL;
452   if (!group)
453     return NULL;
454
455   p = hash_get_mem (group->igmp_src_by_key, key);
456   if (p)
457     src = vec_elt_at_index (group->srcs, p[0]);
458
459   return src;
460 }
461
462 /** \brief igmp group lookup
463     @param im - igmp main
464     @param client_index - client index
465 */
466 always_inline igmp_api_client_t *
467 igmp_api_client_lookup (igmp_main_t * im, u32 client_index)
468 {
469   uword *p;
470   igmp_api_client_t *api_client = NULL;
471
472   p = hash_get_mem (im->igmp_api_client_by_client_index, &client_index);
473   if (p)
474     api_client = vec_elt_at_index (im->api_clients, p[0]);
475
476   return api_client;
477 }
478
479 #endif /* _IGMP_H_ */
480
481 /*
482  * fd.io coding-style-patch-verification: ON
483  *
484  * Local Variables:
485  * eval: (c-set-style "gnu")
486  * End:
487  */