FD.io VPP  v18.04-17-g3a0d853
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_sg_t * sg, u32 context)
111 {
113 
114  mp = vl_msg_api_alloc (sizeof (*mp));
115  memset (mp, 0, sizeof (*mp));
116 
117  mp->_vl_msg_id = htons (VL_API_IGMP_DETAILS + im->msg_id_base);
118  mp->context = context;
119  mp->sw_if_index = htonl (config->sw_if_index);
120  clib_memcpy (mp->saddr, &sg->saddr.ip4, sizeof (u8) * 4);
121  clib_memcpy (mp->gaddr, &sg->gaddr.ip4, sizeof (u8) * 4);
122 
123  vl_msg_api_send_shmem (q, (u8 *) & mp);
124 }
125 
126 static void
128 {
129  igmp_main_t *im = &igmp_main;
130  igmp_config_t *config;
131  igmp_sg_t *sg;
132 
135  if (!q)
136  return;
137 
138  if (mp->dump_all)
139  {
140  /* *INDENT-OFF* */
141  pool_foreach (config, im->configs, (
142  {
143  pool_foreach (sg, config->sg, (
144  {
145  send_igmp_details (q, im, config, sg, mp->context);
146  }));
147  }));
148  /* *INDENT-ON* */
149  return;
150  }
151  config = igmp_config_lookup (im, ntohl (mp->sw_if_index));
152  if (config)
153  {
154  /* *INDENT-OFF* */
155  pool_foreach (sg, config->sg, (
156  {
157  send_igmp_details (q, im, config, sg, mp->context);
158  }));
159  /* *INDENT-ON* */
160  }
161 }
162 
163 static void
165 {
166  igmp_main_t *im = &igmp_main;
167  igmp_config_t *config;
168  vl_api_igmp_clear_interface_reply_t *rmp;
169  int rv = 0;
170 
171  config = igmp_config_lookup (im, ntohl (mp->sw_if_index));
172  if (config)
173  igmp_clear_config (config);
174 
177  if (!q)
178  return;
179 
180  rmp = vl_msg_api_alloc (sizeof (*rmp));
181  rmp->_vl_msg_id =
182  htons ((VL_API_IGMP_CLEAR_INTERFACE_REPLY) + im->msg_id_base);
183  rmp->context = mp->context;
184  rmp->retval = htonl (rv);
185 
186  vl_msg_api_send_shmem (q, (u8 *) & rmp);
187 }
188 
189 /** \brief igmp group lookup
190  @param im - igmp main
191  @param client_index - client index
192 */
195 {
196  uword *p;
197  vpe_client_registration_t *api_client = NULL;
198 
199  p = hash_get (im->igmp_api_client_by_client_index, client_index);
200  if (p)
201  api_client = vec_elt_at_index (im->api_clients, p[0]);
202 
203  return api_client;
204 }
205 
206 static void
208 {
209  igmp_main_t *im = &igmp_main;
210  vpe_client_registration_t *api_client;
211  vl_api_want_igmp_events_reply_t *rmp;
212  int rv = 0;
213 
214  api_client = igmp_api_client_lookup (im, mp->client_index);
215  if (api_client)
216  {
217  if (mp->enable)
218  {
219  rv = VNET_API_ERROR_INVALID_REGISTRATION;
220  goto done;
221  }
223  api_client->client_index);
224  pool_put (im->api_clients, api_client);
225  goto done;
226  }
227  if (mp->enable)
228  {
229  pool_get (im->api_clients, api_client);
230  memset (api_client, 0, sizeof (vpe_client_registration_t));
231  api_client->client_index = mp->client_index;
232  api_client->client_pid = mp->pid;
234  mp->client_index, api_client - im->api_clients);
235  goto done;
236  }
237  rv = VNET_API_ERROR_INVALID_REGISTRATION;
238 
239 done:;
242  if (!q)
243  return;
244 
245  rmp = vl_msg_api_alloc (sizeof (*rmp));
246  rmp->_vl_msg_id = htons ((VL_API_WANT_IGMP_EVENTS_REPLY) + im->msg_id_base);
247  rmp->context = mp->context;
248  rmp->retval = htonl (rv);
249 
250  vl_msg_api_send_shmem (q, (u8 *) & rmp);
251 }
252 
253 static clib_error_t *
255 {
256  igmp_main_t *im = &igmp_main;
257  vpe_client_registration_t *api_client;
258  uword *p;
259 
260  p = hash_get (im->igmp_api_client_by_client_index, client_index);
261 
262  if (p)
263  {
264  api_client = pool_elt_at_index (im->api_clients, p[0]);
265  pool_put (im->api_clients, api_client);
266  hash_unset (im->igmp_api_client_by_client_index, client_index);
267  }
268  return (NULL);
269 }
270 
272 
273 void
275  igmp_main_t * im, igmp_config_t * config, igmp_sg_t * sg)
276 {
277  vl_api_igmp_event_t *mp = vl_msg_api_alloc (sizeof (*mp));
278  memset (mp, 0, sizeof (*mp));
279 
280  mp->_vl_msg_id = ntohs ((VL_API_IGMP_EVENT) + im->msg_id_base);
281  mp->context = context;
282  mp->sw_if_index = htonl (config->sw_if_index);
283  clib_memcpy (&mp->saddr, &sg->saddr.ip4, sizeof (ip4_address_t));
284  clib_memcpy (&mp->gaddr, &sg->gaddr.ip4, sizeof (ip4_address_t));
285  mp->is_join =
286  (sg->group_type == IGMP_MEMBERSHIP_GROUP_mode_is_filter_include) ? 1 : 0;
287 
288  vl_msg_api_send_shmem (q, (u8 *) & mp);
289 }
290 
291 void
293 {
294  vpe_client_registration_t *api_client;
296  /* *INDENT-OFF* */
297  pool_foreach (api_client, im->api_clients,
298  ({
299  q = vl_api_client_index_to_input_queue (api_client->client_index);
300  if (q)
301  send_igmp_event (q, 0, im, config, sg);
302  }));
303  /* *INDENT-ON* */
304  if (sg->group_type == IGMP_MEMBERSHIP_GROUP_block_old_sources)
305  {
306  hash_unset_mem (config->igmp_sg_by_key, sg->key);
307  clib_mem_free (sg->key);
308  pool_put (config->sg, sg);
309  if (pool_elts (config->sg) == 0)
310  {
312  pool_put (im->configs, config);
313  }
314  }
315 }
316 
317 #define vl_msg_name_crc_list
318 #include <igmp/igmp_all_api_h.h>
319 #undef vl_msg_name_crc_list
320 
321 static void
323 {
324 #define _(id,n,crc) \
325  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + im->msg_id_base);
326  foreach_vl_msg_name_crc_igmp;
327 #undef _
328 }
329 
330 /* Set up the API message handling tables */
331 static clib_error_t *
333 {
334  igmp_main_t *im = &igmp_main;
335  api_main_t *am = &api_main;
336  u8 *name;
337 
338  /* Construct the API name */
339  name = format (0, "igmp_%08x%c", api_version, 0);
340 
341  /* Ask for a correctly-sized block of API message decode slots */
343  ((char *) name, VL_MSG_FIRST_AVAILABLE);
344 
345 #define _(N,n) \
346  vl_msg_api_set_handlers((VL_API_##N + im->msg_id_base), \
347  #n, \
348  vl_api_##n##_t_handler, \
349  vl_noop_handler, \
350  vl_api_##n##_t_endian, \
351  vl_api_##n##_t_print, \
352  sizeof(vl_api_##n##_t), 1);
354 #undef _
355 
356  /*
357  * Set up the (msg_name, crc, message-id) table
358  */
359  setup_message_id_table (im, am);
360 
361  vec_free (name);
362  return 0;
363 }
364 
366 
367 /*
368  * fd.io coding-style-patch-verification: ON
369  *
370  * Local Variables:
371  * eval: (c-set-style "gnu")
372  * End:
373  */
igmp event details
Definition: igmp.api:130
#define foreach_igmp_plugin_api_msg
Definition: igmp_api.c:49
static clib_error_t * igmp_plugin_api_hookup(vlib_main_t *vm)
Definition: igmp_api.c:332
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:254
#define hash_unset(h, key)
Definition: hash.h:260
remove all (S,G)s from an interface
Definition: igmp.api:94
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_config_t * configs
pool of igmp configurations
Definition: igmp.h:141
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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)
u16 msg_id_base
API message ID base.
Definition: igmp.h:129
void send_igmp_event(unix_shared_memory_queue_t *q, u32 context, igmp_main_t *im, igmp_config_t *config, igmp_sg_t *sg)
Definition: igmp_api.c:274
ip46_address_t saddr
Definition: igmp.h:76
void igmp_clear_config(igmp_config_t *config)
Definition: igmp.c:38
#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
void igmp_event(igmp_main_t *im, igmp_config_t *config, igmp_sg_t *sg)
Definition: igmp_api.c:292
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
igmp_membership_group_v3_type_t group_type
Definition: igmp.h:78
#define hash_get(h, key)
Definition: hash.h:248
static clib_error_t * want_igmp_events_reaper(u32 client_index)
Definition: igmp_api.c:254
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
#define hash_unset_mem(h, key)
Definition: hash.h:290
uword * igmp_config_by_sw_if_index
Definition: igmp.h:138
#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
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:199
static void setup_message_id_table(igmp_main_t *im, api_main_t *am)
Definition: igmp_api.c:322
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:739
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
vpe_client_registration_t * api_clients
pool of api clients registered for join/leave notifications
Definition: igmp.h:135
#define clib_memcpy(a, b, c)
Definition: string.h:75
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:588
igmp_sg_key_t * key
Definition: igmp.h:83
unsigned int u32
Definition: types.h:88
igmp_sg_t * sg
Definition: igmp.h:107
static void clib_mem_free(void *p)
Definition: mem.h:179
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u64 uword
Definition: types.h:112
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)
Definition: igmp.c:595
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)
Definition: igmp.h:233
unsigned char u8
Definition: types.h:56
static void vl_api_want_igmp_events_t_handler(vl_api_want_igmp_events_t *mp)
Definition: igmp_api.c:207
u32 sw_if_index
Definition: igmp.h:88
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
ip46_address_t gaddr
Definition: igmp.h:75
uword * igmp_sg_by_key
Definition: igmp.h:104
static void vl_api_igmp_dump_t_handler(vl_api_igmp_dump_t *mp)
Definition: igmp_api.c:127
static vpe_client_registration_t * igmp_api_client_lookup(igmp_main_t *im, u32 client_index)
igmp group lookup
Definition: igmp_api.c:194
uword * igmp_api_client_by_client_index
Definition: igmp.h:132
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:164
api_main_t api_main
Definition: api_shared.c:35
register for igmp events
Definition: igmp.api:108
static void send_igmp_details(unix_shared_memory_queue_t *q, igmp_main_t *im, igmp_config_t *config, igmp_sg_t *sg, u32 context)
Definition: igmp_api.c:109
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