FD.io VPP  v20.09-64-g4f7b92f0a
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.api_enum.h>
27 #include <igmp/igmp.api_types.h>
28 #include <vnet/format_fns.h>
29 
31 
32 #define IGMP_MSG_ID(_id) (_id + igmp_main.msg_id_base)
33 
34 static void
36 {
38  vnet_main_t *vnm = vnet_get_main ();
39  vl_api_igmp_listen_reply_t *rmp;
40  int ii, rv = 0;
41  ip46_address_t gaddr, *saddrs = NULL;
42 
44 
45  if ((vnet_sw_interface_get_flags (vnm, ntohl (mp->group.sw_if_index)) &&
47  {
48  // FIXME - don't we clear this state on interface down ...
49  rv = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
50  goto done;
51  }
52 
53  clib_memset (&gaddr, 0, sizeof (gaddr));
54  clib_memcpy (&gaddr.ip4, &mp->group.gaddr, sizeof (ip4_address_t));
55 
56  vec_validate (saddrs, mp->group.n_srcs - 1);
57 
58  vec_foreach_index (ii, saddrs)
59  {
60  clib_memcpy (&saddrs[ii].ip4,
61  &mp->group.saddrs[ii], sizeof (ip4_address_t));
62  }
63 
64  rv = igmp_listen (vm,
65  (mp->group.filter ?
66  IGMP_FILTER_MODE_INCLUDE :
67  IGMP_FILTER_MODE_EXCLUDE),
68  ntohl (mp->group.sw_if_index), saddrs, &gaddr);
69 
70  vec_free (saddrs);
71 
73 done:;
74  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_LISTEN_REPLY));
75 }
76 
77 static void
79 {
80  vl_api_igmp_enable_disable_reply_t *rmp;
81  int rv = 0;
82 
84 
85  rv = igmp_enable_disable (ntohl (mp->sw_if_index),
86  mp->enable,
87  (mp->mode ? IGMP_MODE_HOST : IGMP_MODE_ROUTER));
88 
90 
91  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_ENABLE_DISABLE_REPLY));
92 }
93 
94 static void
96  * mp)
97 {
98  vl_api_igmp_proxy_device_add_del_reply_t *rmp;
99  int rv = 0;
100 
102 
103  rv =
104  igmp_proxy_device_add_del (ntohl (mp->vrf_id), ntohl (mp->sw_if_index),
105  mp->add);
106 
108 
109  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_PROXY_DEVICE_ADD_DEL_REPLY));
110 }
111 
112 static void
115 {
116  vl_api_igmp_proxy_device_add_del_interface_reply_t *rmp;
117  int rv = 0;
118 
120 
121  rv =
123  ntohl (mp->sw_if_index), mp->add);
124 
126 
128  (VL_API_IGMP_PROXY_DEVICE_ADD_DEL_INTERFACE_REPLY));
129 }
130 
131 static void
133  igmp_config_t * config, igmp_group_t * group,
134  igmp_src_t * src, u32 context)
135 {
137 
138  mp = vl_msg_api_alloc (sizeof (*mp));
139  clib_memset (mp, 0, sizeof (*mp));
140 
141  mp->_vl_msg_id = htons (IGMP_MSG_ID (VL_API_IGMP_DETAILS));
142  mp->context = context;
143  mp->sw_if_index = htonl (config->sw_if_index);
144  clib_memcpy (&mp->saddr, &src->key->ip4, sizeof (src->key->ip4));
145  clib_memcpy (&mp->gaddr, &group->key->ip4, sizeof (group->key->ip4));
146 
147  vl_api_send_msg (rp, (u8 *) mp);
148 }
149 
150 static void
153  u32 context, igmp_config_t * config)
154 {
155  igmp_group_t *group;
156  igmp_src_t *src;
157 
158  /* *INDENT-OFF* */
159  FOR_EACH_GROUP (group, config,
160  ({
161  FOR_EACH_SRC (src, group, IGMP_FILTER_MODE_INCLUDE,
162  ({
163  send_igmp_details (rp, im, config, group, src, context);
164  }));
165  }));
166  /* *INDENT-ON* */
167 }
168 
169 static void
171 {
172  igmp_main_t *im = &igmp_main;
173  igmp_config_t *config;
176 
178  if (rp == 0)
179  return;
180 
181  sw_if_index = ntohl (mp->sw_if_index);
182  if (~0 == sw_if_index)
183  {
184  /* *INDENT-OFF* */
185  pool_foreach (config, im->configs,
186  ({
187  igmp_config_dump(im, rp, mp->context, config);
188  }));
189  /* *INDENT-ON* */
190  }
191  else
192  {
193  config = igmp_config_lookup (sw_if_index);
194  if (config)
195  {
196  igmp_config_dump (im, rp, mp->context, config);
197  }
198  }
199 }
200 
201 static void
203 {
204  vl_api_igmp_clear_interface_reply_t *rmp;
205  igmp_config_t *config;
206  int rv = 0;
207 
208  config = igmp_config_lookup (ntohl (mp->sw_if_index));
209  if (config)
210  igmp_clear_config (config);
211 
212  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_CLEAR_INTERFACE_REPLY));
213 }
214 
215 static vl_api_group_prefix_type_t
217 {
218  switch (t)
219  {
220  case IGMP_GROUP_PREFIX_TYPE_ASM:
221  return (htonl (ASM));
222  case IGMP_GROUP_PREFIX_TYPE_SSM:
223  return (htonl (SSM));
224  }
225 
226  return (SSM);
227 }
228 
230 igmp_group_type_api_to_int (vl_api_group_prefix_type_t t)
231 {
232  switch (htonl (t))
233  {
234  case ASM:
235  return (IGMP_GROUP_PREFIX_TYPE_ASM);
236  case SSM:
237  return (IGMP_GROUP_PREFIX_TYPE_SSM);
238  }
239 
240  return (IGMP_GROUP_PREFIX_TYPE_SSM);
241 }
242 
243 static void
245 {
246  vl_api_igmp_group_prefix_set_reply_t *rmp;
247  fib_prefix_t pfx;
248  int rv = 0;
249 
250  ip_prefix_decode (&mp->gp.prefix, &pfx);
252 
253  REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_GROUP_PREFIX_SET_REPLY));
254 }
255 
257 {
261 
262 static walk_rc_t
264  igmp_group_prefix_type_t type, void *args)
265 {
268 
269  mp = vl_msg_api_alloc (sizeof (*mp));
270  clib_memset (mp, 0, sizeof (*mp));
271 
272  mp->_vl_msg_id = htons (IGMP_MSG_ID (VL_API_IGMP_DETAILS));
273  mp->context = ctx->context;
274  mp->gp.type = igmp_group_type_int_to_api (type);
275  ip_prefix_encode (pfx, &mp->gp.prefix);
276 
277  vl_api_send_msg (ctx->rp, (u8 *) mp);
278 
279  return (WALK_CONTINUE);
280 }
281 
282 static void
284 {
286 
288  if (rp == 0)
289  return;
290 
292  .rp = rp,
293  .context = mp->context,
294  };
295 
297 }
298 
301 {
302  uword *p;
303  vpe_client_registration_t *api_client = NULL;
304 
305  p = hash_get (im->igmp_api_client_by_client_index, client_index);
306  if (p)
307  api_client = vec_elt_at_index (im->api_clients, p[0]);
308 
309  return api_client;
310 }
311 
312 static void
314 {
315  igmp_main_t *im = &igmp_main;
316  vpe_client_registration_t *api_client;
317  vl_api_want_igmp_events_reply_t *rmp;
318  int rv = 0;
319 
320  api_client = igmp_api_client_lookup (im, mp->client_index);
321  if (api_client)
322  {
323  if (mp->enable)
324  {
325  rv = VNET_API_ERROR_INVALID_REGISTRATION;
326  goto done;
327  }
329  api_client->client_index);
330  pool_put (im->api_clients, api_client);
331  goto done;
332  }
333  if (mp->enable)
334  {
335  pool_get (im->api_clients, api_client);
336  clib_memset (api_client, 0, sizeof (vpe_client_registration_t));
337  api_client->client_index = mp->client_index;
338  api_client->client_pid = mp->pid;
340  mp->client_index, api_client - im->api_clients);
341  goto done;
342  }
343  rv = VNET_API_ERROR_INVALID_REGISTRATION;
344 
345 done:
346  REPLY_MACRO (VL_API_WANT_IGMP_EVENTS_REPLY + im->msg_id_base);
347 }
348 
349 static clib_error_t *
351 {
352  igmp_main_t *im = &igmp_main;
353  vpe_client_registration_t *api_client;
354  uword *p;
355 
356  p = hash_get (im->igmp_api_client_by_client_index, client_index);
357 
358  if (p)
359  {
360  api_client = pool_elt_at_index (im->api_clients, p[0]);
361  pool_put (im->api_clients, api_client);
362  hash_unset (im->igmp_api_client_by_client_index, client_index);
363  }
364  return (NULL);
365 }
366 
368 
369 void
371  igmp_filter_mode_t filter,
373  const ip46_address_t * saddr, const ip46_address_t * gaddr)
374 {
375  vl_api_igmp_event_t *mp = vl_msg_api_alloc (sizeof (*mp));
376  clib_memset (mp, 0, sizeof (*mp));
377 
378  mp->_vl_msg_id = ntohs ((VL_API_IGMP_EVENT) + igmp_main.msg_id_base);
379  mp->sw_if_index = htonl (sw_if_index);
380  mp->filter = htonl (filter);
381  clib_memcpy (&mp->saddr, &saddr->ip4, sizeof (ip4_address_t));
382  clib_memcpy (&mp->gaddr, &gaddr->ip4, sizeof (ip4_address_t));
383 
384  vl_api_send_msg (rp, (u8 *) mp);
385 }
386 
387 void
390  const ip46_address_t * saddr, const ip46_address_t * gaddr)
391 {
392  vpe_client_registration_t *api_client;
394  igmp_main_t *im;
395 
396  im = &igmp_main;
397 
398  IGMP_DBG ("event: (%U, %U) %U %U",
402  vnet_get_main (), sw_if_index, format_igmp_filter_mode, filter);
403 
404 
405  /* *INDENT-OFF* */
406  pool_foreach (api_client, im->api_clients,
407  ({
408  rp = vl_api_client_index_to_registration (api_client->client_index);
409  if (rp)
410  send_igmp_event (rp, filter, sw_if_index, saddr, gaddr);
411  }));
412  /* *INDENT-ON* */
413 }
414 
415 /* Set up the API message handling tables */
416 #include <igmp/igmp.api.c>
417 static clib_error_t *
419 {
420  igmp_main_t *im = &igmp_main;
421 
422  /* Ask for a correctly-sized block of API message decode slots */
424 
425  return 0;
426 }
427 
429 
430 /*
431  * fd.io coding-style-patch-verification: ON
432  *
433  * Local Variables:
434  * eval: (c-set-style "gnu")
435  * End:
436  */
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:217
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
static clib_error_t * igmp_plugin_api_hookup(vlib_main_t *vm)
Definition: igmp_api.c:418
Used by a &#39;router&#39; and &#39;host&#39; to enable the reception of IGMP packets.
Definition: igmp.api:92
#define vec_foreach_index(var, v)
Iterate over vector indices.
Definition: igmp.api:231
static void vl_api_igmp_proxy_device_add_del_t_handler(vl_api_igmp_proxy_device_add_del_t *mp)
Definition: igmp_api.c:95
#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:233
remove all (S,G)s from an interface
Definition: igmp.api:179
#define ntohs(x)
Definition: af_xdp.bpf.c:29
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:46
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:220
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define IGMP_MSG_ID(_id)
Definition: igmp_api.c:32
igmp_config_t * configs
pool of configs
Definition: igmp.h:95
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:35
vl_api_interface_index_t sw_if_index
Definition: igmp.api:219
vl_api_address_t src
Definition: gre.api:54
vlib_main_t * vm
Definition: in2out_ed.c:1582
dump (S,G)s from interface
Definition: igmp.api:150
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
void * vl_msg_api_alloc(int nbytes)
vl_api_ip4_address_t gaddr
Definition: igmp.api:222
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:513
static igmp_group_prefix_type_t igmp_group_type_api_to_int(vl_api_group_prefix_type_t t)
Definition: igmp_api.c:230
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
Definition: fib_types.h:203
#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
vl_api_fib_path_type_t type
Definition: fib_types.api:123
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:350
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
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:263
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 saddrs[n_srcs]
Definition: igmp.api:71
long ctx[MAX_CONNS]
Definition: main.c:144
vl_api_ip4_address_t saddr
Definition: igmp.api:221
vl_api_interface_index_t sw_if_index
Definition: igmp.api:184
Configure a prefix for SSM or ASM semantics.
Definition: igmp.api:248
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
vl_api_interface_index_t sw_if_index
Definition: igmp.api:120
static void igmp_config_dump(igmp_main_t *im, vl_api_registration_t *rp, u32 context, igmp_config_t *config)
Definition: igmp_api.c:151
#define REPLY_MACRO(t)
vl_api_ip4_address_t ip4
Definition: one.api:376
vl_api_interface_index_t sw_if_index
Definition: igmp.api:155
VLIB_API_INIT_FUNCTION(igmp_plugin_api_hookup)
igmp details
Definition: igmp.api:165
static void vl_api_igmp_group_prefix_dump_t_handler(vl_api_igmp_dump_t *mp)
Definition: igmp_api.c:283
collection of data related to IGMP
Definition: igmp.h:63
vl_api_interface_index_t sw_if_index
Definition: igmp.api:169
format_function_t format_ip46_address
Definition: ip46_address.h:50
Definition: igmp.api:230
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
#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:244
vl_api_igmp_group_t group
Definition: igmp.api:78
vl_api_ip4_address_t gaddr
Definition: igmp.api:70
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
vpe_client_registration_t * api_clients
API client registered for events.
Definition: igmp.h:75
enum igmp_filter_mode_t_ igmp_filter_mode_t
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:79
vl_api_ip4_address_t gaddr
Definition: igmp.api:171
void igmp_group_prefix_set(const fib_prefix_t *pfx, igmp_group_prefix_type_t type)
vl_api_interface_index_t sw_if_index
Definition: igmp.api:141
static void send_igmp_details(vl_api_registration_t *rp, igmp_main_t *im, igmp_config_t *config, igmp_group_t *group, igmp_src_t *src, u32 context)
Definition: igmp_api.c:132
vl_api_registration_t * rp
Definition: igmp_api.c:258
Add/del downstream interface to/from proxy device.
Definition: igmp.api:134
vl_api_group_prefix_t gp
Definition: igmp.api:253
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:114
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:113
void send_igmp_event(vl_api_registration_t *rp, igmp_filter_mode_t filter, u32 sw_if_index, const ip46_address_t *saddr, const ip46_address_t *gaddr)
Definition: igmp_api.c:370
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:216
void ip_prefix_encode(const fib_prefix_t *in, vl_api_prefix_t *out)
Definition: ip_types_api.c:261
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:388
#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:313
vl_api_ip4_address_t saddr
Definition: igmp.api:170
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 vl_api_igmp_listen_t_handler(vl_api_igmp_listen_t *mp)
Definition: igmp_api.c:35
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:78
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:170
static void setup_message_id_table(snat_main_t *sm, api_main_t *am)
Definition: nat_api.c:2804
static vpe_client_registration_t * igmp_api_client_lookup(igmp_main_t *im, u32 client_index)
Definition: igmp_api.c:300
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:202
register for igmp events
Definition: igmp.api:194
vl_api_interface_index_t sw_if_index
Definition: igmp.api:99
IGMP source The representation of a specified source address with in multicast group.
Definition: igmp_src.h:41
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
#define VALIDATE_SW_IF_INDEX(mp)
vl_api_group_prefix_t gp
Definition: igmp.api:266