b8759ffa3b1cf948dc03fe26427dae05614d55cc
[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 #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")
52
53 typedef enum
54 {
55 #define _(a,b,c) IGMP_CONFIG_FLAG_##b = (1 << a),
56   foreach_igmp_config_flag
57 #undef _
58 } igmp_config_flag_t;
59
60 enum
61 {
62   IGMP_PROCESS_EVENT_UPDATE_TIMER = 1,
63 } igmp_process_event_t;
64
65 /*! Igmp versions */
66 typedef enum
67 {
68   IGMP_V1,
69   IGMP_V2,
70   IGMP_V3,
71 } igmp_ver_t;
72
73 struct igmp_config_t_;
74
75 typedef struct igmp_config_t_ igmp_config_t;
76
77 struct igmp_group_t_;
78
79 typedef struct igmp_group_t_ igmp_group_t;
80
81 /** \brief create message
82     @param b - vlib buffer
83     @param config - igmp configuration
84     @param group - igmp group
85
86     Populate supplied bufefr with IGMP message.
87 */
88 typedef void (create_msg_t) (vlib_buffer_t * b, igmp_config_t * config,
89                              igmp_group_t * group);
90
91 /** \brief igmp key
92     @param data - key data
93     @param group_type - membership group type
94 */
95 typedef struct
96 {
97   u64 data[2];                  /*!< ip46_address_t.as_u64 */
98   u64 group_type;               /*!< zero in case of source key */
99 } igmp_key_t;
100
101 /** \brief igmp source
102     @param addr - ip4/6 source address
103     @param exp_time - expiration time
104     @param key - pointer to key
105 */
106 typedef struct
107 {
108   ip46_address_t addr;
109
110   f64 exp_time;
111
112   igmp_key_t *key;
113 } igmp_src_t;
114
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
124 */
125 typedef struct igmp_group_t_
126 {
127   ip46_address_t addr;
128
129   f64 exp_time;
130
131   igmp_key_t *key;
132
133   igmp_membership_group_v3_type_t type;
134
135   u16 n_srcs;
136
137   u8 flags;
138 /** reponse to query was received */
139 #define IGMP_GROUP_FLAG_QUERY_RESP_RECVED       (1 << 0)
140
141   uword *igmp_src_by_key;
142   igmp_src_t *srcs;
143 } igmp_group_t;
144
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
154 */
155 typedef struct igmp_config_t_
156 {
157   u32 sw_if_index;
158
159   adj_index_t adj_index;
160
161   create_msg_t *next_create_msg;
162
163   igmp_ver_t igmp_ver;
164
165   u8 robustness_var;
166
167   u8 flags;
168
169   uword *igmp_group_by_key;
170
171   igmp_group_t *groups;
172 } igmp_config_t;
173
174 struct igmp_timer_t_;
175
176 typedef struct igmp_timer_t_ igmp_timer_t;
177
178 typedef struct
179 {
180   u8 *name;
181   igmp_type_t type;
182 } igmp_type_info_t;
183
184 typedef struct
185 {
186   u8 *name;
187   igmp_membership_group_v3_type_t type;
188 } igmp_report_type_info_t;
189
190 /** \brief igmp main
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
204 */
205 typedef struct igmp_main_t_
206 {
207   u16 msg_id_base;
208
209   uword *igmp_api_client_by_client_index;
210
211   vpe_client_registration_t *api_clients;
212
213   uword *igmp_config_by_sw_if_index;
214
215   igmp_config_t *configs;
216
217   igmp_timer_t *timers;
218
219   igmp_type_info_t *type_infos;
220   igmp_report_type_info_t *report_type_infos;
221
222   uword *type_info_by_type;
223   uword *report_type_info_by_report_type;
224 } igmp_main_t;
225
226 extern igmp_main_t igmp_main;
227
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
233 */
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);
237
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
243 */
244 typedef struct igmp_timer_t_
245 {
246   f64 exp_time;
247   igmp_timer_function_t *func;
248
249   u32 sw_if_index;
250   void *data;
251 } igmp_timer_t;
252
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;
257
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
265
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.
269 */
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);
272
273 /** \brief igmp clear config
274     @param config - igmp configuration
275
276     Clear all (S,G)s on specified config and remove this config from pool.
277 */
278 void igmp_clear_config (igmp_config_t * config);
279
280 /** \brief igmp clear group
281     @param config - igmp configuration
282     @param group - the group to be removed
283
284     Remove this group from interface (specified by configuration).
285 */
286 void igmp_clear_group (igmp_config_t * config, igmp_group_t * group);
287
288 /** \brief igmp sort timers
289     @param timers - pool of igmp timers
290
291     Sort igmp timers, so that the first to expire is at end.
292 */
293 void igmp_sort_timers (igmp_timer_t * timers);
294
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
299
300
301     Creates new interface timer. Delayed reports, query msg, query resp.
302 */
303 void igmp_create_int_timer (f64 time, u32 sw_if_index,
304                             igmp_timer_function_t * func);
305
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
311
312     Creates new group timer.
313 */
314 void igmp_create_group_timer (f64 time, u32 sw_if_index, igmp_key_t * gkey,
315                               igmp_timer_function_t * func);
316
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
323
324     Creates new source timer.
325 */
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);
328
329 /** \brief igmp send query (igmp_timer_function_t)
330
331     Send an igmp query.
332     If the timer holds group key, send Group-Specific query,
333     else send General query.
334 */
335 void igmp_send_query (vlib_main_t * vm, vlib_node_runtime_t * rt,
336                       igmp_main_t * im, igmp_timer_t * timer);
337
338 /** \brief igmp query response expiration (igmp_timer_function_t)
339
340     If a response to a query didn't come in time, remove (S,G)s.
341 */
342 void igmp_query_resp_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
343                           igmp_main_t * im, igmp_timer_t * timer);
344
345 /** \brief igmp send report (igmp_timer_function_t)
346
347     Send igmp membership report.
348 */
349 void igmp_send_report (vlib_main_t * vm, vlib_node_runtime_t * rt,
350                        igmp_main_t * im, igmp_timer_t * timer);
351
352 /** \brief igmp send state changed (igmp_timer_function_t)
353
354     Send report if an (S,G) filter has changed.
355 */
356 void igmp_send_state_changed (vlib_main_t * vm, vlib_node_runtime_t * rt,
357                               igmp_main_t * im, igmp_timer_t * timer);
358
359 /** \brief igmp source expiration (igmp_timer_function_t)
360
361     Remove expired (S,G) from group.
362 */
363 void igmp_src_exp (vlib_main_t * vm, vlib_node_runtime_t * rt,
364                    igmp_main_t * im, igmp_timer_t * timer);
365
366 static inline igmp_type_info_t *
367 igmp_get_type_info (igmp_main_t * im, u32 type)
368 {
369   uword *p;
370
371   p = hash_get (im->type_info_by_type, type);
372   return p ? vec_elt_at_index (im->type_infos, p[0]) : 0;
373 }
374
375 static inline igmp_report_type_info_t *
376 igmp_get_report_type_info (igmp_main_t * im, u8 report_type)
377 {
378   uword *p;
379
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;
382 }
383
384 /** \brief igmp event
385     @param im - igmp main
386     @param config - igmp configuration
387     @param group - igmp group
388     @param src - source
389
390     Notify registered api clients of (S,G) filter update.
391 */
392 void igmp_event (igmp_main_t * im, igmp_config_t * config,
393                  igmp_group_t * group, igmp_src_t * src);
394
395 typedef enum
396 {
397   IGMP_NEXT_IP4_REWRITE_MCAST_NODE,
398   IGMP_NEXT_IP6_REWRITE_MCAST_NODE,
399   IGMP_N_NEXT,
400 } igmp_next_t;
401
402 /** \brief igmp config lookup
403     @param im - igmp main
404     @param sw_if_index - interface sw_if_index
405 */
406 always_inline igmp_config_t *
407 igmp_config_lookup (igmp_main_t * im, u32 sw_if_index)
408 {
409   uword *p;
410   igmp_config_t *config = NULL;
411
412   p = hash_get (im->igmp_config_by_sw_if_index, sw_if_index);
413   if (p)
414     config = vec_elt_at_index (im->configs, p[0]);
415
416   return config;
417 }
418
419 /** \brief igmp group lookup
420     @param config - igmp configuration
421     @param key - igmp key
422 */
423 always_inline igmp_group_t *
424 igmp_group_lookup (igmp_config_t * config, igmp_key_t * key)
425 {
426   uword *p;
427   igmp_group_t *group = NULL;
428   if (!config)
429     return NULL;
430
431   p = hash_get_mem (config->igmp_group_by_key, key);
432   if (p)
433     group = vec_elt_at_index (config->groups, p[0]);
434
435   return group;
436 }
437
438 /** \brief igmp group lookup
439     @param group - igmp group
440     @param key - igmp key
441 */
442 always_inline igmp_src_t *
443 igmp_src_lookup (igmp_group_t * group, igmp_key_t * key)
444 {
445   uword *p;
446   igmp_src_t *src = NULL;
447   if (!group)
448     return NULL;
449
450   p = hash_get_mem (group->igmp_src_by_key, key);
451   if (p)
452     src = vec_elt_at_index (group->srcs, p[0]);
453
454   return src;
455 }
456
457 #endif /* _IGMP_H_ */
458
459 /*
460  * fd.io coding-style-patch-verification: ON
461  *
462  * Local Variables:
463  * eval: (c-set-style "gnu")
464  * End:
465  */