FD.io VPP  v18.10-32-g1161dda
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  vlib_cli_command_t * cmd)
225 {
226  clib_error_t *error = NULL;
227  igmp_main_t *im = &igmp_main;
228  vnet_main_t *vnm = vnet_get_main ();
229  igmp_config_t *config;
230  igmp_group_t *group;
231  igmp_src_t *src;
232 
233  /* *INDENT-OFF* */
234  pool_foreach (config, im->configs,
235  ({
236  vlib_cli_output (vm, "interface: %U mode:%U",
237  format_vnet_sw_if_index_name, vnm, config->sw_if_index,
238  format_igmp_mode, config->mode);
239 
240  FOR_EACH_GROUP (group, config,
241  ({
242  vlib_cli_output (vm, "\t%U", format_igmp_key, group->key);
243  FOR_EACH_SRC (src, group, IGMP_FILTER_MODE_INCLUDE,
244  ({
245  vlib_cli_output (vm, "\t\t%U", format_igmp_key, src->key);
246  }));
247  }));
248  }));
249  /* *INDENT-ON* */
250 
251  return error;
252 }
253 
254 /* *INDENT-OFF* */
255 VLIB_CLI_COMMAND (igmp_show_command, static) = {
256  .path = "show igmp config",
257  .short_help = "show igmp config",
258  .function = igmp_show_command_fn,
259 };
260 /* *INDENT-ON* */
261 
262 static clib_error_t *
264  unformat_input_t * input,
265  vlib_cli_command_t * cmd)
266 {
267 #define _(n,f) vlib_cli_output (vm, "%s: %d", #f, igmp_timer_type_get(n));
269 #undef _
270  return (NULL);
271 }
272 
273 /* *INDENT-OFF* */
274 VLIB_CLI_COMMAND (igmp_show_timers_command, static) = {
275  .path = "show igmp timers",
276  .short_help = "show igmp timers",
277  .function = igmp_show_timers_command_fn,
278 };
279 /* *INDENT-ON* */
280 
281 static clib_error_t *
283  unformat_input_t * input, vlib_cli_command_t * cmd)
284 {
285  clib_error_t *error = NULL;
286  u32 value;
287 
289  {
290  if (unformat (input, "query %d", &value))
291  igmp_timer_type_set (IGMP_TIMER_QUERY, value);
292  else if (unformat (input, "src %d", &value))
293  igmp_timer_type_set (IGMP_TIMER_SRC, value);
294  else if (unformat (input, "leave %d", &value))
295  igmp_timer_type_set (IGMP_TIMER_LEAVE, value);
296  else
297  error = clib_error_return (0, "query or src timers only");
298  }
299 
300  return error;
301 }
302 
303 /* *INDENT-OFF* */
304 VLIB_CLI_COMMAND (test_igmp_command, static) = {
305  .path = "test igmp timers",
306  .short_help = "Change the default values for IGMP timers - only sensible during unit tests",
307  .function = test_igmp_command_fn,
308 };
309 /* *INDENT-ON* */
310 
311 
312 clib_error_t *
314 {
315  return 0;
316 }
317 
319 
320 /*
321  * fd.io coding-style-patch-verification: ON
322  *
323  * Local Variables:
324  * eval: (c-set-style "gnu")
325  * End:
326  */
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
vl_api_address_t src
Definition: vxlan_gbp.api:33
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
igmp_main_t igmp_main
Definition: igmp.c:36
#define NULL
Definition: clib.h:57
igmp_config_t * configs
pool of configs
Definition: igmp.h:94
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
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:263
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:443
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
u32 sw_if_index
Definition: vxlan_gbp.api:39
#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:282
unformat_function_t unformat_line_input
Definition: format.h:282
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
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
collection of data related to IGMP
Definition: igmp.h:62
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
vlib_main_t * vm
Definition: buffer.c:294
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
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:223
unformat_function_t unformat_ip46_address
Definition: format.h:65
IGMP interface configuration.
Definition: igmp_config.h:43
IGMP group A multicast group address for which reception has been requested.
Definition: igmp_group.h:55
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
clib_error_t * igmp_cli_init(vlib_main_t *vm)
Definition: igmp_cli.c:313
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
IGMP source The representation of a specified source address with in multicast group.
Definition: igmp_src.h:41
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170