FD.io VPP  v18.07-rc0-415-g6c78436
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 
23 /* define message IDs */
24 #include <igmp/igmp_msg_enum.h>
25 
26 /* define message structures */
27 #define vl_typedefs
28 #include <igmp/igmp_all_api_h.h>
29 #undef vl_typedefs
30 
31 /* define generated endian-swappers */
32 #define vl_endianfun
33 #include <igmp/igmp_all_api_h.h>
34 #undef vl_endianfun
35 
36 /* instantiate all the print functions we know about */
37 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
38 #define vl_printfun
39 #include <igmp/igmp_all_api_h.h>
40 #undef vl_printfun
41 
42 /* Get the API version number */
43 #define vl_api_version(n,v) static u32 api_version=(v);
44 #include <igmp/igmp_all_api_h.h>
45 #undef vl_api_version
46 
48 
49 #define foreach_igmp_plugin_api_msg \
50 _(IGMP_LISTEN, igmp_listen) \
51 _(IGMP_ENABLE_DISABLE, igmp_enable_disable) \
52 _(IGMP_DUMP, igmp_dump) \
53 _(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
54 _(WANT_IGMP_EVENTS, want_igmp_events) \
55 
56 static void
58 {
60  vnet_main_t *vnm = vnet_get_main ();
61  igmp_main_t *im = &igmp_main;
62  vl_api_igmp_listen_reply_t *rmp;
63  int rv = 0;
64  ip46_address_t saddr, gaddr;
65 
66  if (!vnet_sw_interface_is_api_valid (vnm, ntohl (mp->sw_if_index)))
67  {
68  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
69  goto done;
70  }
71 
72  if ((vnet_sw_interface_get_flags (vnm, ntohl (mp->sw_if_index)) &&
74  {
75  rv = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
76  goto done;
77  }
78 
79  clib_memcpy (&saddr.ip4.as_u8, mp->saddr, sizeof (u8) * 4);
80  clib_memcpy (&gaddr.ip4.as_u8, mp->gaddr, sizeof (u8) * 4);
81 
82  rv = igmp_listen (vm, mp->enable, ntohl (mp->sw_if_index), saddr, gaddr, 1);
83 
84 done:;
87  if (!q)
88  return;
89 
90  rmp = vl_msg_api_alloc (sizeof (*rmp));
91  rmp->_vl_msg_id = htons ((VL_API_IGMP_LISTEN_REPLY) + im->msg_id_base);
92  rmp->context = mp->context;
93  rmp->retval = htonl (rv);
94 
95  vl_msg_api_send_shmem (q, (u8 *) & rmp);
96 }
97 
98 static void
100 {
101  vl_api_igmp_enable_disable_reply_t *rmp;
102  igmp_main_t *im = &igmp_main;
103  int rv = 0;
104 
105  REPLY_MACRO (VL_API_IGMP_ENABLE_DISABLE_REPLY + im->msg_id_base);
106 }
107 
108 static void
110  igmp_config_t * config, igmp_group_t * group,
111  igmp_src_t * src, u32 context)
112 {
114 
115  mp = vl_msg_api_alloc (sizeof (*mp));
116  memset (mp, 0, sizeof (*mp));
117 
118  mp->_vl_msg_id = htons (VL_API_IGMP_DETAILS + im->msg_id_base);
119  mp->context = context;
120  mp->sw_if_index = htonl (config->sw_if_index);
121  clib_memcpy (mp->saddr, &src->addr.ip4, sizeof (u8) * 4);
122  clib_memcpy (mp->gaddr, &group->addr.ip4, sizeof (u8) * 4);
123 
124  vl_msg_api_send_shmem (q, (u8 *) & mp);
125 }
126 
127 static void
129 {
130  igmp_main_t *im = &igmp_main;
131  igmp_config_t *config;
132  igmp_group_t *group;
133  igmp_src_t *src;
134 
137  if (!q)
138  return;
139 
140  if (mp->dump_all)
141  {
142  /* *INDENT-OFF* */
143  pool_foreach (config, im->configs, (
144  {
145  pool_foreach (group, config->groups, (
146  {
147  pool_foreach (src, group->srcs, (
148  {
149  send_igmp_details (q, im, config, group, src, mp->context);
150  }));
151  }));
152  }));
153  /* *INDENT-ON* */
154  return;
155  }
156  config = igmp_config_lookup (im, ntohl (mp->sw_if_index));
157  if (config)
158  {
159  /* *INDENT-OFF* */
160  pool_foreach (group, config->groups, (
161  {
162  pool_foreach (src, group->srcs, (
163  {
164  send_igmp_details (q, im, config, group, src, mp->context);
165  }));
166  }));
167  /* *INDENT-ON* */
168  }
169 }
170 
171 static void
173 {
174  igmp_main_t *im = &igmp_main;
175  igmp_config_t *config;
176  vl_api_igmp_clear_interface_reply_t *rmp;
177  int rv = 0;
178 
179  config = igmp_config_lookup (im, ntohl (mp->sw_if_index));
180  if (config)
181  igmp_clear_config (config);
182 
185  if (!q)
186  return;
187 
188  rmp = vl_msg_api_alloc (sizeof (*rmp));
189  rmp->_vl_msg_id =
190  htons ((VL_API_IGMP_CLEAR_INTERFACE_REPLY) + im->msg_id_base);
191  rmp->context = mp->context;
192  rmp->retval = htonl (rv);
193 
194  vl_msg_api_send_shmem (q, (u8 *) & rmp);
195 }
196 
197 /** \brief igmp group lookup
198  @param im - igmp main
199  @param client_index - client index
200 */
203 {
204  uword *p;
205  vpe_client_registration_t *api_client = NULL;
206 
207  p = hash_get (im->igmp_api_client_by_client_index, client_index);
208  if (p)
209  api_client = vec_elt_at_index (im->api_clients, p[0]);
210 
211  return api_client;
212 }
213 
214 static void
216 {
217  igmp_main_t *im = &igmp_main;
218  vpe_client_registration_t *api_client;
219  vl_api_want_igmp_events_reply_t *rmp;
220  int rv = 0;
221 
222  api_client = igmp_api_client_lookup (im, mp->client_index);
223  if (api_client)
224  {
225  if (mp->enable)
226  {
227  rv = VNET_API_ERROR_INVALID_REGISTRATION;
228  goto done;
229  }
231  api_client->client_index);
232  pool_put (im->api_clients, api_client);
233  goto done;
234  }
235  if (mp->enable)
236  {
237  pool_get (im->api_clients, api_client);
238  memset (api_client, 0, sizeof (vpe_client_registration_t));
239  api_client->client_index = mp->client_index;
240  api_client->client_pid = mp->pid;
242  mp->client_index, api_client - im->api_clients);
243  goto done;
244  }
245  rv = VNET_API_ERROR_INVALID_REGISTRATION;
246 
247 done:;
250  if (!q)
251  return;
252 
253  rmp = vl_msg_api_alloc (sizeof (*rmp));
254  rmp->_vl_msg_id = htons ((VL_API_WANT_IGMP_EVENTS_REPLY) + im->msg_id_base);
255  rmp->context = mp->context;
256  rmp->retval = htonl (rv);
257 
258  vl_msg_api_send_shmem (q, (u8 *) & rmp);
259 }
260 
261 static clib_error_t *
263 {
264  igmp_main_t *im = &igmp_main;
265  vpe_client_registration_t *api_client;
266  uword *p;
267 
268  p = hash_get (im->igmp_api_client_by_client_index, client_index);
269 
270  if (p)
271  {
272  api_client = pool_elt_at_index (im->api_clients, p[0]);
273  pool_put (im->api_clients, api_client);
274  hash_unset (im->igmp_api_client_by_client_index, client_index);
275  }
276  return (NULL);
277 }
278 
280 
281 void
283  igmp_main_t * im, igmp_config_t * config,
284  igmp_group_t * group, igmp_src_t * src)
285 {
286  vl_api_igmp_event_t *mp = vl_msg_api_alloc (sizeof (*mp));
287  memset (mp, 0, sizeof (*mp));
288 
289  mp->_vl_msg_id = ntohs ((VL_API_IGMP_EVENT) + im->msg_id_base);
290  mp->context = context;
291  mp->sw_if_index = htonl (config->sw_if_index);
292  clib_memcpy (&mp->saddr, &src->addr.ip4, sizeof (ip4_address_t));
293  clib_memcpy (&mp->gaddr, &group->addr.ip4, sizeof (ip4_address_t));
294  mp->is_join =
295  (group->type == IGMP_MEMBERSHIP_GROUP_mode_is_filter_include) ? 1 : 0;
296 
297  vl_msg_api_send_shmem (q, (u8 *) & mp);
298 }
299 
300 void
302  igmp_src_t * src)
303 {
304  vpe_client_registration_t *api_client;
306  /* *INDENT-OFF* */
307  pool_foreach (api_client, im->api_clients,
308  ({
309  q = vl_api_client_index_to_input_queue (api_client->client_index);
310  if (q)
311  send_igmp_event (q, 0, im, config, group, src);
312  }));
313  /* *INDENT-ON* */
314  if (group->type == IGMP_MEMBERSHIP_GROUP_block_old_sources)
315  {
316  igmp_clear_group (config, group);
317  if (pool_elts (config->groups) == 0)
318  {
320  pool_put (im->configs, config);
321  }
322  }
323 }
324 
325 #define vl_msg_name_crc_list
326 #include <igmp/igmp_all_api_h.h>
327 #undef vl_msg_name_crc_list
328 
329 static void
331 {
332 #define _(id,n,crc) \
333  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + im->msg_id_base);
334  foreach_vl_msg_name_crc_igmp;
335 #undef _
336 }
337 
338 /* Set up the API message handling tables */
339 static clib_error_t *
341 {
342  igmp_main_t *im = &igmp_main;
343  api_main_t *am = &api_main;
344  u8 *name;
345 
346  /* Construct the API name */
347  name = format (0, "igmp_%08x%c", api_version, 0);
348 
349  /* Ask for a correctly-sized block of API message decode slots */
351  ((char *) name, VL_MSG_FIRST_AVAILABLE);
352 
353 #define _(N,n) \
354  vl_msg_api_set_handlers((VL_API_##N + im->msg_id_base), \
355  #n, \
356  vl_api_##n##_t_handler, \
357  vl_noop_handler, \
358  vl_api_##n##_t_endian, \
359  vl_api_##n##_t_print, \
360  sizeof(vl_api_##n##_t), 1);
362 #undef _
363 
364  /*
365  * Set up the (msg_name, crc, message-id) table
366  */
367  setup_message_id_table (im, am);
368 
369  vec_free (name);
370  return 0;
371 }
372 
374 
375 /*
376  * fd.io coding-style-patch-verification: ON
377  *
378  * Local Variables:
379  * eval: (c-set-style "gnu")
380  * End:
381  */
igmp event details
Definition: igmp.api:130
#define foreach_igmp_plugin_api_msg
Definition: igmp_api.c:49
igmp_membership_group_v3_type_t type
Definition: igmp.h:121
static clib_error_t * igmp_plugin_api_hookup(vlib_main_t *vm)
Definition: igmp_api.c:340
Used by a &#39;router&#39; to enable the recption of IGMP packets and the construction of group state for hos...
Definition: igmp.api:50
#define hash_set(h, key, value)
Definition: hash.h:255
#define hash_unset(h, key)
Definition: hash.h:261
void igmp_event(igmp_main_t *im, igmp_config_t *config, igmp_group_t *group, igmp_src_t *src)
igmp event
Definition: igmp_api.c:301
remove all (S,G)s from an interface
Definition: igmp.api:94
void igmp_clear_group(igmp_config_t *config, igmp_group_t *group)
igmp clear group
Definition: igmp.c:37
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
igmp_main_t igmp_main
Definition: igmp.c:34
#define NULL
Definition: clib.h:55
igmp source
Definition: igmp.h:94
igmp_config_t * configs
Definition: igmp.h:208
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
ip46_address_t addr
Definition: igmp.h:115
dump (S,G)s from interface
Definition: igmp.api:65
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
void * vl_msg_api_alloc(int nbytes)
unsigned char u8
Definition: types.h:56
u16 msg_id_base
Definition: igmp.h:200
void igmp_clear_config(igmp_config_t *config)
igmp clear config
Definition: igmp.c:62
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:440
svm_queue_t unix_shared_memory_queue_t
Definition: queue.h:77
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned int u32
Definition: types.h:88
#define hash_get(h, key)
Definition: hash.h:249
static clib_error_t * want_igmp_events_reaper(u32 client_index)
Definition: igmp_api.c:262
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
uword * igmp_config_by_sw_if_index
Definition: igmp.h:206
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
Used by a &#39;host&#39; to enable the recption/listening of packets for a specific multicast group...
Definition: igmp.api:30
#define REPLY_MACRO(t)
VLIB_API_INIT_FUNCTION(igmp_plugin_api_hookup)
igmp details
Definition: igmp.api:80
void send_igmp_event(unix_shared_memory_queue_t *q, u32 context, igmp_main_t *im, igmp_config_t *config, igmp_group_t *group, igmp_src_t *src)
Definition: igmp_api.c:282
igmp main
Definition: igmp.h:198
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:201
static void setup_message_id_table(igmp_main_t *im, api_main_t *am)
Definition: igmp_api.c:330
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
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
Definition: igmp.h:204
ip46_address_t addr
Definition: igmp.h:96
#define clib_memcpy(a, b, c)
Definition: string.h:75
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:660
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
igmp configuration
Definition: igmp.h:144
int igmp_listen(vlib_main_t *vm, u8 enable, u32 sw_if_index, ip46_address_t saddr, ip46_address_t gaddr, u8 cli_api_configured)
igmp listen
Definition: igmp.c:738
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
VL_MSG_API_REAPER_FUNCTION(want_igmp_events_reaper)
static igmp_config_t * igmp_config_lookup(igmp_main_t *im, u32 sw_if_index)
igmp config lookup
Definition: igmp.h:403
static void vl_api_want_igmp_events_t_handler(vl_api_want_igmp_events_t *mp)
Definition: igmp_api.c:215
igmp group
Definition: igmp.h:113
u64 uword
Definition: types.h:112
u32 sw_if_index
Definition: igmp.h:146
static void vl_api_igmp_listen_t_handler(vl_api_igmp_listen_t *mp)
Definition: igmp_api.c:57
static void vl_api_igmp_enable_disable_t_handler(vl_api_igmp_enable_disable_t *mp)
Definition: igmp_api.c:99
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:109
static void vl_api_igmp_dump_t_handler(vl_api_igmp_dump_t *mp)
Definition: igmp_api.c:128
static vpe_client_registration_t * igmp_api_client_lookup(igmp_main_t *im, u32 client_index)
igmp group lookup
Definition: igmp_api.c:202
uword * igmp_api_client_by_client_index
Definition: igmp.h:202
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:172
api_main_t api_main
Definition: api_shared.c:35
igmp_group_t * groups
Definition: igmp.h:164
register for igmp events
Definition: igmp.api:108
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:872
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128