Line data Source code
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 *
32 0 : igmp_clear_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
33 : vlib_cli_command_t * cmd)
34 : {
35 0 : unformat_input_t _line_input, *line_input = &_line_input;
36 0 : clib_error_t *error = NULL;
37 0 : vnet_main_t *vnm = vnet_get_main ();
38 : u32 sw_if_index;
39 :
40 : igmp_config_t *config;
41 :
42 0 : if (!unformat_user (input, unformat_line_input, line_input))
43 : {
44 : error =
45 0 : clib_error_return (0, "'help clear igmp' or 'clear igmp ?' for help");
46 0 : return error;
47 : }
48 :
49 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
50 : {
51 0 : if (unformat
52 : (line_input, "int %U", unformat_vnet_sw_interface, vnm,
53 : &sw_if_index));
54 : else
55 : {
56 : error =
57 0 : clib_error_return (0, "unknown input '%U'", format_unformat_error,
58 : line_input);
59 0 : goto done;
60 : }
61 : }
62 :
63 0 : config = igmp_config_lookup (sw_if_index);
64 0 : if (config)
65 0 : igmp_clear_config (config);
66 :
67 0 : done:
68 0 : unformat_free (line_input);
69 0 : return error;
70 : }
71 :
72 : /* *INDENT-OFF* */
73 206953 : VLIB_CLI_COMMAND (igmp_clear_interface_command, static) = {
74 : .path = "clear igmp",
75 : .short_help = "clear igmp int <interface>",
76 : .function = igmp_clear_interface_command_fn,
77 : };
78 : /* *INDENT-ON* */
79 :
80 : static clib_error_t *
81 0 : igmp_listen_command_fn (vlib_main_t * vm, unformat_input_t * input,
82 : vlib_cli_command_t * cmd)
83 : {
84 0 : unformat_input_t _line_input, *line_input = &_line_input;
85 0 : clib_error_t *error = NULL;
86 0 : u8 enable = 1;
87 0 : ip46_address_t saddr, *saddrs = NULL, gaddr;
88 0 : vnet_main_t *vnm = vnet_get_main ();
89 : u32 sw_if_index;
90 : int rv;
91 :
92 0 : if (!unformat_user (input, unformat_line_input, line_input))
93 : {
94 : error =
95 0 : clib_error_return (0,
96 : "'help igmp listen' or 'igmp listen ?' for help");
97 0 : return error;
98 : }
99 :
100 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
101 : {
102 0 : if (unformat (line_input, "enable"))
103 0 : enable = 1;
104 0 : else if (unformat (line_input, "disable"))
105 0 : enable = 0;
106 : else
107 0 : if (unformat
108 : (line_input, "int %U", unformat_vnet_sw_interface, vnm,
109 : &sw_if_index));
110 : else
111 0 : if (unformat (line_input, "saddr %U", unformat_ip46_address, &saddr))
112 0 : vec_add1 (saddrs, saddr);
113 : else
114 0 : if (unformat (line_input, "gaddr %U", unformat_ip46_address, &gaddr));
115 : else
116 : {
117 : error =
118 0 : clib_error_return (0, "unknown input '%U'", format_unformat_error,
119 : line_input);
120 0 : goto done;
121 : }
122 : }
123 :
124 0 : if ((vnet_sw_interface_get_flags (vnm, sw_if_index)
125 : && VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0)
126 : {
127 0 : error = clib_error_return (0, "Interface is down");
128 0 : goto done;
129 : }
130 :
131 0 : rv = igmp_listen (vm, enable, sw_if_index, saddrs, &gaddr);
132 :
133 0 : if (rv == -1)
134 : {
135 0 : if (enable)
136 : error =
137 0 : clib_error_return (0, "This igmp configuration already exists");
138 : else
139 : error =
140 0 : clib_error_return (0, "This igmp configuration does not exist");
141 : }
142 0 : else if (rv == -2)
143 : error =
144 0 : clib_error_return (0,
145 : "Failed to add configuration, interface is in router mode");
146 :
147 0 : done:
148 0 : unformat_free (line_input);
149 0 : vec_free (saddrs);
150 0 : return error;
151 : }
152 :
153 : /* *INDENT-OFF* */
154 206953 : 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 *
163 0 : igmp_enable_cli (vlib_main_t * vm,
164 : unformat_input_t * input, vlib_cli_command_t * cmd)
165 : {
166 0 : unformat_input_t _line_input, *line_input = &_line_input;
167 0 : igmp_mode_t mode = IGMP_MODE_ROUTER;
168 0 : vnet_main_t *vnm = vnet_get_main ();
169 0 : clib_error_t *error = NULL;
170 0 : u32 sw_if_index = ~0;
171 0 : u8 enable = 1;
172 : int rv;
173 :
174 0 : if (!unformat_user (input, unformat_line_input, line_input))
175 0 : return error;
176 :
177 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
178 : {
179 0 : if (unformat (line_input, "enable"))
180 0 : enable = 1;
181 0 : else if (unformat (line_input, "disable"))
182 0 : enable = 0;
183 0 : if (unformat (line_input, "host"))
184 0 : mode = IGMP_MODE_HOST;
185 0 : else if (unformat (line_input, "router"))
186 0 : mode = IGMP_MODE_ROUTER;
187 0 : else if (unformat (line_input, "%U",
188 : unformat_vnet_sw_interface, vnm, &sw_if_index));
189 : else
190 : {
191 : error =
192 0 : clib_error_return (0, "unknown input '%U'", format_unformat_error,
193 : line_input);
194 0 : goto done;
195 : }
196 : }
197 :
198 0 : if (~0 == sw_if_index)
199 : {
200 0 : error = clib_error_return (0, "interface must be specified");
201 0 : goto done;
202 : }
203 :
204 0 : rv = igmp_enable_disable (sw_if_index, enable, mode);
205 :
206 0 : if (0 != rv)
207 0 : error = clib_error_return (0, "result: %d", rv);
208 :
209 0 : done:
210 0 : unformat_free (line_input);
211 0 : return error;
212 : }
213 :
214 : /* *INDENT-OFF* */
215 206953 : 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 *
223 0 : igmp_proxy_device_add_del_command_fn (vlib_main_t * vm,
224 : unformat_input_t * input,
225 : vlib_cli_command_t * cmd)
226 : {
227 0 : unformat_input_t _line_input, *line_input = &_line_input;
228 0 : vnet_main_t *vnm = vnet_get_main ();
229 0 : clib_error_t *error = NULL;
230 0 : u32 sw_if_index = ~0;
231 0 : u32 vrf_id = ~0;
232 0 : u8 add = 1;
233 : int rv;
234 :
235 0 : if (!unformat_user (input, unformat_line_input, line_input))
236 0 : return error;
237 :
238 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
239 : {
240 0 : if (unformat (line_input, "add"))
241 0 : add = 1;
242 0 : else if (unformat (line_input, "del"))
243 0 : add = 0;
244 0 : else if (unformat (line_input, "vrf-id %u", &vrf_id))
245 : ;
246 0 : else if (unformat (line_input, "%U",
247 : unformat_vnet_sw_interface, vnm, &sw_if_index));
248 : else
249 : {
250 : error =
251 0 : clib_error_return (0, "unknown input '%U'", format_unformat_error,
252 : line_input);
253 0 : goto done;
254 : }
255 : }
256 :
257 0 : if (~0 == sw_if_index)
258 : {
259 0 : error = clib_error_return (0, "interface must be specified");
260 0 : goto done;
261 : }
262 :
263 0 : if (~0 == vrf_id)
264 : {
265 0 : error = clib_error_return (0, "VRF must be specified");
266 0 : goto done;
267 : }
268 :
269 0 : rv = igmp_proxy_device_add_del (vrf_id, sw_if_index, add);
270 :
271 0 : if (0 != rv)
272 0 : error = clib_error_return (0, "result: %d", rv);
273 :
274 0 : done:
275 0 : unformat_free (line_input);
276 0 : return error;
277 : }
278 : /* *INDENT-OFF* */
279 206953 : 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>",
282 : .function = igmp_proxy_device_add_del_command_fn,
283 : };
284 : /* *INDENT-ON* */
285 :
286 : static clib_error_t *
287 0 : igmp_proxy_device_add_del_interface_command_fn (vlib_main_t * vm,
288 : unformat_input_t * input,
289 : vlib_cli_command_t * cmd)
290 : {
291 0 : unformat_input_t _line_input, *line_input = &_line_input;
292 0 : vnet_main_t *vnm = vnet_get_main ();
293 0 : clib_error_t *error = NULL;
294 0 : u32 sw_if_index = ~0;
295 0 : u32 vrf_id = ~0;
296 0 : u8 add = 1;
297 : int rv;
298 :
299 0 : if (!unformat_user (input, unformat_line_input, line_input))
300 0 : return error;
301 :
302 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
303 : {
304 0 : if (unformat (line_input, "add"))
305 0 : add = 1;
306 0 : else if (unformat (line_input, "del"))
307 0 : add = 0;
308 0 : else if (unformat (line_input, "vrf-id %u", &vrf_id))
309 : ;
310 0 : else if (unformat (line_input, "%U",
311 : unformat_vnet_sw_interface, vnm, &sw_if_index));
312 : else
313 : {
314 : error =
315 0 : clib_error_return (0, "unknown input '%U'", format_unformat_error,
316 : line_input);
317 0 : goto done;
318 : }
319 : }
320 :
321 0 : if (~0 == sw_if_index)
322 : {
323 0 : error = clib_error_return (0, "interface must be specified");
324 0 : goto done;
325 : }
326 :
327 0 : if (~0 == vrf_id)
328 : {
329 0 : error = clib_error_return (0, "VRF must be specified");
330 0 : goto done;
331 : }
332 :
333 0 : rv = igmp_proxy_device_add_del_interface (vrf_id, sw_if_index, add);
334 :
335 0 : if (0 != rv)
336 0 : error = clib_error_return (0, "result: %d", rv);
337 :
338 0 : done:
339 0 : unformat_free (line_input);
340 0 : return error;
341 : }
342 : /* *INDENT-OFF* */
343 206953 : 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>",
346 : .function = igmp_proxy_device_add_del_interface_command_fn,
347 : };
348 : /* *INDENT-ON* */
349 :
350 : static clib_error_t *
351 1 : igmp_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
352 : vlib_cli_command_t * cmd)
353 : {
354 1 : clib_error_t *error = NULL;
355 1 : igmp_main_t *im = &igmp_main;
356 : igmp_config_t *config;
357 :
358 : /* *INDENT-OFF* */
359 2 : pool_foreach (config, im->configs)
360 : {
361 1 : vlib_cli_output (vm, "%U", format_igmp_config, config);
362 : }
363 : /* *INDENT-ON* */
364 :
365 1 : return error;
366 : }
367 :
368 : /* *INDENT-OFF* */
369 206953 : 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 *
377 0 : igmp_show_timers_command_fn (vlib_main_t * vm,
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));
382 0 : foreach_igmp_timer_type
383 : #undef _
384 0 : return (NULL);
385 : }
386 :
387 : /* *INDENT-OFF* */
388 206953 : 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 *
396 2 : test_igmp_command_fn (vlib_main_t * vm,
397 : unformat_input_t * input, vlib_cli_command_t * cmd)
398 : {
399 2 : clib_error_t *error = NULL;
400 : u32 value;
401 :
402 8 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
403 : {
404 6 : if (unformat (input, "query %d", &value))
405 2 : igmp_timer_type_set (IGMP_TIMER_QUERY, value);
406 4 : else if (unformat (input, "src %d", &value))
407 2 : igmp_timer_type_set (IGMP_TIMER_SRC, value);
408 2 : else if (unformat (input, "leave %d", &value))
409 2 : igmp_timer_type_set (IGMP_TIMER_LEAVE, value);
410 : else
411 0 : error = clib_error_return (0, "query or src timers only");
412 : }
413 :
414 2 : return error;
415 : }
416 :
417 : /* *INDENT-OFF* */
418 206953 : 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 *
427 575 : igmp_cli_init (vlib_main_t * vm)
428 : {
429 575 : return 0;
430 : }
431 :
432 1151 : VLIB_INIT_FUNCTION (igmp_cli_init);
433 :
434 : /*
435 : * fd.io coding-style-patch-verification: ON
436 : *
437 : * Local Variables:
438 : * eval: (c-set-style "gnu")
439 : * End:
440 : */
|