FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
igmp_cli.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 <stdint.h>
19 #include <sys/ioctl.h>
20 #include <inttypes.h>
21 
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/ip/ip.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 
31 static clib_error_t *
33  vlib_cli_command_t * cmd)
34 {
35  unformat_input_t _line_input, *line_input = &_line_input;
36  clib_error_t *error = NULL;
37  vnet_main_t *vnm = vnet_get_main ();
39 
40  igmp_config_t *config;
41 
42  if (!unformat_user (input, unformat_line_input, line_input))
43  {
44  error =
45  clib_error_return (0, "'help clear igmp' or 'clear igmp ?' for help");
46  return error;
47  }
48 
49  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
50  {
51  if (unformat
52  (line_input, "int %U", unformat_vnet_sw_interface, vnm,
53  &sw_if_index));
54  else
55  {
56  error =
57  clib_error_return (0, "unknown input '%U'", format_unformat_error,
58  line_input);
59  goto done;
60  }
61  }
62 
63  config = igmp_config_lookup (sw_if_index);
64  if (config)
65  igmp_clear_config (config);
66 
67 done:
68  unformat_free (line_input);
69  return error;
70 }
71 
72 /* *INDENT-OFF* */
73 VLIB_CLI_COMMAND (igmp_clear_interface_command, static) = {
74  .path = "clear igmp",
75  .short_help = "clear igmp int <interface>",
77 };
78 /* *INDENT-ON* */
79 
80 static clib_error_t *
82  vlib_cli_command_t * cmd)
83 {
84  unformat_input_t _line_input, *line_input = &_line_input;
85  clib_error_t *error = NULL;
86  u8 enable = 1;
87  ip46_address_t saddr, *saddrs = NULL, gaddr;
88  vnet_main_t *vnm = vnet_get_main ();
90  int rv;
91 
92  if (!unformat_user (input, unformat_line_input, line_input))
93  {
94  error =
96  "'help igmp listen' or 'igmp listen ?' for help");
97  return error;
98  }
99 
100  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
101  {
102  if (unformat (line_input, "enable"))
103  enable = 1;
104  else if (unformat (line_input, "disable"))
105  enable = 0;
106  else
107  if (unformat
108  (line_input, "int %U", unformat_vnet_sw_interface, vnm,
109  &sw_if_index));
110  else
111  if (unformat (line_input, "saddr %U", unformat_ip46_address, &saddr))
112  vec_add1 (saddrs, saddr);
113  else
114  if (unformat (line_input, "gaddr %U", unformat_ip46_address, &gaddr));
115  else
116  {
117  error =
118  clib_error_return (0, "unknown input '%U'", format_unformat_error,
119  line_input);
120  goto done;
121  }
122  }
123 
124  if ((vnet_sw_interface_get_flags (vnm, sw_if_index)
126  {
127  error = clib_error_return (0, "Interface is down");
128  goto done;
129  }
130 
131  rv = igmp_listen (vm, enable, sw_if_index, saddrs, &gaddr);
132 
133  if (rv == -1)
134  {
135  if (enable)
136  error =
137  clib_error_return (0, "This igmp configuration already exists");
138  else
139  error =
140  clib_error_return (0, "This igmp configuration does not exist");
141  }
142  else if (rv == -2)
143  error =
145  "Failed to add configuration, interface is in router mode");
146 
147 done:
148  unformat_free (line_input);
149  vec_free (saddrs);
150  return error;
151 }
152 
153 /* *INDENT-OFF* */
154 VLIB_CLI_COMMAND (igmp_listen_command, static) = {
155  .path = "igmp listen",
156  .short_help = "igmp listen [<enable|disable>] "
157  "int <interface> saddr <ip4-address> gaddr <ip4-address>",
158  .function = igmp_listen_command_fn,
159 };
160 /* *INDENT-ON* */
161 
162 static clib_error_t *
164  unformat_input_t * input, vlib_cli_command_t * cmd)
165 {
166  unformat_input_t _line_input, *line_input = &_line_input;
167  igmp_mode_t mode = IGMP_MODE_ROUTER;
168  vnet_main_t *vnm = vnet_get_main ();
169  clib_error_t *error = NULL;
170  u32 sw_if_index = ~0;
171  u8 enable = 1;
172  int rv;
173 
174  if (!unformat_user (input, unformat_line_input, line_input))
175  return error;
176 
177  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
178  {
179  if (unformat (line_input, "enable"))
180  enable = 1;
181  else if (unformat (line_input, "disable"))
182  enable = 0;
183  if (unformat (line_input, "host"))
184  mode = IGMP_MODE_HOST;
185  else if (unformat (line_input, "router"))
186  mode = IGMP_MODE_ROUTER;
187  else if (unformat (line_input, "%U",
188  unformat_vnet_sw_interface, vnm, &sw_if_index));
189  else
190  {
191  error =
192  clib_error_return (0, "unknown input '%U'", format_unformat_error,
193  line_input);
194  goto done;
195  }
196  }
197 
198  if (~0 == sw_if_index)
199  {
200  error = clib_error_return (0, "interface must be specified");
201  goto done;
202  }
203 
204  rv = igmp_enable_disable (sw_if_index, enable, mode);
205 
206  if (0 != rv)
207  error = clib_error_return (0, "result: %d", rv);
208 
209 done:
210  unformat_free (line_input);
211  return error;
212 }
213 
214 /* *INDENT-OFF* */
215 VLIB_CLI_COMMAND (igmp_enable_command, static) = {
216  .path = "igmp",
217  .short_help = "igmp <enable|disable> <host|router> <interface>",
218  .function = igmp_enable_cli,
219 };
220 /* *INDENT-ON* */
221 
222 static clib_error_t *
224  unformat_input_t * input,
225  vlib_cli_command_t * cmd)
226 {
227  unformat_input_t _line_input, *line_input = &_line_input;
228  vnet_main_t *vnm = vnet_get_main ();
229  clib_error_t *error = NULL;
230  u32 sw_if_index = ~0;
231  u32 vrf_id = ~0;
232  u8 add = 1;
233  int rv;
234 
235  if (!unformat_user (input, unformat_line_input, line_input))
236  return error;
237 
238  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
239  {
240  if (unformat (line_input, "add"))
241  add = 1;
242  else if (unformat (line_input, "del"))
243  add = 0;
244  else if (unformat (line_input, "vrf-id %u", &vrf_id))
245  ;
246  else if (unformat (line_input, "%U",
247  unformat_vnet_sw_interface, vnm, &sw_if_index));
248  else
249  {
250  error =
251  clib_error_return (0, "unknown input '%U'", format_unformat_error,
252  line_input);
253  goto done;
254  }
255  }
256 
257  if (~0 == sw_if_index)
258  {
259  error = clib_error_return (0, "interface must be specified");
260  goto done;
261  }
262 
263  if (~0 == vrf_id)
264  {
265  error = clib_error_return (0, "VRF must be specified");
266  goto done;
267  }
268 
269  rv = igmp_proxy_device_add_del (vrf_id, sw_if_index, add);
270 
271  if (0 != rv)
272  error = clib_error_return (0, "result: %d", rv);
273 
274 done:
275  unformat_free (line_input);
276  return error;
277 }
278 /* *INDENT-OFF* */
279 VLIB_CLI_COMMAND (igmp_proxy_device_add_del_command, static) = {
280  .path = "igmp proxy-dev",
281  .short_help = "igmp proxy-dev <add|del> vrf-id <table-id> <interface>",
283 };
284 /* *INDENT-ON* */
285 
286 static clib_error_t *
288  unformat_input_t * input,
289  vlib_cli_command_t * cmd)
290 {
291  unformat_input_t _line_input, *line_input = &_line_input;
292  vnet_main_t *vnm = vnet_get_main ();
293  clib_error_t *error = NULL;
294  u32 sw_if_index = ~0;
295  u32 vrf_id = ~0;
296  u8 add = 1;
297  int rv;
298 
299  if (!unformat_user (input, unformat_line_input, line_input))
300  return error;
301 
302  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
303  {
304  if (unformat (line_input, "add"))
305  add = 1;
306  else if (unformat (line_input, "del"))
307  add = 0;
308  else if (unformat (line_input, "vrf-id %u", &vrf_id))
309  ;
310  else if (unformat (line_input, "%U",
311  unformat_vnet_sw_interface, vnm, &sw_if_index));
312  else
313  {
314  error =
315  clib_error_return (0, "unknown input '%U'", format_unformat_error,
316  line_input);
317  goto done;
318  }
319  }
320 
321  if (~0 == sw_if_index)
322  {
323  error = clib_error_return (0, "interface must be specified");
324  goto done;
325  }
326 
327  if (~0 == vrf_id)
328  {
329  error = clib_error_return (0, "VRF must be specified");
330  goto done;
331  }
332 
333  rv = igmp_proxy_device_add_del_interface (vrf_id, sw_if_index, add);
334 
335  if (0 != rv)
336  error = clib_error_return (0, "result: %d", rv);
337 
338 done:
339  unformat_free (line_input);
340  return error;
341 }
342 /* *INDENT-OFF* */
343 VLIB_CLI_COMMAND (igmp_proxy_device_add_del_interface_command, static) = {
344  .path = "igmp proxy-dev itf",
345  .short_help = "igmp proxy-dev itf <add|del> vrf-id <table-id> <interface>",
347 };
348 /* *INDENT-ON* */
349 
350 static clib_error_t *
352  vlib_cli_command_t * cmd)
353 {
354  clib_error_t *error = NULL;
355  igmp_main_t *im = &igmp_main;
356  igmp_config_t *config;
357 
358  /* *INDENT-OFF* */
359  pool_foreach (config, im->configs,
360  ({
361  vlib_cli_output (vm, "%U", format_igmp_config, config);
362  }));
363  /* *INDENT-ON* */
364 
365  return error;
366 }
367 
368 /* *INDENT-OFF* */
369 VLIB_CLI_COMMAND (igmp_show_command, static) = {
370  .path = "show igmp config",
371  .short_help = "show igmp config",
372  .function = igmp_show_command_fn,
373 };
374 /* *INDENT-ON* */
375 
376 static clib_error_t *
378  unformat_input_t * input,
379  vlib_cli_command_t * cmd)
380 {
381 #define _(n,f) vlib_cli_output (vm, "%s: %d", #f, igmp_timer_type_get(n));
383 #undef _
384  return (NULL);
385 }
386 
387 /* *INDENT-OFF* */
388 VLIB_CLI_COMMAND (igmp_show_timers_command, static) = {
389  .path = "show igmp timers",
390  .short_help = "show igmp timers",
391  .function = igmp_show_timers_command_fn,
392 };
393 /* *INDENT-ON* */
394 
395 static clib_error_t *
397  unformat_input_t * input, vlib_cli_command_t * cmd)
398 {
399  clib_error_t *error = NULL;
400  u32 value;
401 
403  {
404  if (unformat (input, "query %d", &value))
405  igmp_timer_type_set (IGMP_TIMER_QUERY, value);
406  else if (unformat (input, "src %d", &value))
407  igmp_timer_type_set (IGMP_TIMER_SRC, value);
408  else if (unformat (input, "leave %d", &value))
409  igmp_timer_type_set (IGMP_TIMER_LEAVE, value);
410  else
411  error = clib_error_return (0, "query or src timers only");
412  }
413 
414  return error;
415 }
416 
417 /* *INDENT-OFF* */
418 VLIB_CLI_COMMAND (test_igmp_command, static) = {
419  .path = "test igmp timers",
420  .short_help = "Change the default values for IGMP timers - only sensible during unit tests",
421  .function = test_igmp_command_fn,
422 };
423 /* *INDENT-ON* */
424 
425 
426 clib_error_t *
428 {
429  return 0;
430 }
431 
433 
434 /*
435  * fd.io coding-style-patch-verification: ON
436  *
437  * Local Variables:
438  * eval: (c-set-style "gnu")
439  * End:
440  */
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
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
igmp_main_t igmp_main
Definition: igmp.c:36
igmp_config_t * configs
pool of configs
Definition: igmp.h:95
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
vlib_main_t * vm
Definition: in2out_ed.c:1582
unformat_function_t unformat_vnet_sw_interface
static clib_error_t * igmp_show_timers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:377
unsigned char u8
Definition: types.h:56
void igmp_clear_config(igmp_config_t *config)
igmp clear config
Definition: igmp_config.c:22
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static clib_error_t * igmp_proxy_device_add_del_interface_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:287
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
static clib_error_t * test_igmp_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:396
unformat_function_t unformat_line_input
Definition: format.h:283
igmp_config_t * igmp_config_lookup(u32 sw_if_index)
igmp config lookup
Definition: igmp_config.c:45
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
struct _unformat_input_t unformat_input_t
static clib_error_t * igmp_clear_interface_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:32
void igmp_timer_type_set(igmp_timer_type_t t, u32 v)
Definition: igmp_timer.c:75
static clib_error_t * igmp_listen_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:81
static clib_error_t * igmp_proxy_device_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:223
collection of data related to IGMP
Definition: igmp.h:63
vl_api_tunnel_mode_t mode
Definition: gre.api:48
vl_api_ip4_address_t gaddr
Definition: igmp.api:70
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
static clib_error_t * igmp_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:351
u8 value
Definition: qos.api:54
unformat_function_t unformat_ip46_address
Definition: format.h:63
IGMP interface configuration.
Definition: igmp_config.h:47
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
clib_error_t * igmp_cli_init(vlib_main_t *vm)
Definition: igmp_cli.c:427
enum igmp_mode_t_ igmp_mode_t
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static vnet_sw_interface_flags_t vnet_sw_interface_get_flags(vnet_main_t *vnm, u32 sw_if_index)
static clib_error_t * igmp_enable_cli(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: igmp_cli.c:163
u32 vrf_id
Definition: nat.api:944
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
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171