FD.io VPP  v18.07-34-g55fbdb9
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_DUMP, igmp_dump) \
57 _(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
58 _(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
59 _(IGMP_GROUP_PREFIX_SET, igmp_group_prefix_set) \
60 _(IGMP_GROUP_PREFIX_DUMP, igmp_group_prefix_dump) \
61 _(WANT_IGMP_EVENTS, want_igmp_events) \
62 
63 static void
65 {
67  vnet_main_t *vnm = vnet_get_main ();
68  vl_api_igmp_listen_reply_t *rmp;
69  int ii, rv = 0;
70  ip46_address_t gaddr, *saddrs = NULL;
71 
73 
74  if ((vnet_sw_interface_get_flags (vnm, ntohl (mp->group.sw_if_index)) &&
76  {
77  // FIXME - don't we clear this state on interface down ...
78  rv = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
79  goto done;
80  }
81 
82  memset (&gaddr, 0, sizeof (gaddr));
83  clib_memcpy (&gaddr.ip4, &mp->group.gaddr, sizeof (ip4_address_t));
84 
85  vec_validate (saddrs, mp->group.n_srcs - 1);
86 
87  vec_foreach_index (ii, saddrs)
88  {
89  clib_memcpy (&saddrs[ii].ip4,
90  &mp->group.saddrs[ii], sizeof (ip4_address_t));
91  }
92 
93  rv = igmp_listen (vm,
94  (mp->group.filter ?
95  IGMP_FILTER_MODE_INCLUDE :
96  IGMP_FILTER_MODE_EXCLUDE),
97  ntohl (mp->group.sw_if_index), saddrs, &gaddr);
98 
99  vec_free (saddrs);
100 
102 done:;
103  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_LISTEN_REPLY));
104 }
105 
106 static void
108 {
109  vl_api_igmp_enable_disable_reply_t *rmp;
110  int rv = 0;
111 
113 
114  rv = igmp_enable_disable (ntohl (mp->sw_if_index),
115  mp->enable,
116  (mp->mode ? IGMP_MODE_HOST : IGMP_MODE_ROUTER));
117 
119 
120  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_ENABLE_DISABLE_REPLY));
121 }
122 
123 static void
125  igmp_config_t * config, igmp_group_t * group,
126  igmp_src_t * src, u32 context)
127 {
129 
130  mp = vl_msg_api_alloc (sizeof (*mp));
131  memset (mp, 0, sizeof (*mp));
132 
133  mp->_vl_msg_id = htons (IGMP_MSG_ID (VL_API_IGMP_DETAILS));
134  mp->context = context;
135  mp->sw_if_index = htonl (config->sw_if_index);
136  clib_memcpy (mp->saddr.address, &src->key->ip4, sizeof (src->key->ip4));
137  clib_memcpy (mp->gaddr.address, &group->key->ip4, sizeof (group->key->ip4));
138 
139  vl_msg_api_send_shmem (q, (u8 *) & mp);
140 }
141 
142 static void
145  u32 context, igmp_config_t * config)
146 {
147  igmp_group_t *group;
148  igmp_src_t *src;
149 
150  /* *INDENT-OFF* */
151  FOR_EACH_GROUP (group, config,
152  ({
153  FOR_EACH_SRC (src, group, IGMP_FILTER_MODE_INCLUDE,
154  ({
155  send_igmp_details (q, im, config, group, src, context);
156  }));
157  }));
158  /* *INDENT-ON* */
159 }
160 
161 static void
163 {
165  igmp_main_t *im = &igmp_main;
166  igmp_config_t *config;
167  u32 sw_if_index;
168 
170  if (!q)
171  return;
172 
173  sw_if_index = ntohl (mp->sw_if_index);
174  if (~0 == sw_if_index)
175  {
176  /* *INDENT-OFF* */
177  pool_foreach (config, im->configs,
178  ({
179  igmp_config_dump(im, q, mp->context, config);
180  }));
181  /* *INDENT-ON* */
182  }
183  else
184  {
185  config = igmp_config_lookup (sw_if_index);
186  if (config)
187  {
188  igmp_config_dump (im, q, mp->context, config);
189  }
190  }
191 }
192 
193 static void
195 {
196  vl_api_igmp_clear_interface_reply_t *rmp;
197  igmp_config_t *config;
198  int rv = 0;
199 
200  config = igmp_config_lookup (ntohl (mp->sw_if_index));
201  if (config)
202  igmp_clear_config (config);
203 
204  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_CLEAR_INTERFACE_REPLY));
205 }
206 
207 static vl_api_group_prefix_type_t
209 {
210  switch (t)
211  {
212  case IGMP_GROUP_PREFIX_TYPE_ASM:
213  return (htonl (ASM));
214  case IGMP_GROUP_PREFIX_TYPE_SSM:
215  return (htonl (SSM));
216  }
217 
218  return (SSM);
219 }
220 
222 igmp_group_type_api_to_int (vl_api_group_prefix_type_t t)
223 {
224  switch (htonl (t))
225  {
226  case ASM:
227  return (IGMP_GROUP_PREFIX_TYPE_ASM);
228  case SSM:
229  return (IGMP_GROUP_PREFIX_TYPE_SSM);
230  }
231 
232  return (IGMP_GROUP_PREFIX_TYPE_SSM);
233 }
234 
235 static void
237 {
238  vl_api_igmp_group_prefix_set_reply_t *rmp;
239  fib_prefix_t pfx;
240  int rv = 0;
241 
242  ip_prefix_decode (&mp->gp.prefix, &pfx);
244 
245  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_GROUP_PREFIX_SET_REPLY));
246 }
247 
249 {
253 
254 static walk_rc_t
256  igmp_group_prefix_type_t type, void *args)
257 {
260 
261  mp = vl_msg_api_alloc (sizeof (*mp));
262  memset (mp, 0, sizeof (*mp));
263 
264  mp->_vl_msg_id = htons (IGMP_MSG_ID (VL_API_IGMP_DETAILS));
265  mp->context = ctx->context;
266  mp->gp.type = igmp_group_type_int_to_api (type);
267  ip_prefix_encode (pfx, &mp->gp.prefix);
268 
269  vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
270 
271  return (WALK_CONTINUE);
272 }
273 
274 static void
276 {
278 
280  if (!q)
281  return;
282 
284  .q = q,
285  .context = mp->context,
286  };
287 
289 }
290 
293 {
294  uword *p;
295  vpe_client_registration_t *api_client = NULL;
296 
297  p = hash_get (im->igmp_api_client_by_client_index, client_index);
298  if (p)
299  api_client = vec_elt_at_index (im->api_clients, p[0]);
300 
301  return api_client;
302 }
303 
304 static void
306 {
307  igmp_main_t *im = &igmp_main;
308  vpe_client_registration_t *api_client;
309  vl_api_want_igmp_events_reply_t *rmp;
310  int rv = 0;
311 
312  api_client = igmp_api_client_lookup (im, mp->client_index);
313  if (api_client)
314  {
315  if (mp->enable)
316  {
317  rv = VNET_API_ERROR_INVALID_REGISTRATION;
318  goto done;
319  }
321  api_client->client_index);
322  pool_put (im->api_clients, api_client);
323  goto done;
324  }
325  if (mp->enable)
326  {
327  pool_get (im->api_clients, api_client);
328  memset (api_client, 0, sizeof (vpe_client_registration_t));
329  api_client->client_index = mp->client_index;
330  api_client->client_pid = mp->pid;
332  mp->client_index, api_client - im->api_clients);
333  goto done;
334  }
335  rv = VNET_API_ERROR_INVALID_REGISTRATION;
336 
337 done:;
338  REPLY_MACRO (VL_API_WANT_IGMP_EVENTS_REPLY + im->msg_id_base);
339 }
340 
341 static clib_error_t *
343 {
344  igmp_main_t *im = &igmp_main;
345  vpe_client_registration_t *api_client;
346  uword *p;
347 
348  p = hash_get (im->igmp_api_client_by_client_index, client_index);
349 
350  if (p)
351  {
352  api_client = pool_elt_at_index (im->api_clients, p[0]);
353  pool_put (im->api_clients, api_client);
354  hash_unset (im->igmp_api_client_by_client_index, client_index);
355  }
356  return (NULL);
357 }
358 
360 
361 void
363  u32 context,
364  igmp_filter_mode_t filter,
365  u32 sw_if_index,
366  const ip46_address_t * saddr, const ip46_address_t * gaddr)
367 {
368  vl_api_igmp_event_t *mp = vl_msg_api_alloc (sizeof (*mp));
369  memset (mp, 0, sizeof (*mp));
370 
371  mp->_vl_msg_id = ntohs ((VL_API_IGMP_EVENT) + igmp_main.msg_id_base);
372  mp->context = context;
373  mp->sw_if_index = htonl (sw_if_index);
374  mp->filter = htonl (filter);
375  clib_memcpy (&mp->saddr, &saddr->ip4, sizeof (ip4_address_t));
376  clib_memcpy (&mp->gaddr, &gaddr->ip4, sizeof (ip4_address_t));
377 
378  vl_msg_api_send_shmem (q, (u8 *) & mp);
379 }
380 
381 void
383  u32 sw_if_index,
384  const ip46_address_t * saddr, const ip46_address_t * gaddr)
385 {
386  vpe_client_registration_t *api_client;
388  igmp_main_t *im;
389 
390  im = &igmp_main;
391 
392  IGMP_DBG ("event: (%U, %U) %U %U",
396  vnet_get_main (), sw_if_index, format_igmp_filter_mode, filter);
397 
398 
399  /* *INDENT-OFF* */
400  pool_foreach (api_client, im->api_clients,
401  ({
402  q = vl_api_client_index_to_input_queue (api_client->client_index);
403  if (q)
404  send_igmp_event (q, 0, filter, sw_if_index, saddr, gaddr);
405  }));
406  /* *INDENT-ON* */
407 }
408 
409 #define vl_msg_name_crc_list
410 #include <igmp/igmp_all_api_h.h>
411 #undef vl_msg_name_crc_list
412 
413 static void
415 {
416 #define _(id,n,crc) \
417  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + im->msg_id_base);
418  foreach_vl_msg_name_crc_igmp;
419 #undef _
420 }
421 
422 /* Set up the API message handling tables */
423 static clib_error_t *
425 {
426  igmp_main_t *im = &igmp_main;
427  api_main_t *am = &api_main;
428  u8 *name;
429 
430  /* Construct the API name */
431  name = format (0, "igmp_%08x%c", api_version, 0);
432 
433  /* Ask for a correctly-sized block of API message decode slots */
435  ((char *) name, VL_MSG_FIRST_AVAILABLE);
436 
437 #define _(N,n) \
438  vl_msg_api_set_handlers((VL_API_##N + im->msg_id_base), \
439  #n, \
440  vl_api_##n##_t_handler, \
441  vl_noop_handler, \
442  vl_api_##n##_t_endian, \
443  vl_api_##n##_t_print, \
444  sizeof(vl_api_##n##_t), 1);
446 #undef _
447 
448  /*
449  * Set up the (msg_name, crc, message-id) table
450  */
451  setup_message_id_table (im, am);
452 
453  vec_free (name);
454  return 0;
455 }
456 
458 
459 /*
460  * fd.io coding-style-patch-verification: ON
461  *
462  * Local Variables:
463  * eval: (c-set-style "gnu")
464  * End:
465  */
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:174
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
#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:424
vl_api_filter_mode_t filter
Definition: igmp.api:66
Used by a &#39;router&#39; and &#39;host&#39; to enable the recption of IGMP packets.
Definition: igmp.api:91
#define vec_foreach_index(var, v)
Iterate over vector indices.
Definition: igmp.api:190
#define hash_set(h, key, value)
Definition: hash.h:255
#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:65
remove all (S,G)s from an interface
Definition: igmp.api:136
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:179
#define NULL
Definition: clib.h:55
#define IGMP_MSG_ID(_id)
Definition: igmp_api.c:51
igmp_config_t * configs
pool of configs
Definition: igmp.h:94
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:362
dump (S,G)s from interface
Definition: igmp.api:107
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
void * vl_msg_api_alloc(int nbytes)
vl_api_ip4_address_t gaddr
Definition: igmp.api:181
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:67
#define IGMP_DBG(...)
Definition: igmp.h:37
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:443
svm_queue_t unix_shared_memory_queue_t
Definition: queue.h:77
static igmp_group_prefix_type_t igmp_group_type_api_to_int(vl_api_group_prefix_type_t t)
Definition: igmp_api.c:222
#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:188
vl_api_ip4_address_t saddrs[n_srcs]
Definition: igmp.api:70
unix_shared_memory_queue_t * q
Definition: igmp_api.c:250
#define FOR_EACH_GROUP(_group, _config, _body)
Definition: igmp_config.h:76
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:342
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
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:255
int igmp_enable_disable(u32 sw_if_index, u8 enable, igmp_mode_t mode)
IGMP interface enable/disable.
Definition: igmp.c:340
vl_api_ip4_address_t saddr
Definition: igmp.api:180
Configure a prefix for SSM or ASM semantics.
Definition: igmp.api:207
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
#define REPLY_MACRO(t)
VLIB_API_INIT_FUNCTION(igmp_plugin_api_hookup)
igmp details
Definition: igmp.api:122
static void vl_api_igmp_group_prefix_dump_t_handler(vl_api_igmp_dump_t *mp)
Definition: igmp_api.c:275
collection of data related to IGMP
Definition: igmp.h:62
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:201
Definition: igmp.api:189
static void setup_message_id_table(igmp_main_t *im, api_main_t *am)
Definition: igmp_api.c:414
#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:236
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:294
svm_queue_t * vl_api_client_index_to_input_queue(u32 index)
Definition: memory_api.c:754
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
vpe_client_registration_t * api_clients
API client registered for events.
Definition: igmp.h:74
#define clib_memcpy(a, b, c)
Definition: string.h:75
enum igmp_filter_mode_t_ igmp_filter_mode_t
vl_api_ip4_address_t gaddr
Definition: igmp.api:128
void igmp_group_prefix_set(const fib_prefix_t *pfx, igmp_group_prefix_type_t type)
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:661
vl_api_group_prefix_t gp
Definition: igmp.api:212
long ctx[MAX_CONNS]
Definition: main.c:126
u8 * format_igmp_filter_mode(u8 *s, va_list *args)
Definition: igmp_format.c:50
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:43
static vl_api_group_prefix_type_t igmp_group_type_int_to_api(igmp_group_prefix_type_t t)
Definition: igmp_api.c:208
void ip_prefix_encode(const fib_prefix_t *in, vl_api_prefix_t *out)
Definition: ip_types_api.c:81
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:382
#define FOR_EACH_SRC(_src, _group, _filter, _body)
Definition: igmp_group.h:89
igmp_key_t * key
The group&#39;s key within the per-interface config.
Definition: igmp_group.h:58
static void vl_api_want_igmp_events_t_handler(vl_api_want_igmp_events_t *mp)
Definition: igmp_api.c:305
vl_api_ip4_address_t saddr
Definition: igmp.api:127
IGMP group A multicast group address for which reception has been requested.
Definition: igmp_group.h:55
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:143
static void vl_api_igmp_listen_t_handler(vl_api_igmp_listen_t *mp)
Definition: igmp_api.c:64
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:107
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:124
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:162
static vpe_client_registration_t * igmp_api_client_lookup(igmp_main_t *im, u32 client_index)
Definition: igmp_api.c:292
uword * igmp_api_client_by_client_index
Definition: igmp.h:69
static uword vnet_sw_interface_get_flags(vnet_main_t *vnm, u32 sw_if_index)
static void vl_api_igmp_clear_interface_t_handler(vl_api_igmp_clear_interface_t *mp)
Definition: igmp_api.c:194
api_main_t api_main
Definition: api_shared.c:35
register for igmp events
Definition: igmp.api:151
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:225
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:872