FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
igmp_input.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 <vlib/vlib.h>
19 #include <vlibmemory/api.h>
20 #include <vnet/plugin/plugin.h>
21 #include <vpp/app/version.h>
22 #include <vnet/ip/ip.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/adj/adj_mcast.h>
25 
26 #include <igmp/igmp.h>
27 #include <igmp/igmp_pkt.h>
28 #include <igmp/igmp_query.h>
29 #include <igmp/igmp_report.h>
30 #include <igmp/igmp_error.h>
31 
32 #include <limits.h>
33 
34 typedef enum
35 {
41 
42 typedef enum
43 {
47 
48 typedef enum
49 {
53 
54 char *igmp_error_strings[] = {
55 #define _(sym,string) string,
57 #undef _
58 };
59 
60 typedef struct
61 {
65  u8 packet_data[64];
67 
68 static u8 *
69 format_igmp_input_trace (u8 * s, va_list * va)
70 {
71  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
72  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
73  igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *);
74 
75  s = format (s, "sw_if_index %u next-index %u",
76  t->sw_if_index, t->next_index);
77  s = format (s, "\n%U", format_igmp_header, t->packet_data,
78  sizeof (t->packet_data));
79  return s;
80 }
81 
82 static u8 *
84 {
85  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
86  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
87  igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *);
88 
89  s = format (s, "sw_if_index %u next-index %u",
90  t->sw_if_index, t->next_index);
91  s = format (s, "\n%U", format_igmp_report_v3, t->packet_data,
92  sizeof (t->packet_data));
93  return s;
94 }
95 
96 static u8 *
97 format_igmp_parse_query_trace (u8 * s, va_list * va)
98 {
99  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
100  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
101  igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *);
102 
103  s = format (s, "sw_if_index %u next-input %u len %u",
104  t->sw_if_index, t->next_index, t->len);
105  s = format (s, "\n%U", format_igmp_query_v3, t->packet_data,
106  sizeof (t->packet_data));
107  s = format (s, "\n%U", format_hex_bytes,
108  t->packet_data, sizeof (t->packet_data));
109  return s;
110 }
111 
112 static uword
115 {
117  u32 n_left_from, *from, *to_next;
118  vlib_node_runtime_t *error_node;
119  u8 error;
120 
121  error = IGMP_ERROR_NONE;
122  error_node = node;
123 
125  n_left_from = frame->n_vectors;
126  next_index = node->cached_next_index;
127 
128  while (n_left_from > 0)
129  {
130  u32 n_left_to_next;
131 
132  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
133 
134  while (n_left_from > 0 && n_left_to_next > 0)
135  {
136  igmp_header_t *igmp;
137  u16 checksum, csum;
138  vlib_buffer_t *b;
139  ip4_header_t *ip;
140  ip_csum_t sum;
141  u32 bi, next;
142 
144  bi = from[0];
145  to_next[0] = bi;
146  from++;
147  to_next++;
148  n_left_from--;
149  n_left_to_next--;
150 
151  b = vlib_get_buffer (vm, bi);
153 
154  if (ip->protocol != IP_PROTOCOL_IGMP)
155  {
156  error = IGMP_ERROR_INVALID_PROTOCOL;
158  goto next_buffer;
159  }
160 
162 
163  igmp = vlib_buffer_get_current (b);
164 
165  checksum = igmp->checksum;
166  igmp->checksum = 0;
167  sum = ip_incremental_checksum (0, igmp,
168  clib_net_to_host_u16 (ip->length) -
169  ip4_header_bytes (ip));
170  igmp->checksum = checksum;
171  csum = ~ip_csum_fold (sum);
172  if (checksum != csum)
173  {
174  error = IGMP_ERROR_BAD_CHECKSUM;
176  goto next_buffer;
177  }
179  {
180  error = IGMP_ERROR_NOT_ENABLED;
182  goto next_buffer;
183  }
184 
185  /* TODO: IGMPv2 and IGMPv1 */
186  switch (igmp->type)
187  {
188  case IGMP_TYPE_membership_query:
190  break;
191  case IGMP_TYPE_membership_report_v3:
193  break;
194  default:
195  error = IGMP_ERROR_UNKNOWN_TYPE;
197  break;
198  }
199  next_buffer:
200  b->error = error_node->errors[error];
201 
202  if (node->flags & VLIB_NODE_FLAG_TRACE)
203  {
204  igmp_input_trace_t *tr;
205  tr = vlib_add_trace (vm, node, b, sizeof (*tr));
206  tr->next_index = next;
207  tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
210  sizeof (tr->packet_data));
211  }
212 
214  n_left_to_next, bi, next);
215  }
216  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
217  }
218 
219  return frame->n_vectors;
220 }
221 
222 /* *INDENT-OFF* */
224 {
225  .function = igmp_input,
226  .name = "igmp-input",
227  .vector_size = sizeof (u32),
228 
229  .format_buffer = format_igmp_header,
230  .format_trace = format_igmp_input_trace,
231 
232  .n_errors = IGMP_N_ERROR,
233  .error_strings = igmp_error_strings,
234 
235  .n_next_nodes = IGMP_INPUT_N_NEXT,
236  .next_nodes = {
237  [IGMP_INPUT_NEXT_DROP] = "error-drop",
238  [IGMP_INPUT_NEXT_PARSE_QUERY] = "igmp-parse-query",
239  [IGMP_INPUT_NEXT_PARSE_REPORT] = "igmp-parse-report",
240  }
241 };
242 /* *INDENT-ON* */
243 
244 static uword
247 {
248  u32 n_left_from, *from, *to_next;
250 
252  n_left_from = frame->n_vectors;
253  next_index = node->cached_next_index;
254 
255  while (n_left_from > 0)
256  {
257  u32 n_left_to_next;
258 
259  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
260 
261  while (n_left_from > 0 && n_left_to_next > 0)
262  {
264  igmp_query_args_t *args;
265  u32 bi, next, len;
266  vlib_buffer_t *b;
267 
269  bi = from[0];
270  to_next[0] = bi;
271  from++;
272  to_next++;
273  n_left_from--;
274  n_left_to_next--;
275 
276  b = vlib_get_buffer (vm, bi);
277  igmp = vlib_buffer_get_current (b);
278  ASSERT (igmp->header.type == IGMP_TYPE_membership_query);
280 
281  if (node->flags & VLIB_NODE_FLAG_TRACE)
282  {
283  igmp_input_trace_t *tr;
284  tr = vlib_add_trace (vm, node, b, sizeof (*tr));
285  tr->next_index = next;
286  tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
287  tr->len = len;
289  sizeof (tr->packet_data));
290  }
291 
292  /*
293  * validate that the length on the packet on the wire corresponds
294  * to at least the length of the calculated v3 query.
295  * If there's extra, then it will be ignored.
296  */
298  {
299  /*
300  * copy the contents of the query, and the interface, over
301  * to the main thread for processing
302  */
303  vlib_buffer_advance (b, -sizeof (u32));
304  args = vlib_buffer_get_current (b);
305  args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
306 
308  (u8 *) args, sizeof (*args) + len);
309  }
310  else
311  {
312  /*
313  * else a packet that is reporting more sources than it really
314  * has; bin it
315  */
316  b->error = node->errors[IGMP_ERROR_BAD_LENGTH];
317  }
318 
320  n_left_to_next, bi, next);
321  }
322  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
323  }
324 
325  return frame->n_vectors;
326 }
327 
328 /* *INDENT-OFF* */
330 {
331  .function = igmp_parse_query,
332  .name = "igmp-parse-query",
333  .vector_size = sizeof (u32),
334 
335  .format_buffer = format_igmp_query_v3,
336  .format_trace = format_igmp_parse_query_trace,
337 
338  .n_errors = IGMP_N_ERROR,
339  .error_strings = igmp_error_strings,
340 
341  .n_next_nodes = IGMP_PARSE_QUERY_N_NEXT,
342  .next_nodes = {
343  [IGMP_PARSE_QUERY_NEXT_DROP] = "error-drop",
344  }
345 };
346 /* *INDENT-ON* */
347 
348 static uword
351 {
352  u32 n_left_from, *from, *to_next;
354  vlib_node_runtime_t *error_node =
356  u8 error;
357 
359  n_left_from = frame->n_vectors;
360  next_index = node->cached_next_index;
361 
362  while (n_left_from > 0)
363  {
364  u32 n_left_to_next;
365 
366  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
367 
368  while (n_left_from > 0 && n_left_to_next > 0)
369  {
371  igmp_report_args_t *args;
372  u32 bi, next, len;
373  vlib_buffer_t *b;
374 
376 
377  bi = from[0];
378  to_next[0] = bi;
379  from++;
380  to_next++;
381  n_left_from--;
382  n_left_to_next--;
383 
384  b = vlib_get_buffer (vm, bi);
385 
386  error = IGMP_ERROR_NONE;
387  b->error = error_node->errors[error];
388  igmp = vlib_buffer_get_current (b);
390 
391  ASSERT (igmp->header.type == IGMP_TYPE_membership_report_v3);
392 
393  if (node->flags & VLIB_NODE_FLAG_TRACE)
394  {
395  igmp_input_trace_t *tr;
396  tr = vlib_add_trace (vm, node, b, sizeof (*tr));
397  tr->next_index = next;
398  tr->len = len;
399  tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
401  sizeof (tr->packet_data));
402  }
403 
404  /*
405  * validate that the length on the packet on the wire
406  * corresponds to the length on the calculated v3 query
407  */
409  {
410  /*
411  * copy the contents of the query, and the interface, over
412  * to the main thread for processing
413  */
414  vlib_buffer_advance (b, -sizeof (u32));
415  args = vlib_buffer_get_current (b);
416  args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
417 
419  (u8 *) args, sizeof (*args) + len);
420  }
421  else
422  {
423  /*
424  * this is a packet with more groups/sources than the
425  * header reports. bin it
426  */
427  b->error = node->errors[IGMP_ERROR_BAD_LENGTH];
428  }
429 
431  n_left_to_next, bi, next);
432  }
433  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
434  }
435 
436  return frame->n_vectors;
437 }
438 
439 /* *INDENT-OFF* */
441 {
442  .function = igmp_parse_report,
443  .name = "igmp-parse-report",
444  .vector_size = sizeof (u32),
445 
446  .format_buffer = format_igmp_report_v3,
447  .format_trace = format_igmp_parse_report_trace,
448 
449  .n_errors = IGMP_N_ERROR,
450  .error_strings = igmp_error_strings,
451 
452  .n_next_nodes = IGMP_PARSE_REPORT_N_NEXT,
453  .next_nodes = {
454  [IGMP_PARSE_REPORT_NEXT_DROP] = "error-drop",
455  }
456 };
457 /* *INDENT-ON* */
458 
459 static clib_error_t *
461 {
462  ip4_register_protocol (IP_PROTOCOL_IGMP, igmp_input_node.index);
463 
464  IGMP_DBG ("input-initialized");
465 
466  return (0);
467 }
468 
469 /* *INDENT-OFF* */
471 {
472  .runs_after = VLIB_INITS("igmp_init"),
473 };
474 /* *INDENT-ON* */
475 
476 /*
477  * fd.io coding-style-patch-verification: ON
478  *
479  * Local Variables:
480  * eval: (c-set-style "gnu")
481  * End:
482  */
vlib.h
api.h
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
IGMP_DBG
#define IGMP_DBG(...)
Definition: igmp.h:38
format_igmp_query_v3
u8 * format_igmp_query_v3(u8 *s, va_list *args)
Definition: igmp_format.c:146
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
igmp_report_args_t_
A copy of the report message sent from the worker to the main thread.
Definition: igmp_report.h:23
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
igmp_input
static uword igmp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: igmp_input.c:113
format_igmp_header
u8 * format_igmp_header(u8 *s, va_list *args)
Definition: igmp_format.c:80
igmp_membership_report_v3_length
static u32 igmp_membership_report_v3_length(const igmp_membership_report_v3_t *r)
Definition: igmp_packet.h:193
igmp_header_t::type
igmp_type_t type
Definition: igmp_packet.h:70
next
u16 * next
Definition: nat44_ei_out2in.c:718
igmp_parse_report_next_t
igmp_parse_report_next_t
Definition: igmp_input.c:48
format_hex_bytes
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
IGMP_PARSE_REPORT_N_NEXT
@ IGMP_PARSE_REPORT_N_NEXT
Definition: igmp_input.c:51
igmp.h
adj_mcast.h
u16
unsigned short u16
Definition: types.h:57
igmp_header_t::checksum
u16 checksum
Definition: igmp_packet.h:74
igmp_input_trace_t
Definition: igmp_input.c:60
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
igmp_error_strings
char * igmp_error_strings[]
Definition: igmp_input.c:54
igmp_report.h
igmp_report_args_t_::sw_if_index
u32 sw_if_index
Definition: igmp_report.h:25
igmp_membership_report_v3_t
Definition: igmp_packet.h:179
ip4_register_protocol
void ip4_register_protocol(u32 protocol, u32 node_index)
Definition: ip4_forward.c:1895
igmp_query.h
igmp_config_lookup
igmp_config_t * igmp_config_lookup(u32 sw_if_index)
igmp config lookup
Definition: igmp_config.c:45
vlib_frame_t
Definition: node.h:372
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
ip4_header_t
Definition: ip4_packet.h:87
error
Definition: cJSON.c:88
vlib_node_runtime_t::errors
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:460
IGMP_PARSE_REPORT_NEXT_DROP
@ IGMP_PARSE_REPORT_NEXT_DROP
Definition: igmp_input.c:50
igmp_input_trace_t::packet_data
u8 packet_data[64]
Definition: igmp_input.c:65
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
format_igmp_input_trace
static u8 * format_igmp_input_trace(u8 *s, va_list *va)
Definition: igmp_input.c:69
format_igmp_parse_query_trace
static u8 * format_igmp_parse_query_trace(u8 *s, va_list *va)
Definition: igmp_input.c:97
len
u8 len
Definition: ip_types.api:103
IGMP_INPUT_NEXT_DROP
@ IGMP_INPUT_NEXT_DROP
Definition: igmp_input.c:36
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
foreach_igmp_error
#define foreach_igmp_error
Definition: igmp_error.h:21
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
ip_incremental_checksum
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:319
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
uword
u64 uword
Definition: types.h:112
igmp_handle_report
void igmp_handle_report(const igmp_report_args_t *args)
Definition: igmp_report.c:216
igmp_parse_query
static uword igmp_parse_query(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: igmp_input.c:245
igmp_parse_report_node
vlib_node_registration_t igmp_parse_report_node
(constructor) VLIB_REGISTER_NODE (igmp_parse_report_node)
Definition: igmp_input.c:440
IGMP_PARSE_QUERY_NEXT_DROP
@ IGMP_PARSE_QUERY_NEXT_DROP
Definition: igmp_input.c:44
igmp_parse_report
static uword igmp_parse_report(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: igmp_input.c:349
igmp_membership_query_v3_length
static u32 igmp_membership_query_v3_length(const igmp_membership_query_v3_t *q)
Definition: igmp_packet.h:119
igmp_input_trace_t::next_index
u32 next_index
Definition: igmp_input.c:62
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
plugin.h
igmp_input_init
static clib_error_t * igmp_input_init(vlib_main_t *vm)
Definition: igmp_input.c:460
vlib_validate_buffer_enqueue_x1
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
format_igmp_parse_report_trace
static u8 * format_igmp_parse_report_trace(u8 *s, va_list *va)
Definition: igmp_input.c:83
igmp_handle_query
void igmp_handle_query(const igmp_query_args_t *args)
Called from the main thread on reception of a Query message.
Definition: igmp_query.c:174
IGMP_PARSE_QUERY_N_NEXT
@ IGMP_PARSE_QUERY_N_NEXT
Definition: igmp_input.c:45
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
ip.h
u32
unsigned int u32
Definition: types.h:88
igmp_error.h
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
IGMP_INPUT_NEXT_PARSE_REPORT
@ IGMP_INPUT_NEXT_PARSE_REPORT
Definition: igmp_input.c:38
IGMP_INPUT_N_NEXT
@ IGMP_INPUT_N_NEXT
Definition: igmp_input.c:39
igmp_input_next_t
igmp_input_next_t
Definition: igmp_input.c:34
vl_api_rpc_call_main_thread
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: vlib_api.c:620
IGMP_INPUT_NEXT_PARSE_QUERY
@ IGMP_INPUT_NEXT_PARSE_QUERY
Definition: igmp_input.c:37
vlib_node_get_runtime
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:116
igmp_parse_query_next_t
igmp_parse_query_next_t
Definition: igmp_input.c:42
igmp_query_args_t_::sw_if_index
u32 sw_if_index
Definition: igmp_query.h:25
vlib_main_t
Definition: main.h:102
igmp_parse_query_node
vlib_node_registration_t igmp_parse_query_node
(constructor) VLIB_REGISTER_NODE (igmp_parse_query_node)
Definition: igmp_input.c:329
vlib_node_t
Definition: node.h:247
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
VLIB_INITS
#define VLIB_INITS(...)
Definition: init.h:352
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
unix.h
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip
vl_api_address_t ip
Definition: l2.api:558
igmp_input_trace_t::sw_if_index
u32 sw_if_index
Definition: igmp_input.c:63
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
ip_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
ip4_header_bytes
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:190
igmp_membership_query_v3_t::header
igmp_header_t header
Definition: igmp_packet.h:103
vlib_node_runtime_t
Definition: node.h:454
igmp_query_args_t_
A copy of the query message sent from the worker to the main thread.
Definition: igmp_query.h:23
from
from
Definition: nat44_ei_hairpinning.c:415
igmp_membership_report_v3_t::header
igmp_header_t header
Definition: igmp_packet.h:182
igmp_pkt.h
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vlib_get_next_frame
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
ip_csum_fold
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
igmp_input_trace_t::len
u32 len
Definition: igmp_input.c:64
format_igmp_report_v3
u8 * format_igmp_report_v3(u8 *s, va_list *args)
Definition: igmp_format.c:100
igmp_header_t
Definition: igmp_packet.h:68
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
igmp_membership_query_v3_t
Definition: igmp_packet.h:100
igmp_input_node
vlib_node_registration_t igmp_input_node
(constructor) VLIB_REGISTER_NODE (igmp_input_node)
Definition: igmp_input.c:223
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
IGMP_N_ERROR
@ IGMP_N_ERROR
Definition: igmp_error.h:35