BFD: command line interface
[vpp.git] / src / vnet / bfd / bfd_cli.c
1 /*
2  * Copyright (c) 2011-2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief BFD CLI implementation
18  */
19
20 #include <vlib/vlib.h>
21 #include <vlib/cli.h>
22 #include <vppinfra/format.h>
23 #include <vnet/api_errno.h>
24 #include <vnet/ip/format.h>
25 #include <vnet/bfd/bfd_api.h>
26 #include <vnet/bfd/bfd_main.h>
27
28 static u8 *
29 format_bfd_session_cli (u8 * s, va_list * args)
30 {
31   bfd_main_t *bm = va_arg (*args, bfd_main_t *);
32   bfd_session_t *bs = va_arg (*args, bfd_session_t *);
33   switch (bs->transport)
34     {
35     case BFD_TRANSPORT_UDP4:
36       s = format (s, "%=10u %-32s %20U %20U\n", bs->bs_idx, "IPv4 address",
37                   format_ip4_address, bs->udp.key.local_addr.ip4.as_u8,
38                   format_ip4_address, bs->udp.key.peer_addr.ip4.as_u8);
39       break;
40     case BFD_TRANSPORT_UDP6:
41       s = format (s, "%=10u %-32s %20U %20U\n", bs->bs_idx, "IPv6 address",
42                   format_ip6_address, &bs->udp.key.local_addr.ip6,
43                   format_ip6_address, &bs->udp.key.peer_addr.ip6);
44       break;
45     }
46   s = format (s, "%10s %-32s %20s %20s\n", "", "Session state",
47               bfd_state_string (bs->local_state),
48               bfd_state_string (bs->remote_state));
49   s = format (s, "%10s %-32s %20s %20s\n", "", "Diagnostic code",
50               bfd_diag_code_string (bs->local_diag),
51               bfd_diag_code_string (bs->remote_diag));
52   s = format (s, "%10s %-32s %20u %20u\n", "", "Detect multiplier",
53               bs->local_detect_mult, bs->remote_detect_mult);
54   s = format (s, "%10s %-32s %20u %20u\n", "",
55               "Required Min Rx Interval (usec)",
56               bs->config_required_min_rx_usec, bs->remote_min_rx_usec);
57   s = format (s, "%10s %-32s %20u %20u\n", "",
58               "Desired Min Tx Interval (usec)",
59               bs->config_desired_min_tx_usec, bfd_clocks_to_usec (bm,
60                                                                   bs->remote_desired_min_tx_clocks));
61   s =
62     format (s, "%10s %-32s %20u\n", "", "Transmit interval",
63             bfd_clocks_to_usec (bm, bs->transmit_interval_clocks));
64   s =
65     format (s, "%10s %-32s %20s %20s\n", "", "Demand mode", "no",
66             bs->remote_demand ? "yes" : "no");
67   s =
68     format (s, "%10s %-32s %20s\n", "", "Poll state",
69             bfd_poll_state_string (bs->poll_state));
70   if (bs->auth.curr_key)
71     {
72       s = format (s, "%10s %-32s %20u\n", "", "Authentication config key ID",
73                   bs->auth.curr_key->conf_key_id);
74       s = format (s, "%10s %-32s %20u\n", "", "Authentication BFD key ID",
75                   bs->auth.curr_bfd_key_id);
76     }
77   return s;
78 }
79
80 static clib_error_t *
81 show_bfd (vlib_main_t * vm, unformat_input_t * input,
82           CLIB_UNUSED (vlib_cli_command_t * lmd))
83 {
84   bfd_main_t *bm = &bfd_main;
85   bfd_session_t *bs = NULL;
86
87   if (unformat (input, "keys"))
88     {
89       bfd_auth_key_t *key = NULL;
90       u8 *s = format (NULL, "%=10s %=25s %=10s\n", "Configuration Key ID",
91                       "Type", "Use Count");
92       /* *INDENT-OFF* */
93       pool_foreach (key, bm->auth_keys, {
94         s = format (s, "%10u %-25s %10u\n", key->conf_key_id,
95                     bfd_auth_type_str (key->auth_type), key->use_count);
96       });
97       /* *INDENT-ON* */
98       vlib_cli_output (vm, "%v\n", s);
99       vlib_cli_output (vm, "Number of configured BFD keys: %lu\n",
100                        (u64) pool_elts (bm->auth_keys));
101     }
102   else if (unformat (input, "sessions"))
103     {
104       u8 *s = format (NULL, "%=10s %=32s %=20s %=20s\n", "Index", "Property",
105                       "Local value", "Remote value");
106       /* *INDENT-OFF* */
107       pool_foreach (bs, bm->sessions,
108                     { s = format (s, "%U", format_bfd_session_cli, bm, bs); });
109       /* *INDENT-ON* */
110       vlib_cli_output (vm, "%v", s);
111       vec_free (s);
112       vlib_cli_output (vm, "Number of configured BFD sessions: %lu\n",
113                        (u64) pool_elts (bm->sessions));
114     }
115   else if (unformat (input, "echo-source"))
116     {
117       int is_set;
118       u32 sw_if_index;
119       int have_usable_ip4;
120       ip4_address_t ip4;
121       int have_usable_ip6;
122       ip6_address_t ip6;
123       bfd_udp_get_echo_source (&is_set, &sw_if_index, &have_usable_ip4, &ip4,
124                                &have_usable_ip6, &ip6);
125       if (is_set)
126         {
127           vnet_sw_interface_t *sw_if =
128             vnet_get_sw_interface_safe (&vnet_main, sw_if_index);
129           vnet_hw_interface_t *hw_if =
130             vnet_get_hw_interface (&vnet_main, sw_if->hw_if_index);
131           u8 *s = format (NULL, "UDP echo source is: %v\n", hw_if->name);
132           s = format (s, "IPv4 address usable as echo source: ");
133           if (have_usable_ip4)
134             {
135               s = format (s, "%U\n", format_ip4_address, &ip4);
136             }
137           else
138             {
139               s = format (s, "none\n");
140             }
141           s = format (s, "IPv6 address usable as echo source: ");
142           if (have_usable_ip6)
143             {
144               s = format (s, "%U\n", format_ip6_address, &ip6);
145             }
146           else
147             {
148               s = format (s, "none\n");
149             }
150           vlib_cli_output (vm, "%v", s);
151           vec_free (s);
152         }
153       else
154         {
155           vlib_cli_output (vm, "UDP echo source is not set.\n");
156         }
157     }
158   else
159     {
160       vlib_cli_output (vm, "Number of configured BFD sessions: %lu\n",
161                        (u64) pool_elts (bm->sessions));
162       vlib_cli_output (vm, "Number of configured BFD keys: %lu\n",
163                        (u64) pool_elts (bm->auth_keys));
164     }
165   return 0;
166 }
167
168 /* *INDENT-OFF* */
169 VLIB_CLI_COMMAND (show_bfd_command, static) = {
170   .path = "show bfd",
171   .short_help = "show bfd [keys|sessions|echo-source]",
172   .function = show_bfd,
173 };
174 /* *INDENT-ON* */
175
176 static u8 *
177 format_vnet_api_errno (u8 * s, va_list * args)
178 {
179   vnet_api_error_t api_error = va_arg (*args, vnet_api_error_t);
180 #define _(a, b, c)           \
181   case b:                    \
182     s = format (s, "%s", c); \
183     break;
184   switch (api_error)
185     {
186       foreach_vnet_api_error default:s = format (s, "UNKNOWN");
187       break;
188     }
189   return s;
190 }
191
192 static clib_error_t *
193 bfd_cli_key_add (vlib_main_t * vm, unformat_input_t * input,
194                  CLIB_UNUSED (vlib_cli_command_t * lmd))
195 {
196   clib_error_t *ret = NULL;
197   int have_key_id = 0;
198   u32 key_id = 0;
199   u8 *vec_auth_type = NULL;
200   bfd_auth_type_e auth_type = BFD_AUTH_TYPE_reserved;
201   u8 *secret = NULL;
202   static const u8 keyed_sha1[] = "keyed-sha1";
203   static const u8 meticulous_keyed_sha1[] = "meticulous-keyed-sha1";
204
205   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
206     {
207       if (unformat (input, "conf-key-id %u", &key_id))
208         {
209           have_key_id = 1;
210         }
211       else if (unformat (input, "type %U", unformat_token, "a-zA-Z0-9-",
212                          &vec_auth_type))
213         {
214           if (vec_len (vec_auth_type) == sizeof (keyed_sha1) - 1 &&
215               0 == memcmp (vec_auth_type, keyed_sha1,
216                            sizeof (keyed_sha1) - 1))
217             {
218               auth_type = BFD_AUTH_TYPE_keyed_sha1;
219             }
220           else if (vec_len (vec_auth_type) ==
221                    sizeof (meticulous_keyed_sha1) - 1 &&
222                    0 == memcmp (vec_auth_type, meticulous_keyed_sha1,
223                                 sizeof (meticulous_keyed_sha1) - 1))
224             {
225               auth_type = BFD_AUTH_TYPE_meticulous_keyed_sha1;
226             }
227           else
228             {
229               ret = clib_error_return (0, "invalid type `%v'", vec_auth_type);
230               goto out;
231             }
232         }
233       else if (unformat (input, "secret %U", unformat_hex_string, &secret))
234         {
235           /* nothing to do here */
236         }
237       else
238         {
239           ret = clib_error_return (0, "Unknown input `%U'",
240                                    format_unformat_error, input);
241           goto out;
242         }
243     }
244
245   if (!have_key_id)
246     {
247       ret =
248         clib_error_return (0, "required parameter missing: `conf-key-id'");
249       goto out;
250     }
251   if (!vec_auth_type)
252     {
253       ret = clib_error_return (0, "required parameter missing: `type'");
254       goto out;
255     }
256   if (!secret)
257     {
258       ret = clib_error_return (0, "required parameter missing: `secret'");
259       goto out;
260     }
261
262   vnet_api_error_t rv =
263     bfd_auth_set_key (key_id, auth_type, vec_len (secret), secret);
264   if (rv)
265     {
266       ret =
267         clib_error_return (0, "`bfd_auth_set_key' API call failed, rv=%d:%U",
268                            (int) rv, format_vnet_api_errno, rv);
269     }
270
271 out:
272   vec_free (vec_auth_type);
273   return ret;
274 }
275
276 /* *INDENT-OFF* */
277 VLIB_CLI_COMMAND (bfd_cli_key_add_command, static) = {
278   .path = "bfd key set",
279   .short_help = "bfd key set"
280                 " conf-key-id <id>"
281                 " type <keyed-sha1|meticulous-keyed-sha1> "
282                 " secret <secret>",
283   .function = bfd_cli_key_add,
284 };
285 /* *INDENT-ON* */
286
287 static clib_error_t *
288 bfd_cli_key_del (vlib_main_t * vm, unformat_input_t * input,
289                  CLIB_UNUSED (vlib_cli_command_t * lmd))
290 {
291   clib_error_t *ret = NULL;
292   u32 key_id = 0;
293
294   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
295     {
296       if (!unformat (input, "conf-key-id %u", &key_id))
297         {
298           ret = clib_error_return (0, "Unknown input `%U'",
299                                    format_unformat_error, input);
300           goto out;
301         }
302     }
303
304   vnet_api_error_t rv = bfd_auth_del_key (key_id);
305   if (rv)
306     {
307       ret =
308         clib_error_return (0, "`bfd_auth_del_key' API call failed, rv=%d:%U",
309                            (int) rv, format_vnet_api_errno, rv);
310     }
311
312 out:
313   return ret;
314 }
315
316 /* *INDENT-OFF* */
317 VLIB_CLI_COMMAND (bfd_cli_key_del_command, static) = {
318   .path = "bfd key del",
319   .short_help = "bfd key del conf-key-id <id>",
320   .function = bfd_cli_key_del,
321 };
322 /* *INDENT-ON* */
323
324 #define INTERFACE_STR "interface"
325 #define LOCAL_ADDR_STR "local-addr"
326 #define PEER_ADDR_STR "peer-addr"
327 #define CONF_KEY_ID_STR "conf-key-id"
328 #define BFD_KEY_ID_STR "bfd-key-id"
329 #define DESIRED_MIN_TX_STR "desired-min-tx"
330 #define REQUIRED_MIN_RX_STR "required-min-rx"
331 #define DETECT_MULT_STR "detect-mult"
332 #define ADMIN_STR "admin"
333 #define DELAYED_STR "delayed"
334
335 static const unsigned mandatory = 1;
336 static const unsigned optional = 0;
337
338 #define DECLARE(t, n, s, r, ...) \
339   int have_##n = 0;              \
340   t n;
341
342 #define UNFORMAT(t, n, s, r, ...)              \
343   if (unformat (input, s " " __VA_ARGS__, &n)) \
344     {                                          \
345       something_parsed = 1;                    \
346       have_##n = 1;                            \
347     }
348
349 #define CHECK_MANDATORY(t, n, s, r, ...)                                  \
350   if (mandatory == r && !have_##n)                                        \
351     {                                                                     \
352       ret = clib_error_return (0, "Required parameter `%s' missing.", n); \
353       goto out;                                                           \
354     }
355
356 static clib_error_t *
357 bfd_cli_udp_session_add (vlib_main_t * vm, unformat_input_t * input,
358                          CLIB_UNUSED (vlib_cli_command_t * lmd))
359 {
360   clib_error_t *ret = NULL;
361 #define foreach_bfd_cli_udp_session_add_cli_param(F)              \
362   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",            \
363      unformat_vnet_sw_interface, &vnet_main)                      \
364   F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \
365      unformat_ip46_address)                                       \
366   F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U",   \
367      unformat_ip46_address)                                       \
368   F (u32, desired_min_tx, DESIRED_MIN_TX_STR, mandatory, "%u")    \
369   F (u32, required_min_rx, REQUIRED_MIN_RX_STR, mandatory, "%u")  \
370   F (u32, detect_mult, DETECT_MULT_STR, mandatory, "%u")          \
371   F (u32, conf_key_id, CONF_KEY_ID_STR, optional, "%u")           \
372   F (u32, bfd_key_id, BFD_KEY_ID_STR, optional, "%u")
373
374   foreach_bfd_cli_udp_session_add_cli_param (DECLARE);
375
376   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
377     {
378       int something_parsed = 0;
379       foreach_bfd_cli_udp_session_add_cli_param (UNFORMAT);
380
381       if (!something_parsed)
382         {
383           ret = clib_error_return (0, "Unknown input `%U'",
384                                    format_unformat_error, input);
385           goto out;
386         }
387     }
388
389   foreach_bfd_cli_udp_session_add_cli_param (CHECK_MANDATORY);
390
391   if (1 == have_conf_key_id + have_bfd_key_id)
392     {
393       ret = clib_error_return (0, "Incompatible parameter combination, `%s' "
394                                "and `%s' must be either both specified or none",
395                                CONF_KEY_ID_STR, BFD_KEY_ID_STR);
396       goto out;
397     }
398
399   if (detect_mult > 255)
400     {
401       ret = clib_error_return (0, "%s value `%u' out of range <1,255>",
402                                DETECT_MULT_STR, detect_mult);
403       goto out;
404     }
405
406   if (have_bfd_key_id && bfd_key_id > 255)
407     {
408       ret = clib_error_return (0, "%s value `%u' out of range <1,255>",
409                                BFD_KEY_ID_STR, bfd_key_id);
410       goto out;
411     }
412
413   vnet_api_error_t rv =
414     bfd_udp_add_session (sw_if_index, &local_addr, &peer_addr, desired_min_tx,
415                          required_min_rx,
416                          detect_mult, have_conf_key_id, conf_key_id,
417                          bfd_key_id);
418   if (rv)
419     {
420       ret =
421         clib_error_return (0,
422                            "`bfd_add_add_session' API call failed, rv=%d:%U",
423                            (int) rv, format_vnet_api_errno, rv);
424       goto out;
425     }
426
427 out:
428   return ret;
429 }
430
431 /* *INDENT-OFF* */
432 VLIB_CLI_COMMAND (bfd_cli_udp_session_add_command, static) = {
433   .path = "bfd udp session add",
434   .short_help = "bfd udp session add"
435                 " interface <interface>"
436                 " local-addr <local-address>"
437                 " peer-addr <peer-address>"
438                 " desired-min-tx <desired min tx interval>"
439                 " required-min-rx <required min rx interval>"
440                 " detect-mult <detect multiplier> "
441                 "["
442                 " conf-key-id <config key ID>"
443                 " bfd-key-id <BFD key ID>"
444                 "]",
445   .function = bfd_cli_udp_session_add,
446 };
447 /* *INDENT-ON* */
448
449 static clib_error_t *
450 bfd_cli_udp_session_mod (vlib_main_t * vm, unformat_input_t * input,
451                          CLIB_UNUSED (vlib_cli_command_t * lmd))
452 {
453   clib_error_t *ret = NULL;
454 #define foreach_bfd_cli_udp_session_mod_cli_param(F)              \
455   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",            \
456      unformat_vnet_sw_interface, &vnet_main)                      \
457   F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \
458      unformat_ip46_address)                                       \
459   F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U",   \
460      unformat_ip46_address)                                       \
461   F (u32, desired_min_tx, DESIRED_MIN_TX_STR, mandatory, "%u")    \
462   F (u32, required_min_rx, REQUIRED_MIN_RX_STR, mandatory, "%u")  \
463   F (u32, detect_mult, DETECT_MULT_STR, mandatory, "%u")
464
465   foreach_bfd_cli_udp_session_mod_cli_param (DECLARE);
466
467   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
468     {
469       int something_parsed = 0;
470       foreach_bfd_cli_udp_session_mod_cli_param (UNFORMAT);
471
472       if (!something_parsed)
473         {
474           ret = clib_error_return (0, "Unknown input `%U'",
475                                    format_unformat_error, input);
476           goto out;
477         }
478     }
479
480   foreach_bfd_cli_udp_session_mod_cli_param (CHECK_MANDATORY);
481
482   if (detect_mult > 255)
483     {
484       ret = clib_error_return (0, "%s value `%u' out of range <1,255>",
485                                DETECT_MULT_STR, detect_mult);
486       goto out;
487     }
488
489   vnet_api_error_t rv =
490     bfd_udp_mod_session (sw_if_index, &local_addr, &peer_addr,
491                          desired_min_tx, required_min_rx, detect_mult);
492   if (rv)
493     {
494       ret =
495         clib_error_return (0,
496                            "`bfd_udp_mod_session' API call failed, rv=%d:%U",
497                            (int) rv, format_vnet_api_errno, rv);
498       goto out;
499     }
500
501 out:
502   return ret;
503 }
504
505 /* *INDENT-OFF* */
506 VLIB_CLI_COMMAND (bfd_cli_udp_session_mod_command, static) = {
507   .path = "bfd udp session mod",
508   .short_help = "bfd udp session mod interface"
509                 " <interface> local-addr"
510                 " <local-address> peer-addr"
511                 " <peer-address> desired-min-tx"
512                 " <desired min tx interval> required-min-rx"
513                 " <required min rx interval> detect-mult"
514                 " <detect multiplier> ",
515   .function = bfd_cli_udp_session_mod,
516 };
517 /* *INDENT-ON* */
518
519 static clib_error_t *
520 bfd_cli_udp_session_del (vlib_main_t * vm, unformat_input_t * input,
521                          CLIB_UNUSED (vlib_cli_command_t * lmd))
522 {
523   clib_error_t *ret = NULL;
524 #define foreach_bfd_cli_udp_session_del_cli_param(F)              \
525   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",            \
526      unformat_vnet_sw_interface, &vnet_main)                      \
527   F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \
528      unformat_ip46_address)                                       \
529   F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U",   \
530      unformat_ip46_address)
531
532   foreach_bfd_cli_udp_session_del_cli_param (DECLARE);
533
534   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
535     {
536       int something_parsed = 0;
537       foreach_bfd_cli_udp_session_del_cli_param (UNFORMAT);
538
539       if (!something_parsed)
540         {
541           ret = clib_error_return (0, "Unknown input `%U'",
542                                    format_unformat_error, input);
543           goto out;
544         }
545     }
546
547   foreach_bfd_cli_udp_session_del_cli_param (CHECK_MANDATORY);
548
549   vnet_api_error_t rv =
550     bfd_udp_del_session (sw_if_index, &local_addr, &peer_addr);
551   if (rv)
552     {
553       ret =
554         clib_error_return (0,
555                            "`bfd_udp_del_session' API call failed, rv=%d:%U",
556                            (int) rv, format_vnet_api_errno, rv);
557       goto out;
558     }
559
560 out:
561   return ret;
562 }
563
564 /* *INDENT-OFF* */
565 VLIB_CLI_COMMAND (bfd_cli_udp_session_del_command, static) = {
566   .path = "bfd udp session del",
567   .short_help = "bfd udp session del interface"
568                 " <interface> local-addr"
569                 " <local-address> peer-addr"
570                 "<peer-address> ",
571   .function = bfd_cli_udp_session_del,
572 };
573 /* *INDENT-ON* */
574
575 static clib_error_t *
576 bfd_cli_udp_session_set_flags (vlib_main_t * vm, unformat_input_t * input,
577                                CLIB_UNUSED (vlib_cli_command_t * lmd))
578 {
579   clib_error_t *ret = NULL;
580 #define foreach_bfd_cli_udp_session_set_flags_cli_param(F)        \
581   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",            \
582      unformat_vnet_sw_interface, &vnet_main)                      \
583   F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \
584      unformat_ip46_address)                                       \
585   F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U",   \
586      unformat_ip46_address)                                       \
587   F (u8 *, admin_up_down_token, ADMIN_STR, mandatory, "%v",       \
588      &admin_up_down_token)
589
590   foreach_bfd_cli_udp_session_set_flags_cli_param (DECLARE);
591
592   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
593     {
594       int something_parsed = 0;
595       foreach_bfd_cli_udp_session_set_flags_cli_param (UNFORMAT);
596
597       if (!something_parsed)
598         {
599           ret = clib_error_return (0, "Unknown input `%U'",
600                                    format_unformat_error, input);
601           goto out;
602         }
603     }
604
605   foreach_bfd_cli_udp_session_set_flags_cli_param (CHECK_MANDATORY);
606
607   u8 admin_up_down;
608   static const char up[] = "up";
609   static const char down[] = "down";
610   if (!memcmp (admin_up_down_token, up, sizeof (up) - 1))
611     {
612       admin_up_down = 1;
613     }
614   else if (!memcmp (admin_up_down_token, down, sizeof (down) - 1))
615     {
616       admin_up_down = 0;
617     }
618   else
619     {
620       ret =
621         clib_error_return (0, "Unrecognized value for `%s' parameter: `%v'",
622                            ADMIN_STR, admin_up_down_token);
623       goto out;
624     }
625   vnet_api_error_t rv = bfd_udp_session_set_flags (sw_if_index, &local_addr,
626                                                    &peer_addr, admin_up_down);
627   if (rv)
628     {
629       ret =
630         clib_error_return (0,
631                            "`bfd_udp_session_set_flags' API call failed, rv=%d:%U",
632                            (int) rv, format_vnet_api_errno, rv);
633       goto out;
634     }
635
636 out:
637   return ret;
638 }
639
640 /* *INDENT-OFF* */
641 VLIB_CLI_COMMAND (bfd_cli_udp_session_set_flags_command, static) = {
642   .path = "bfd udp session set-flags",
643   .short_help = "bfd udp session set-flags"
644                 " interface <interface>"
645                 " local-addr <local-address>"
646                 " peer-addr <peer-address>"
647                 " admin <up|down>",
648   .function = bfd_cli_udp_session_set_flags,
649 };
650 /* *INDENT-ON* */
651
652 static clib_error_t *
653 bfd_cli_udp_session_auth_activate (vlib_main_t * vm, unformat_input_t * input,
654                                    CLIB_UNUSED (vlib_cli_command_t * lmd))
655 {
656   clib_error_t *ret = NULL;
657 #define foreach_bfd_cli_udp_session_auth_activate_cli_param(F)    \
658   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",            \
659      unformat_vnet_sw_interface, &vnet_main)                      \
660   F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \
661      unformat_ip46_address)                                       \
662   F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U",   \
663      unformat_ip46_address)                                       \
664   F (u8 *, delayed_token, DELAYED_STR, optional, "%v")            \
665   F (u32, conf_key_id, CONF_KEY_ID_STR, mandatory, "%u")          \
666   F (u32, bfd_key_id, BFD_KEY_ID_STR, mandatory, "%u")
667
668   foreach_bfd_cli_udp_session_auth_activate_cli_param (DECLARE);
669
670   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
671     {
672       int something_parsed = 0;
673       foreach_bfd_cli_udp_session_auth_activate_cli_param (UNFORMAT);
674
675       if (!something_parsed)
676         {
677           ret = clib_error_return (0, "Unknown input `%U'",
678                                    format_unformat_error, input);
679           goto out;
680         }
681     }
682
683   foreach_bfd_cli_udp_session_auth_activate_cli_param (CHECK_MANDATORY);
684
685   u8 is_delayed = 0;
686   if (have_delayed_token)
687     {
688       static const char yes[] = "yes";
689       static const char no[] = "no";
690       if (!memcmp (delayed_token, yes, sizeof (yes) - 1))
691         {
692           is_delayed = 1;
693         }
694       else if (!memcmp (delayed_token, no, sizeof (no) - 1))
695         {
696           is_delayed = 0;
697         }
698       else
699         {
700           ret =
701             clib_error_return (0,
702                                "Unrecognized value for `%s' parameter: `%v'",
703                                DELAYED_STR, delayed_token);
704           goto out;
705         }
706     }
707
708   if (have_bfd_key_id && bfd_key_id > 255)
709     {
710       ret = clib_error_return (0, "%s value `%u' out of range <1,255>",
711                                BFD_KEY_ID_STR, bfd_key_id);
712       goto out;
713     }
714
715   vnet_api_error_t rv =
716     bfd_udp_auth_activate (sw_if_index, &local_addr, &peer_addr, conf_key_id,
717                            bfd_key_id, is_delayed);
718   if (rv)
719     {
720       ret =
721         clib_error_return (0,
722                            "`bfd_udp_auth_activate' API call failed, rv=%d:%U",
723                            (int) rv, format_vnet_api_errno, rv);
724       goto out;
725     }
726
727 out:
728   return ret;
729 }
730
731 /* *INDENT-OFF* */
732 VLIB_CLI_COMMAND (bfd_cli_udp_session_auth_activate_command, static) = {
733   .path = "bfd udp session auth activate",
734   .short_help = "bfd udp session auth activate"
735                 " interface <interface>"
736                 " local-addr <local-address>"
737                 " peer-addr <peer-address>"
738                 " conf-key-id <config key ID>"
739                 " bfd-key-id <BFD key ID>"
740                 " [ delayed <yes|no>]",
741   .function = bfd_cli_udp_session_auth_activate,
742 };
743
744 static clib_error_t *
745 bfd_cli_udp_session_auth_deactivate (vlib_main_t *vm, unformat_input_t *input,
746                                      CLIB_UNUSED (vlib_cli_command_t *lmd))
747 {
748   clib_error_t *ret = NULL;
749 #define foreach_bfd_cli_udp_session_auth_deactivate_cli_param(F)  \
750   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",            \
751      unformat_vnet_sw_interface, &vnet_main)                      \
752   F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \
753      unformat_ip46_address)                                       \
754   F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U",   \
755      unformat_ip46_address)                                       \
756   F (u8 *, delayed_token, DELAYED_STR, optional, "%v")
757
758   foreach_bfd_cli_udp_session_auth_deactivate_cli_param (DECLARE);
759
760   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
761     {
762       int something_parsed = 0;
763       foreach_bfd_cli_udp_session_auth_deactivate_cli_param (UNFORMAT);
764
765       if (!something_parsed)
766         {
767           ret = clib_error_return (0, "Unknown input `%U'",
768                                    format_unformat_error, input);
769           goto out;
770         }
771     }
772
773   foreach_bfd_cli_udp_session_auth_deactivate_cli_param (CHECK_MANDATORY);
774
775   u8 is_delayed = 0;
776   if (have_delayed_token)
777     {
778       static const char yes[] = "yes";
779       static const char no[] = "no";
780       if (!memcmp (delayed_token, yes, sizeof (yes) - 1))
781         {
782           is_delayed = 1;
783         }
784       else if (!memcmp (delayed_token, no, sizeof (no) - 1))
785         {
786           is_delayed = 0;
787         }
788       else
789         {
790           ret = clib_error_return (
791               0, "Unrecognized value for `%s' parameter: `%v'", DELAYED_STR,
792               delayed_token);
793           goto out;
794         }
795     }
796
797   vnet_api_error_t rv = bfd_udp_auth_deactivate (sw_if_index, &local_addr,
798                                                  &peer_addr, is_delayed);
799   if (rv)
800     {
801       ret = clib_error_return (
802           0, "`bfd_udp_auth_deactivate' API call failed, rv=%d:%U", (int)rv,
803           format_vnet_api_errno, rv);
804       goto out;
805     }
806
807 out:
808   return ret;
809 }
810
811 /* *INDENT-OFF* */
812 VLIB_CLI_COMMAND (bfd_cli_udp_session_auth_deactivate_command, static) = {
813   .path = "bfd udp session auth deactivate",
814   .short_help = "bfd udp session auth deactivate"
815                 " interface <interface>"
816                 " local-addr <local-address>"
817                 " peer-addr <peer-address>"
818                 "[ delayed <yes|no>]",
819   .function = bfd_cli_udp_session_auth_deactivate,
820 };
821 /* *INDENT-ON* */
822
823 static clib_error_t *
824 bfd_cli_udp_set_echo_source (vlib_main_t * vm, unformat_input_t * input,
825                              CLIB_UNUSED (vlib_cli_command_t * lmd))
826 {
827   clib_error_t *ret = NULL;
828 #define foreach_bfd_cli_udp_set_echo_source_cli_param(F) \
829   F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U",   \
830      unformat_vnet_sw_interface, &vnet_main)
831
832   foreach_bfd_cli_udp_set_echo_source_cli_param (DECLARE);
833
834   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
835     {
836       int something_parsed = 0;
837       foreach_bfd_cli_udp_set_echo_source_cli_param (UNFORMAT);
838
839       if (!something_parsed)
840         {
841           ret = clib_error_return (0, "Unknown input `%U'",
842                                    format_unformat_error, input);
843           goto out;
844         }
845     }
846
847   foreach_bfd_cli_udp_set_echo_source_cli_param (CHECK_MANDATORY);
848
849   vnet_api_error_t rv = bfd_udp_set_echo_source (sw_if_index);
850   if (rv)
851     {
852       ret =
853         clib_error_return (0,
854                            "`bfd_udp_set_echo_source' API call failed, rv=%d:%U",
855                            (int) rv, format_vnet_api_errno, rv);
856       goto out;
857     }
858
859 out:
860   return ret;
861 }
862
863 /* *INDENT-OFF* */
864 VLIB_CLI_COMMAND (bfd_cli_udp_set_echo_source_cmd, static) = {
865   .path = "bfd udp echo-source set",
866   .short_help = "bfd udp echo-source set interface <interface>",
867   .function = bfd_cli_udp_set_echo_source,
868 };
869 /* *INDENT-ON* */
870
871 static clib_error_t *
872 bfd_cli_udp_del_echo_source (vlib_main_t * vm, unformat_input_t * input,
873                              CLIB_UNUSED (vlib_cli_command_t * lmd))
874 {
875   vnet_api_error_t rv = bfd_udp_del_echo_source ();
876   if (rv)
877     {
878       return clib_error_return (0,
879                                 "`bfd_udp_del_echo_source' API call failed, rv=%d:%U",
880                                 (int) rv, format_vnet_api_errno, rv);
881     }
882
883   return 0;
884 }
885
886 /* *INDENT-OFF* */
887 VLIB_CLI_COMMAND (bfd_cli_udp_del_echo_source_cmd, static) = {
888   .path = "bfd udp echo-source del",
889   .short_help = "bfd udp echo-source del",
890   .function = bfd_cli_udp_del_echo_source,
891 };
892 /* *INDENT-ON* */
893
894 /*
895  * fd.io coding-style-patch-verification: ON
896  *
897  * Local Variables:
898  * eval: (c-set-style "gnu")
899  * End:
900  */