FD.io VPP  v18.10-34-gcce845e
Vector Packet Processing
igmp.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 <vnet/plugin/plugin.h>
20 #include <vpp/app/version.h>
21 #include <vnet/ip/ip.h>
22 #include <vnet/mfib/mfib_entry.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/adj/adj_mcast.h>
25 #include <vnet/fib/fib_entry.h>
26 #include <vnet/fib/fib_table.h>
27 #include <vnet/mfib/mfib_table.h>
28 
29 #include <igmp/igmp.h>
30 #include <igmp/igmp_format.h>
31 #include <igmp/igmp_pkt.h>
32 
33 #include <limits.h>
34 #include <float.h>
35 
37 
38 /* *INDENT-OFF* */
39 /* General Query address */
40 const static mfib_prefix_t mpfx_general_query = {
42  .fp_len = 32,
43  .fp_grp_addr = {
44  .ip4 = {
46  },
47  },
48 };
49 
50 /* Report address */
51 const static mfib_prefix_t mpfx_report = {
53  .fp_len = 32,
54  .fp_grp_addr = {
55  .ip4 = {
57  },
58  },
59 };
60 /* *INDENT-ON* */
61 
62 /**
63  * @brief igmp send query (igmp_timer_function_t)
64  *
65  * Send an igmp query.
66  * If the timer holds group key, send Group-Specific query,
67  * else send General query.
68  */
69 static void
70 igmp_send_general_query (u32 obj, void *dat)
71 {
73  igmp_config_t *config;
74 
75  config = igmp_config_get (obj);
76 
77  IGMP_DBG ("send-general-query: %U",
79  config->sw_if_index);
80 
82 
86 
87  /*
88  * re-schedule
89  */
91  igmp_timer_schedule (igmp_timer_type_get (IGMP_TIMER_QUERY),
92  igmp_config_index (config),
94 }
95 
96 static void
98  const igmp_group_t * group)
99 {
101 
102  IGMP_DBG ("state-change-group: %U", format_igmp_key, group->key);
103 
104  igmp_pkt_build_report_init (&br, sw_if_index);
106  group,
107  IGMP_MEMBERSHIP_GROUP_allow_new_sources);
109 }
110 
111 static void
113 {
114  igmp_config_t *config;
115  igmp_group_t *group;
116 
117  group = igmp_group_get (gi);
118  config = igmp_config_get (group->config);
119 
122 
123  if (++group->n_reports_sent < config->robustness_var)
124  {
126  igmp_timer_schedule (igmp_timer_type_get (IGMP_TIMER_REPORT_INTERVAL),
127  igmp_group_index (group),
129  }
130 }
131 
132 int
134  igmp_filter_mode_t mode,
136  const ip46_address_t * saddrs, const ip46_address_t * gaddr)
137 {
138  const ip46_address_t *saddr;
139  igmp_config_t *config;
140  igmp_group_t *group;
141 
142  /*
143  * RFC 3376 Section 2
144  " For a given combination of socket, interface, and multicast address,
145  only a single filter mode and source list can be in effect at any one
146  time. However, either the filter mode or the source list, or both,
147  may be changed by subsequent IPMulticastListen requests that specify
148  the same socket, interface, and multicast address. Each subsequent
149  request completely replaces any earlier request for the given socket,
150  interface and multicast address."
151  */
152  int rv = 0;
153  IGMP_DBG ("listen: (%U, %U) %U %U",
155  format_igmp_key, gaddr,
157  sw_if_index, format_igmp_filter_mode, mode);
158  /*
159  * find configuration, if it doesn't exist, then this interface is
160  * not IGMP enabled
161  */
162  config = igmp_config_lookup (sw_if_index);
163 
164  if (!config)
165  {
166  rv = VNET_API_ERROR_INVALID_INTERFACE;
167  goto error;
168  }
169  if (config->mode != IGMP_MODE_HOST)
170  {
171  rv = VNET_API_ERROR_INVALID_INTERFACE;
172  goto error;
173  }
174 
175  /* find igmp group, if it doesn't exist, create new */
176  group = igmp_group_lookup (config, gaddr);
177 
178  if (!group)
179  {
180  group = igmp_group_alloc (config, gaddr, mode);
181 
182  /* new group implies create all sources */
183  vec_foreach (saddr, saddrs)
184  {
185  igmp_group_src_update (group, saddr, IGMP_MODE_HOST);
186  }
187 
188  /*
189  * Send state changed event report for the group.
190  *
191  * RFC3376 Section 5.1
192  * "To cover the possibility of the State-Change Report being missed by
193  * one or more multicast routers, it is retransmitted [Robustness
194  * Variable] - 1 more times, at intervals chosen at random from the
195  * range (0, [Unsolicited Report Interval])."
196  */
198 
200 
201  group->n_reports_sent = 1;
203  igmp_timer_schedule (igmp_timer_type_get (IGMP_TIMER_REPORT_INTERVAL),
204  igmp_group_index (group),
206  }
207  else
208  {
209  IGMP_DBG ("... update (%U, %U) %U %U",
211  format_igmp_key, gaddr,
213  sw_if_index, format_igmp_filter_mode, mode);
214 
215  /*
216  * RFC 3367 Section 5.1
217  *
218  * Old State New State State-Change Record Sent
219  * --------- --------- ------------------------
220  *
221  * 1) INCLUDE (A) INCLUDE (B) ALLOW (B-A), BLOCK (A-B)
222  * 2) EXCLUDE (A) EXCLUDE (B) ALLOW (A-B), BLOCK (B-A)
223  * 3) INCLUDE (A) EXCLUDE (B) TO_EX (B)
224  * 4) EXCLUDE (A) INCLUDE (B) TO_IN (B)
225  *
226  * N.B. We do not split state-change records for pending transfer
227  * hence there is no merge logic required.
228  */
229 
230  if (IGMP_FILTER_MODE_INCLUDE == mode)
231  {
232  ip46_address_t *added, *removed;
234 
235  /*
236  * find the list of sources that have been added and removed from
237  * the include set
238  */
239  removed =
240  igmp_group_present_minus_new (group, IGMP_FILTER_MODE_INCLUDE,
241  saddrs);
242  added =
243  igmp_group_new_minus_present (group, IGMP_FILTER_MODE_INCLUDE,
244  saddrs);
245 
246  if (!(vec_len (added) || vec_len (removed)))
247  /* no change => done */
248  goto error;
249 
251 
252  if (vec_len (added))
253  {
255  group->key,
256  added,
257  IGMP_MEMBERSHIP_GROUP_allow_new_sources);
258  }
259 
260  if (vec_len (removed))
261  {
263  group->key,
264  removed,
265  IGMP_MEMBERSHIP_GROUP_block_old_sources);
266  }
267 
268  IGMP_DBG ("... added %U", format_igmp_src_addr_list, added);
269  IGMP_DBG ("... removed %U", format_igmp_src_addr_list, removed);
270 
272 
273  /*
274  * clear the group of the old sources and populate it with the new
275  * set requested
276  */
277  igmp_group_free_all_srcs (group);
278 
279  vec_foreach (saddr, saddrs)
280  {
281  igmp_group_src_update (group, saddr, IGMP_MODE_HOST);
282  }
283 
284  if (0 == igmp_group_n_srcs (group, mode))
285  igmp_group_clear (group);
286 
287  vec_free (added);
288  vec_free (removed);
289  }
290  else
291  {
292  /*
293  * The control plane is excluding some sources.
294  * - First; check for those that are present in the include list
295  * - Second; check add them to the exclude list
296  *
297  * TODO
298  */
299  }
300  }
301 
302 error:
303  return (rv);
304 }
305 
306 /** \brief igmp hardware interface link up down
307  @param vnm - vnet main
308  @param hw_if_index - interface hw_if_index
309  @param flags - hw interface flags
310 
311  If an interface goes down, remove its (S,G)s.
312 */
313 static walk_rc_t
315 {
316  igmp_config_t *config;
317  config = igmp_config_lookup (sw_if_index);
318  IGMP_DBG ("down: %U",
320  if (NULL != config)
321  {
322  igmp_clear_config (config);
323  }
324 
325  return (WALK_CONTINUE);
326 }
327 
328 static clib_error_t *
330 {
331  clib_error_t *error = NULL;
332  /* remove igmp state from down interfaces */
333  if (!(flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
334  vnet_hw_interface_walk_sw (vnm, hw_if_index, igmp_sw_if_down, NULL);
335  return error;
336 }
337 
339 int
341 {
342  igmp_config_t *config;
343  igmp_main_t *im = &igmp_main;
344  u32 mfib_index;
345  IGMP_DBG ("%s: %U", (enable ? "Enabled" : "Disabled"),
347 
348  /* *INDENT-OFF* */
349  fib_route_path_t for_us_path =
350  {
352  .frp_addr = zero_addr,
353  .frp_sw_if_index = 0xffffffff,
354  .frp_fib_index = 0,
355  .frp_weight = 1,
356  .frp_flags = FIB_ROUTE_PATH_LOCAL,
357  };
358  fib_route_path_t via_itf_path =
359  {
361  .frp_addr = zero_addr,
362  .frp_sw_if_index = sw_if_index,
363  .frp_fib_index = 0,
364  .frp_weight = 1,
365  };
366  /* *INDENT-ON* */
367  /* find configuration, if it doesn't exist, create new */
368  config = igmp_config_lookup (sw_if_index);
370  sw_if_index);
371  if (!config && enable)
372  {
373  u32 ii;
374 
376  sw_if_index, ~0);
377  pool_get (im->configs, config);
378  memset (config, 0, sizeof (igmp_config_t));
379  config->sw_if_index = sw_if_index;
380  config->igmp_group_by_key =
381  hash_create_mem (0, sizeof (igmp_key_t), sizeof (uword));
383  config->mode = mode;
384 
385  for (ii = 0; ii < IGMP_CONFIG_N_TIMERS; ii++)
386  config->timers[ii] = IGMP_TIMER_ID_INVALID;
387 
388  if (IGMP_MODE_ROUTER == mode)
389  {
391  igmp_timer_schedule (igmp_timer_type_get (IGMP_TIMER_QUERY),
392  igmp_config_index (config),
394  }
395 
396  config->adj_index =
398  config->sw_if_index);
400  (config - im->configs);
401  {
402  vec_validate (im->n_configs_per_mfib_index, mfib_index);
403  im->n_configs_per_mfib_index[mfib_index]++;
404  if (1 == im->n_configs_per_mfib_index[mfib_index])
405  {
406  /* first config in this FIB */
407  mfib_table_entry_path_update (mfib_index,
408  &mpfx_general_query,
410  &for_us_path,
412  mfib_table_entry_path_update (mfib_index,
413  &mpfx_report,
415  &for_us_path,
417  }
418  mfib_table_entry_path_update (mfib_index,
419  &mpfx_general_query,
421  &via_itf_path, MFIB_ITF_FLAG_ACCEPT);
422  mfib_table_entry_path_update (mfib_index, &mpfx_report,
423  MFIB_SOURCE_IGMP, &via_itf_path,
425  }
426  }
427  else if (config && !enable)
428  {
429  vec_validate (im->n_configs_per_mfib_index, mfib_index);
430  im->n_configs_per_mfib_index[mfib_index]--;
431  if (0 == im->n_configs_per_mfib_index[mfib_index])
432  {
433  /* last config in this FIB */
434  mfib_table_entry_path_remove (mfib_index,
435  &mpfx_general_query,
436  MFIB_SOURCE_IGMP, &for_us_path);
437  mfib_table_entry_path_remove (mfib_index,
438  &mpfx_report,
439  MFIB_SOURCE_IGMP, &for_us_path);
440  }
441 
442  mfib_table_entry_path_remove (mfib_index,
443  &mpfx_general_query,
444  MFIB_SOURCE_IGMP, &via_itf_path);
445  mfib_table_entry_path_remove (mfib_index,
446  &mpfx_report,
447  MFIB_SOURCE_IGMP, &via_itf_path);
448  igmp_clear_config (config);
449  im->igmp_config_by_sw_if_index[config->sw_if_index] = ~0;
450  hash_free (config->igmp_group_by_key);
451  pool_put (im->configs, config);
452  }
453  else
454  {
455  return -1;
456  }
457 
458  return (0);
459 }
460 
461 /** \brief igmp initialization
462  @param vm - vlib main
463 
464  initialize igmp plugin. Initialize igmp_main, set mfib to allow igmp traffic.
465 */
466 static clib_error_t *
468 {
469  clib_error_t *error;
470  igmp_main_t *im = &igmp_main;
471 
472  if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
473  return error;
474 
475  im->igmp_api_client_by_client_index = hash_create (0, sizeof (u32));
476 
477  im->logger = vlib_log_register_class ("igmp", 0);
478 
479  IGMP_DBG ("initialized");
480 
481  return (error);
482 }
483 
485 /* *INDENT-OFF* */
487  .version = VPP_BUILD_VER,
488  .description = "IGMP messaging",
489 };
490 /* *INDENT-ON* */
491 
492 /*
493  * fd.io coding-style-patch-verification: ON
494  *
495  * Local Variables:
496  * eval: (c-set-style "gnu")
497  * End:
498  */
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
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:227
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
igmp_timer_id_t timers[IGMP_CONFIG_N_TIMERS]
A vector of scheduled query-response timers.
Definition: igmp_config.h:73
u8 * format_igmp_src_addr_list(u8 *s, va_list *args)
Definition: igmp_format.c:186
u8 * format_igmp_key(u8 *s, va_list *args)
Definition: igmp_format.c:203
void igmp_pkt_query_v3_send(igmp_pkt_build_query_t *bq)
Definition: igmp_pkt.c:516
static void igmp_send_state_change_group_report_v3(u32 sw_if_index, const igmp_group_t *group)
Definition: igmp.c:97
void igmp_timer_retire(igmp_timer_id_t *tid)
Definition: igmp_timer.c:222
igmp_group_t * igmp_group_lookup(igmp_config_t *config, const igmp_key_t *key)
igmp group lookup
Definition: igmp_config.c:76
A representation of a path as described by a route producer.
Definition: fib_types.h:470
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static clib_error_t * ip4_lookup_init(vlib_main_t *vm)
Definition: ip4_forward.c:903
igmp_main_t igmp_main
Definition: igmp.c:36
void vnet_hw_interface_walk_sw(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_sw_interface_walk_t fn, void *ctx)
Walk the SW interfaces on a HW interface - this is the super interface and any sub-interfaces.
Definition: interface.c:982
void igmp_group_free_all_srcs(igmp_group_t *group)
Definition: igmp_group.c:22
#define NULL
Definition: clib.h:57
igmp_config_t * configs
pool of configs
Definition: igmp.h:94
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(igmp_hw_interface_link_up_down)
adj_index_t adj_index
Definition: igmp_config.h:53
Timer running to resend report.
Definition: igmp_group.h:41
void igmp_pkt_report_v3_add_group(igmp_pkt_build_report_t *br, const igmp_group_t *group, igmp_membership_group_v3_type_t type)
Definition: igmp_pkt.c:352
igmp_src_t * igmp_group_src_update(igmp_group_t *group, const igmp_key_t *skey, igmp_mode_t mode)
Definition: igmp_group.c:45
static clib_error_t * igmp_hw_interface_link_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: igmp.c:329
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:475
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:494
#define IGMP_GENERAL_QUERY_ADDRESS
General Query address - 224.0.0.1 Membership Report address - 224.0.0.22 SSM default range 232/8...
Definition: igmp.h:50
static clib_error_t * igmp_init(vlib_main_t *vm)
igmp initialization
Definition: igmp.c:467
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
void igmp_pkt_build_report_init(igmp_pkt_build_report_t *br, u32 sw_if_index)
Definition: igmp_pkt.c:403
#define IGMP_DBG(...)
Definition: igmp.h:37
igmp_timer_id_t igmp_timer_schedule(f64 when, u32 obj, igmp_timer_function_t fn, void *data)
Schedule a timer to expire in &#39;when&#39; seconds.
Definition: igmp_timer.c:196
void igmp_clear_config(igmp_config_t *config)
igmp clear config
Definition: igmp_config.c:22
u32 igmp_timer_type_get(igmp_timer_type_t t)
Definition: igmp_timer.c:68
enum walk_rc_t_ walk_rc_t
Walk return code.
memset(h->entries, 0, sizeof(h->entries[0])*entries)
u32 n_reports_sent
The number of times the last report has been sent.
Definition: igmp_group.h:81
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
u32 mfib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: mfib_table.c:392
u32 sw_if_index
Definition: vxlan_gbp.api:39
ip46_address_t * igmp_group_present_minus_new(igmp_group_t *group, igmp_filter_mode_t mode, const ip46_address_t *saddrs)
the set of present sources minus the new set
Definition: igmp_group.c:126
u32 igmp_config_index(const igmp_config_t *c)
Get the pool index for a config.
Definition: igmp_config.c:64
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath, mfib_itf_flags_t itf_flags)
Add n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:219
igmp_config_t * igmp_config_get(u32 index)
Get the config from the pool index.
Definition: igmp_config.c:70
unsigned int u32
Definition: types.h:88
#define vlib_call_init_function(vm, x)
Definition: init.h:260
void igmp_pkt_report_v3_send(igmp_pkt_build_report_t *br)
Definition: igmp_pkt.c:211
uword * igmp_group_by_key
Database of groups joined on the link.
Definition: igmp_config.h:68
igmp_config_t * igmp_config_lookup(u32 sw_if_index)
igmp config lookup
Definition: igmp_config.c:45
#define IGMP_CONFIG_N_TIMERS
Definition: igmp_config.h:38
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
int igmp_enable_disable(u32 sw_if_index, u8 enable, igmp_mode_t mode)
IGMP interface enable/disable.
Definition: igmp.c:340
#define IGMP_DEFAULT_ROBUSTNESS_VARIABLE
RFC 3376 Section 8.1.
Definition: igmp.h:35
vlib_log_class_t logger
logger - VLIB log class
Definition: igmp.h:89
long ctx[MAX_CONNS]
Definition: main.c:144
u32 config
The pool index of the config object this group is in.
Definition: igmp_group.h:76
#define IGMP_MEMBERSHIP_REPORT_ADDRESS
Definition: igmp.h:51
#define hash_free(h)
Definition: hash.h:310
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
collection of data related to IGMP
Definition: igmp.h:62
u32 flags
Definition: vhost_user.h:115
igmp_group_t * igmp_group_alloc(igmp_config_t *config, const igmp_key_t *gkey, igmp_filter_mode_t mode)
Definition: igmp_group.c:95
vlib_main_t * vm
Definition: buffer.c:294
u32 timers[IGMP_GROUP_N_TIMERS]
A vector of running timers for the group.
Definition: igmp_group.h:66
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
u32 * igmp_config_by_sw_if_index
per-interface DB of configs
Definition: igmp.h:79
void igmp_pkt_query_v3_add_group(igmp_pkt_build_query_t *bq, const igmp_group_t *group, const ip46_address_t *srcs)
Definition: igmp_pkt.c:451
enum igmp_filter_mode_t_ igmp_filter_mode_t
Aggregrate type for a prefix.
Definition: mfib_types.h:24
#define IGMP_TIMER_ID_INVALID
Definition: igmp_timer.h:28
VLIB_PLUGIN_REGISTER()
#define hash_create(elts, value_bytes)
Definition: hash.h:696
void igmp_pkt_report_v3_add_report(igmp_pkt_build_report_t *br, const ip46_address_t *grp, const ip46_address_t *srcs, igmp_membership_group_v3_type_t type)
Definition: igmp_pkt.c:312
igmp_group_t * igmp_group_get(u32 index)
Definition: igmp_group.c:261
u32 * n_configs_per_mfib_index
the number of igmp configs for each mfib_index (VRF)
Definition: igmp.h:84
u8 * format_igmp_filter_mode(u8 *s, va_list *args)
Definition: igmp_format.c:50
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:237
ip46_address_t igmp_key_t
IGMP Key Used to index groups within an interface config and sources within a list.
Definition: igmp_types.h:49
u8 robustness_var
Robustness variable (section 5.1)
Definition: igmp_config.h:63
IGMP interface configuration.
Definition: igmp_config.h:43
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
A for-us/local path.
Definition: fib_types.h:332
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
igmp_key_t * key
The group&#39;s key within the per-interface config.
Definition: igmp_group.h:58
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_send_general_query(u32 obj, void *dat)
igmp send query (igmp_timer_function_t)
Definition: igmp.c:70
void igmp_pkt_build_query_init(igmp_pkt_build_query_t *bq, u32 sw_if_index)
Definition: igmp_pkt.c:526
enum igmp_mode_t_ igmp_mode_t
adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto, vnet_link_t link_type, u32 sw_if_index)
Mcast Adjacency.
Definition: adj_mcast.c:51
static void igmp_resend_state_change_group_report_v3(u32 gi, void *data)
Definition: igmp.c:112
On expiry send a general query.
Definition: igmp_config.h:35
#define vec_foreach(var, vec)
Vector iterator.
uword * igmp_api_client_by_client_index
Definition: igmp.h:69
ip46_address_t * igmp_group_new_minus_present(igmp_group_t *group, igmp_filter_mode_t mode, const ip46_address_t *saddrs)
the set of new sources minus the present set
Definition: igmp_group.c:172
igmp_mode_t mode
Definition: igmp_config.h:58
u32 igmp_group_n_srcs(const igmp_group_t *group, igmp_filter_mode_t mode)
Definition: igmp_group.c:233
void igmp_group_clear(igmp_group_t *group)
Definition: igmp_group.c:68
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
void mfib_table_entry_path_remove(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath)
Remove n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:251
u32 igmp_group_index(const igmp_group_t *g)
Definition: igmp_group.c:255
const ip46_address_t zero_addr
Definition: lookup.c:318
static walk_rc_t igmp_sw_if_down(vnet_main_t *vnm, u32 sw_if_index, void *ctx)
igmp hardware interface link up down
Definition: igmp.c:314