FD.io VPP  v19.01.3-6-g70449b9b9
Vector Packet Processing
igmp_api.c
Go to the documentation of this file.
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 #include <igmp/igmp.h>
19 
20 #include <vlibapi/api.h>
21 #include <vlibmemory/api.h>
22 #include <vnet/ip/ip_types_api.h>
23 #include <igmp/igmp_ssm_range.h>
24 
25 /* define message IDs */
26 #include <igmp/igmp_msg_enum.h>
27 
28 /* define message structures */
29 #define vl_typedefs
30 #include <igmp/igmp_all_api_h.h>
31 #undef vl_typedefs
32 
33 /* define generated endian-swappers */
34 #define vl_endianfun
35 #include <igmp/igmp_all_api_h.h>
36 #undef vl_endianfun
37 
38 /* instantiate all the print functions we know about */
39 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
40 #define vl_printfun
41 #include <igmp/igmp_all_api_h.h>
42 #undef vl_printfun
43 
44 /* Get the API version number */
45 #define vl_api_version(n,v) static u32 api_version=(v);
46 #include <igmp/igmp_all_api_h.h>
47 #undef vl_api_version
48 
50 
51 #define IGMP_MSG_ID(_id) (_id + igmp_main.msg_id_base)
52 
53 #define foreach_igmp_plugin_api_msg \
54 _(IGMP_LISTEN, igmp_listen) \
55 _(IGMP_ENABLE_DISABLE, igmp_enable_disable) \
56 _(IGMP_PROXY_DEVICE_ADD_DEL, igmp_proxy_device_add_del) \
57 _(IGMP_PROXY_DEVICE_ADD_DEL_INTERFACE, igmp_proxy_device_add_del_interface) \
58 _(IGMP_DUMP, igmp_dump) \
59 _(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
60 _(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
61 _(IGMP_GROUP_PREFIX_SET, igmp_group_prefix_set) \
62 _(IGMP_GROUP_PREFIX_DUMP, igmp_group_prefix_dump) \
63 _(WANT_IGMP_EVENTS, want_igmp_events) \
64 
65 static void
67 {
69  vnet_main_t *vnm = vnet_get_main ();
70  vl_api_igmp_listen_reply_t *rmp;
71  int ii, rv = 0;
72  ip46_address_t gaddr, *saddrs = NULL;
73 
75 
76  if ((vnet_sw_interface_get_flags (vnm, ntohl (mp->group.sw_if_index)) &&
78  {
79  // FIXME - don't we clear this state on interface down ...
80  rv = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
81  goto done;
82  }
83 
84  clib_memset (&gaddr, 0, sizeof (gaddr));
85  clib_memcpy (&gaddr.ip4, &mp->group.gaddr, sizeof (ip4_address_t));
86 
87  vec_validate (saddrs, mp->group.n_srcs - 1);
88 
89  vec_foreach_index (ii, saddrs)
90  {
91  clib_memcpy (&saddrs[ii].ip4,
92  &mp->group.saddrs[ii], sizeof (ip4_address_t));
93  }
94 
95  rv = igmp_listen (vm,
96  (mp->group.filter ?
97  IGMP_FILTER_MODE_INCLUDE :
98  IGMP_FILTER_MODE_EXCLUDE),
99  ntohl (mp->group.sw_if_index), saddrs, &gaddr);
100 
101  vec_free (saddrs);
102 
104 done:;
105  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_LISTEN_REPLY));
106 }
107 
108 static void
110 {
111  vl_api_igmp_enable_disable_reply_t *rmp;
112  int rv = 0;
113 
115 
116  rv = igmp_enable_disable (ntohl (mp->sw_if_index),
117  mp->enable,
118  (mp->mode ? IGMP_MODE_HOST : IGMP_MODE_ROUTER));
119 
121 
122  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_ENABLE_DISABLE_REPLY));
123 }
124 
125 static void
127  * mp)
128 {
129  vl_api_igmp_proxy_device_add_del_reply_t *rmp;
130  int rv = 0;
131 
133 
134  rv =
135  igmp_proxy_device_add_del (ntohl (mp->vrf_id), ntohl (mp->sw_if_index),
136  mp->add);
137 
139 
140  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_PROXY_DEVICE_ADD_DEL_REPLY));
141 }
142 
143 static void
146 {
147  vl_api_igmp_proxy_device_add_del_interface_reply_t *rmp;
148  int rv = 0;
149 
151 
152  rv =
154  ntohl (mp->sw_if_index), mp->add);
155 
157 
159  (VL_API_IGMP_PROXY_DEVICE_ADD_DEL_INTERFACE_REPLY));
160 }
161 
162 static void
164  igmp_config_t * config, igmp_group_t * group,
165  igmp_src_t * src, u32 context)
166 {
168 
169  mp = vl_msg_api_alloc (sizeof (*mp));
170  clib_memset (mp, 0, sizeof (*mp));
171 
172  mp->_vl_msg_id = htons (IGMP_MSG_ID (VL_API_IGMP_DETAILS));
173  mp->context = context;
174  mp->sw_if_index = htonl (config->sw_if_index);
175  clib_memcpy (&mp->saddr, &src->key->ip4, sizeof (src->key->ip4));
176  clib_memcpy (&mp->gaddr, &group->key->ip4, sizeof (group->key->ip4));
177 
178  vl_msg_api_send_shmem (q, (u8 *) & mp);
179 }
180 
181 static void
184  u32 context, igmp_config_t * config)
185 {
186  igmp_group_t *group;
187  igmp_src_t *src;
188 
189  /* *INDENT-OFF* */
190  FOR_EACH_GROUP (group, config,
191  ({
192  FOR_EACH_SRC (src, group, IGMP_FILTER_MODE_INCLUDE,
193  ({
194  send_igmp_details (q, im, config, group, src, context);
195  }));
196  }));
197  /* *INDENT-ON* */
198 }
199 
200 static void
202 {
204  igmp_main_t *im = &igmp_main;
205  igmp_config_t *config;
207 
209  if (!q)
210  return;
211 
212  sw_if_index = ntohl (mp->sw_if_index);
213  if (~0 == sw_if_index)
214  {
215  /* *INDENT-OFF* */
216  pool_foreach (config, im->configs,
217  ({
218  igmp_config_dump(im, q, mp->context, config);
219  }));
220  /* *INDENT-ON* */
221  }
222  else
223  {
224  config = igmp_config_lookup (sw_if_index);
225  if (config)
226  {
227  igmp_config_dump (im, q, mp->context, config);
228  }
229  }
230 }
231 
232 static void
234 {
235  vl_api_igmp_clear_interface_reply_t *rmp;
236  igmp_config_t *config;
237  int rv = 0;
238 
239  config = igmp_config_lookup (ntohl (mp->sw_if_index));
240  if (config)
241  igmp_clear_config (config);
242 
243  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_CLEAR_INTERFACE_REPLY));
244 }
245 
246 static vl_api_group_prefix_type_t
248 {
249  switch (t)
250  {
251  case IGMP_GROUP_PREFIX_TYPE_ASM:
252  return (htonl (ASM));
253  case IGMP_GROUP_PREFIX_TYPE_SSM:
254  return (htonl (SSM));
255  }
256 
257  return (SSM);
258 }
259 
261 igmp_group_type_api_to_int (vl_api_group_prefix_type_t t)
262 {
263  switch (htonl (t))
264  {
265  case ASM:
266  return (IGMP_GROUP_PREFIX_TYPE_ASM);
267  case SSM:
268  return (IGMP_GROUP_PREFIX_TYPE_SSM);
269  }
270 
271  return (IGMP_GROUP_PREFIX_TYPE_SSM);
272 }
273 
274 static void
276 {
277  vl_api_igmp_group_prefix_set_reply_t *rmp;
278  fib_prefix_t pfx;
279  int rv = 0;
280 
281  ip_prefix_decode (&mp->gp.prefix, &pfx);
283 
284  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_GROUP_PREFIX_SET_REPLY));
285 }
286 
288 {
292 
293 static walk_rc_t
295  igmp_group_prefix_type_t type, void *args)
296 {
299 
300  mp = vl_msg_api_alloc (sizeof (*mp));
301  clib_memset (mp, 0, sizeof (*mp));
302 
303  mp->_vl_msg_id = htons (IGMP_MSG_ID (VL_API_IGMP_DETAILS));
304  mp->context = ctx->context;
305  mp->gp.type = igmp_group_type_int_to_api (type);
306  ip_prefix_encode (pfx, &mp->gp.prefix);
307 
308  vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
309 
310  return (WALK_CONTINUE);
311 }
312 
313 static void
315 {
317 
319  if (!q)
320  return;
321 
323  .q = q,
324  .context = mp->context,
325  };
326 
328 }
329 
332 {
333  uword *p;
334  vpe_client_registration_t *api_client = NULL;
335 
336  p = hash_get (im->igmp_api_client_by_client_index, client_index);
337  if (p)
338  api_client = vec_elt_at_index (im->api_clients, p[0]);
339 
340  return api_client;
341 }
342 
343 static void
345 {
346  igmp_main_t *im = &igmp_main;
347  vpe_client_registration_t *api_client;
348  vl_api_want_igmp_events_reply_t *rmp;
349  int rv = 0;
350 
351  api_client = igmp_api_client_lookup (im, mp->client_index);
352  if (api_client)
353  {
354  if (mp->enable)
355  {
356  rv = VNET_API_ERROR_INVALID_REGISTRATION;
357  goto done;
358  }
360  api_client->client_index);
361  pool_put (im->api_clients, api_client);
362  goto done;
363  }
364  if (mp->enable)
365  {
366  pool_get (im->api_clients, api_client);
367  clib_memset (api_client, 0, sizeof (vpe_client_registration_t));
368  api_client->client_index = mp->client_index;
369  api_client->client_pid = mp->pid;
371  mp->client_index, api_client - im->api_clients);
372  goto done;
373  }
374  rv = VNET_API_ERROR_INVALID_REGISTRATION;
375 
376 done:;
377  REPLY_MACRO (VL_API_WANT_IGMP_EVENTS_REPLY + im->msg_id_base);
378 }
379 
380 static clib_error_t *
382 {
383  igmp_main_t *im = &igmp_main;
384  vpe_client_registration_t *api_client;
385  uword *p;
386 
387  p = hash_get (im->igmp_api_client_by_client_index, client_index);
388 
389  if (p)
390  {
391  api_client = pool_elt_at_index (im->api_clients, p[0]);
392  pool_put (im->api_clients, api_client);
393  hash_unset (im->igmp_api_client_by_client_index, client_index);
394  }
395  return (NULL);
396 }
397 
399 
400 void
402  u32 context,
403  igmp_filter_mode_t filter,
405  const ip46_address_t * saddr, const ip46_address_t * gaddr)
406 {
407  vl_api_igmp_event_t *mp = vl_msg_api_alloc (sizeof (*mp));
408  clib_memset (mp, 0, sizeof (*mp));
409 
410  mp->_vl_msg_id = ntohs ((VL_API_IGMP_EVENT) + igmp_main.msg_id_base);
411  mp->context = context;
412  mp->sw_if_index = htonl (sw_if_index);
413  mp->filter = htonl (filter);
414  clib_memcpy (&mp->saddr, &saddr->ip4, sizeof (ip4_address_t));
415  clib_memcpy (&mp->gaddr, &gaddr->ip4, sizeof (ip4_address_t));
416 
417  vl_msg_api_send_shmem (q, (u8 *) & mp);
418 }
419 
420 void
423  const ip46_address_t * saddr, const ip46_address_t * gaddr)
424 {
425  vpe_client_registration_t *api_client;
427  igmp_main_t *im;
428 
429  im = &igmp_main;
430 
431  IGMP_DBG ("event: (%U, %U) %U %U",
435  vnet_get_main (), sw_if_index, format_igmp_filter_mode, filter);
436 
437 
438  /* *INDENT-OFF* */
439  pool_foreach (api_client, im->api_clients,
440  ({
441  q = vl_api_client_index_to_input_queue (api_client->client_index);
442  if (q)
443  send_igmp_event (q, 0, filter, sw_if_index, saddr, gaddr);
444  }));
445  /* *INDENT-ON* */
446 }
447 
448 #define vl_msg_name_crc_list
449 #include <igmp/igmp_all_api_h.h>
450 #undef vl_msg_name_crc_list
451 
452 static void
454 {
455 #define _(id,n,crc) \
456  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + im->msg_id_base);
457  foreach_vl_msg_name_crc_igmp;
458 #undef _
459 }
460 
461 /* Set up the API message handling tables */
462 static clib_error_t *
464 {
465  igmp_main_t *im = &igmp_main;
466  api_main_t *am = &api_main;
467  u8 *name;
468 
469  /* Construct the API name */
470  name = format (0, "igmp_%08x%c", api_version, 0);
471 
472  /* Ask for a correctly-sized block of API message decode slots */
474  ((char *) name, VL_MSG_FIRST_AVAILABLE);
475 
476 #define _(N,n) \
477  vl_msg_api_set_handlers((VL_API_##N + im->msg_id_base), \
478  #n, \
479  vl_api_##n##_t_handler, \
480  vl_noop_handler, \
481  vl_api_##n##_t_endian, \
482  vl_api_##n##_t_print, \
483  sizeof(vl_api_##n##_t), 1);
485 #undef _
486 
487  /*
488  * Set up the (msg_name, crc, message-id) table
489  */
490  setup_message_id_table (im, am);
491 
492  vec_free (name);
493  return 0;
494 }
495 
497 
498 /*
499  * fd.io coding-style-patch-verification: ON
500  *
501  * Local Variables:
502  * eval: (c-set-style "gnu")
503  * End:
504  */
int igmp_listen(vlib_main_t *vm, igmp_filter_mode_t mode, u32 sw_if_index, const ip46_address_t *saddrs, const ip46_address_t *gaddr)
igmp listen Called by a host to request reception of multicast packets
Definition: igmp.c:133
igmp event details
Definition: igmp.api:216
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
#define foreach_igmp_plugin_api_msg
Definition: igmp_api.c:53
static clib_error_t * igmp_plugin_api_hookup(vlib_main_t *vm)
Definition: igmp_api.c:463
vl_api_filter_mode_t filter
Definition: igmp.api:66
Used by a &#39;router&#39; and &#39;host&#39; to enable the reception of IGMP packets.
Definition: igmp.api:91
#define vec_foreach_index(var, v)
Iterate over vector indices.
Definition: igmp.api:232
static void vl_api_igmp_proxy_device_add_del_t_handler(vl_api_igmp_proxy_device_add_del_t *mp)
Definition: igmp_api.c:126
#define hash_set(h, key, value)
Definition: hash.h:255
vl_api_address_t src
Definition: vxlan_gbp.api:32
#define hash_unset(h, key)
Definition: hash.h:261
void ip_prefix_decode(const vl_api_prefix_t *in, fib_prefix_t *out)
Definition: ip_types_api.c:98
remove all (S,G)s from an interface
Definition: igmp.api:178
int igmp_proxy_device_add_del_interface(u32 vrf_id, u32 sw_if_index, u8 add)
IGMP proxy device add/del interface.
Definition: igmp_proxy.c:141
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
void igmp_ssm_range_walk(igmp_ssm_range_walk_t fn, void *ctx)
igmp_main_t igmp_main
Definition: igmp.c:36
vl_api_filter_mode_t filter
Definition: igmp.api:221
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define IGMP_MSG_ID(_id)
Definition: igmp_api.c:51
igmp_config_t * configs
pool of configs
Definition: igmp.h:95
format_function_t format_ip46_address
Definition: format.h:61
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
void send_igmp_event(unix_shared_memory_queue_t *q, u32 context, igmp_filter_mode_t filter, u32 sw_if_index, const ip46_address_t *saddr, const ip46_address_t *gaddr)
Definition: igmp_api.c:401
dump (S,G)s from interface
Definition: igmp.api:149
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
void * vl_msg_api_alloc(int nbytes)
vl_api_ip4_address_t gaddr
Definition: igmp.api:223
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u16 msg_id_base
API base message ID.
Definition: igmp.h:68
#define IGMP_DBG(...)
Definition: igmp.h:38
#define clib_memcpy(d, s, n)
Definition: string.h:180
void igmp_clear_config(igmp_config_t *config)
igmp clear config
Definition: igmp_config.c:22
enum walk_rc_t_ walk_rc_t
Walk return code.
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
u32 sw_if_index
Definition: vxlan_gbp.api:37
svm_queue_t unix_shared_memory_queue_t
Definition: queue.h:132
static igmp_group_prefix_type_t igmp_group_type_api_to_int(vl_api_group_prefix_type_t t)
Definition: igmp_api.c:261
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
Definition: fib_types.h:203
vl_api_ip4_address_t saddrs[n_srcs]
Definition: igmp.api:70
unix_shared_memory_queue_t * q
Definition: igmp_api.c:289
#define FOR_EACH_GROUP(_group, _config, _body)
Definition: igmp_config.h:85
unsigned int u32
Definition: types.h:88
struct igmp_ssm_range_walk_ctx_t_ igmp_ssm_range_walk_ctx_t
igmp_config_t * igmp_config_lookup(u32 sw_if_index)
igmp config lookup
Definition: igmp_config.c:45
#define hash_get(h, key)
Definition: hash.h:249
static clib_error_t * want_igmp_events_reaper(u32 client_index)
Definition: igmp_api.c:381
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
static walk_rc_t igmp_ssm_range_walk_dump(const fib_prefix_t *pfx, igmp_group_prefix_type_t type, void *args)
Definition: igmp_api.c:294
int igmp_enable_disable(u32 sw_if_index, u8 enable, igmp_mode_t mode)
IGMP interface enable/disable.
Definition: igmp.c:340
long ctx[MAX_CONNS]
Definition: main.c:144
vl_api_ip4_address_t saddr
Definition: igmp.api:222
Configure a prefix for SSM or ASM semantics.
Definition: igmp.api:249
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
#define REPLY_MACRO(t)
VLIB_API_INIT_FUNCTION(igmp_plugin_api_hookup)
igmp details
Definition: igmp.api:164
static void vl_api_igmp_group_prefix_dump_t_handler(vl_api_igmp_dump_t *mp)
Definition: igmp_api.c:314
collection of data related to IGMP
Definition: igmp.h:63
u8 name[64]
Definition: memclnt.api:152
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:202
Definition: igmp.api:231
static void setup_message_id_table(igmp_main_t *im, api_main_t *am)
Definition: igmp_api.c:453
#define BAD_SW_IF_INDEX_LABEL
static void vl_api_igmp_group_prefix_set_t_handler(vl_api_igmp_group_prefix_set_t *mp)
Definition: igmp_api.c:275
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
vl_api_igmp_group_t group
Definition: igmp.api:77
vlib_main_t * vm
Definition: buffer.c:301
svm_queue_t * vl_api_client_index_to_input_queue(u32 index)
Definition: memory_api.c:799
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
vpe_client_registration_t * api_clients
API client registered for events.
Definition: igmp.h:75
enum igmp_filter_mode_t_ igmp_filter_mode_t
vl_api_ip4_address_t gaddr
Definition: igmp.api:170
void igmp_group_prefix_set(const fib_prefix_t *pfx, igmp_group_prefix_type_t type)
Add/del downstream interface to/from proxy device.
Definition: igmp.api:133
vl_api_group_prefix_t gp
Definition: igmp.api:254
static void vl_api_igmp_proxy_device_add_del_interface_t_handler(vl_api_igmp_proxy_device_add_del_interface_t *mp)
Definition: igmp_api.c:145
u8 * format_igmp_filter_mode(u8 *s, va_list *args)
Definition: igmp_format.c:50
Add/del proxy device on specified VRF.
Definition: igmp.api:112
vl_api_ip4_address_t gaddr
Definition: igmp.api:69
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
IGMP interface configuration.
Definition: igmp_config.h:47
static vl_api_group_prefix_type_t igmp_group_type_int_to_api(igmp_group_prefix_type_t t)
Definition: igmp_api.c:247
void ip_prefix_encode(const fib_prefix_t *in, vl_api_prefix_t *out)
Definition: ip_types_api.c:115
VL_MSG_API_REAPER_FUNCTION(want_igmp_events_reaper)
void igmp_event(igmp_filter_mode_t filter, u32 sw_if_index, const ip46_address_t *saddr, const ip46_address_t *gaddr)
Send an IGMP event to listening parties.
Definition: igmp_api.c:421
#define FOR_EACH_SRC(_src, _group, _filter, _body)
Definition: igmp_group.h:90
igmp_key_t * key
The group&#39;s key within the per-interface config.
Definition: igmp_group.h:59
static void vl_api_want_igmp_events_t_handler(vl_api_want_igmp_events_t *mp)
Definition: igmp_api.c:344
vl_api_ip4_address_t saddr
Definition: igmp.api:169
IGMP group A multicast group address for which reception has been requested.
Definition: igmp_group.h:56
u64 uword
Definition: types.h:112
static void igmp_config_dump(igmp_main_t *im, unix_shared_memory_queue_t *q, u32 context, igmp_config_t *config)
Definition: igmp_api.c:182
static void vl_api_igmp_listen_t_handler(vl_api_igmp_listen_t *mp)
Definition: igmp_api.c:66
igmp_key_t * key
The source&#39;s key.
Definition: igmp_src.h:46
static void vl_api_igmp_enable_disable_t_handler(vl_api_igmp_enable_disable_t *mp)
Definition: igmp_api.c:109
static void send_igmp_details(unix_shared_memory_queue_t *q, igmp_main_t *im, igmp_config_t *config, igmp_group_t *group, igmp_src_t *src, u32 context)
Definition: igmp_api.c:163
static vnet_sw_interface_flags_t vnet_sw_interface_get_flags(vnet_main_t *vnm, u32 sw_if_index)
enum igmp_group_prefix_type_t_ igmp_group_prefix_type_t
static void vl_api_igmp_dump_t_handler(vl_api_igmp_dump_t *mp)
Definition: igmp_api.c:201
static vpe_client_registration_t * igmp_api_client_lookup(igmp_main_t *im, u32 client_index)
Definition: igmp_api.c:331
uword * igmp_api_client_by_client_index
Definition: igmp.h:70
int igmp_proxy_device_add_del(u32 vrf_id, u32 sw_if_index, u8 add)
IGMP proxy device add/del.
Definition: igmp_proxy.c:80
static void vl_api_igmp_clear_interface_t_handler(vl_api_igmp_clear_interface_t *mp)
Definition: igmp_api.c:233
api_main_t api_main
Definition: api_shared.c:35
register for igmp events
Definition: igmp.api:193
IGMP source The representation of a specified source address with in multicast group.
Definition: igmp_src.h:41
#define VALIDATE_SW_IF_INDEX(mp)
vl_api_group_prefix_t gp
Definition: igmp.api:267
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:865