back to topotato report
topotato coverage report
Current view: top level - bfdd - bfdd_vty.c (source / functions) Hit Total Coverage
Test: test_pim_basic2.py::PIMTopo2Test Lines: 107 517 20.7 %
Date: 2023-02-24 18:39:36 Functions: 7 28 25.0 %

          Line data    Source code
       1             : /*
       2             :  * BFD daemon code
       3             :  * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
       4             :  *
       5             :  * FRR is free software; you can redistribute it and/or modify it
       6             :  * under the terms of the GNU General Public License as published by the
       7             :  * Free Software Foundation; either version 2, or (at your option) any
       8             :  * later version.
       9             :  *
      10             :  * FRR is distributed in the hope that it will be useful, but
      11             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with FRR; see the file COPYING.  If not, write to the Free
      17             :  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      18             :  * 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "lib/command.h"
      24             : #include "lib/json.h"
      25             : #include "lib/log.h"
      26             : #include "lib/northbound_cli.h"
      27             : #include "lib/vty.h"
      28             : 
      29             : #include "bfd.h"
      30             : 
      31             : #include "bfdd/bfdd_vty_clippy.c"
      32             : 
      33             : /*
      34             :  * Commands help string definitions.
      35             :  */
      36             : #define PEER_IPV4_STR "IPv4 peer address\n"
      37             : #define PEER_IPV6_STR "IPv6 peer address\n"
      38             : #define MHOP_STR "Configure multihop\n"
      39             : #define LOCAL_STR "Configure local address\n"
      40             : #define LOCAL_IPV4_STR "IPv4 local address\n"
      41             : #define LOCAL_IPV6_STR "IPv6 local address\n"
      42             : #define LOCAL_INTF_STR "Configure local interface name to use\n"
      43             : 
      44             : /*
      45             :  * Prototypes
      46             :  */
      47             : static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
      48             :                               const struct sockaddr_any *peer,
      49             :                               const struct sockaddr_any *local,
      50             :                               const char *ifname, const char *vrfname,
      51             :                               char *ebuf, size_t ebuflen);
      52             : 
      53             : static void _display_peer_header(struct vty *vty, struct bfd_session *bs);
      54             : static struct json_object *__display_peer_json(struct bfd_session *bs);
      55             : static struct json_object *_peer_json_header(struct bfd_session *bs);
      56             : static void _display_peer_json(struct vty *vty, struct bfd_session *bs);
      57             : static void _display_peer(struct vty *vty, struct bfd_session *bs);
      58             : static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json);
      59             : static void _display_peer_iter(struct hash_bucket *hb, void *arg);
      60             : static void _display_peer_json_iter(struct hash_bucket *hb, void *arg);
      61             : static void _display_peer_counter(struct vty *vty, struct bfd_session *bs);
      62             : static struct json_object *__display_peer_counters_json(struct bfd_session *bs);
      63             : static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs);
      64             : static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg);
      65             : static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg);
      66             : static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json);
      67             : static void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
      68             :                          struct bfd_session *bs);
      69             : 
      70             : static struct bfd_session *
      71             : _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
      72             :                     const char *label, const char *peer_str,
      73             :                     const char *local_str, const char *ifname,
      74             :                     const char *vrfname);
      75             : 
      76             : 
      77             : /*
      78             :  * Show commands helper functions
      79             :  */
      80           0 : static void _display_peer_header(struct vty *vty, struct bfd_session *bs)
      81             : {
      82           0 :         char addr_buf[INET6_ADDRSTRLEN];
      83             : 
      84           0 :         vty_out(vty, "\tpeer %s",
      85           0 :                 inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
      86             :                           sizeof(addr_buf)));
      87             : 
      88           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
      89           0 :                 vty_out(vty, " multihop");
      90             : 
      91           0 :         if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
      92           0 :                 vty_out(vty, " local-address %s",
      93           0 :                         inet_ntop(bs->key.family, &bs->key.local, addr_buf,
      94             :                                   sizeof(addr_buf)));
      95             : 
      96           0 :         if (bs->key.vrfname[0])
      97           0 :                 vty_out(vty, " vrf %s", bs->key.vrfname);
      98           0 :         if (bs->key.ifname[0])
      99           0 :                 vty_out(vty, " interface %s", bs->key.ifname);
     100           0 :         vty_out(vty, "\n");
     101             : 
     102           0 :         if (bs->pl)
     103           0 :                 vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
     104           0 : }
     105             : 
     106           0 : static void _display_peer(struct vty *vty, struct bfd_session *bs)
     107             : {
     108           0 :         char buf[256];
     109           0 :         time_t now;
     110           0 :         uint32_t min = 0;
     111           0 :         uint32_t avg = 0;
     112           0 :         uint32_t max = 0;
     113             : 
     114           0 :         _display_peer_header(vty, bs);
     115             : 
     116           0 :         vty_out(vty, "\t\tID: %u\n", bs->discrs.my_discr);
     117           0 :         vty_out(vty, "\t\tRemote ID: %u\n", bs->discrs.remote_discr);
     118           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE))
     119           0 :                 vty_out(vty, "\t\tPassive mode\n");
     120             :         else
     121           0 :                 vty_out(vty, "\t\tActive mode\n");
     122           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
     123           0 :                 vty_out(vty, "\t\tMinimum TTL: %d\n", bs->mh_ttl);
     124             : 
     125           0 :         vty_out(vty, "\t\tStatus: ");
     126           0 :         switch (bs->ses_state) {
     127           0 :         case PTM_BFD_ADM_DOWN:
     128           0 :                 vty_out(vty, "shutdown\n");
     129           0 :                 break;
     130           0 :         case PTM_BFD_DOWN:
     131           0 :                 vty_out(vty, "down\n");
     132             : 
     133           0 :                 now = monotime(NULL);
     134           0 :                 integer2timestr(now - bs->downtime.tv_sec, buf, sizeof(buf));
     135           0 :                 vty_out(vty, "\t\tDowntime: %s\n", buf);
     136           0 :                 break;
     137           0 :         case PTM_BFD_INIT:
     138           0 :                 vty_out(vty, "init\n");
     139           0 :                 break;
     140           0 :         case PTM_BFD_UP:
     141           0 :                 vty_out(vty, "up\n");
     142             : 
     143           0 :                 now = monotime(NULL);
     144           0 :                 integer2timestr(now - bs->uptime.tv_sec, buf, sizeof(buf));
     145           0 :                 vty_out(vty, "\t\tUptime: %s\n", buf);
     146           0 :                 break;
     147             : 
     148           0 :         default:
     149           0 :                 vty_out(vty, "unknown\n");
     150           0 :                 break;
     151             :         }
     152             : 
     153           0 :         vty_out(vty, "\t\tDiagnostics: %s\n", diag2str(bs->local_diag));
     154           0 :         vty_out(vty, "\t\tRemote diagnostics: %s\n", diag2str(bs->remote_diag));
     155           0 :         vty_out(vty, "\t\tPeer Type: %s\n",
     156           0 :                 CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) ? "configured" : "dynamic");
     157           0 :         _display_rtt(&min, &avg, &max, bs);
     158           0 :         vty_out(vty, "\t\tRTT min/avg/max: %u/%u/%u usec\n", min, avg, max);
     159             : 
     160           0 :         vty_out(vty, "\t\tLocal timers:\n");
     161           0 :         vty_out(vty, "\t\t\tDetect-multiplier: %u\n",
     162           0 :                 bs->detect_mult);
     163           0 :         vty_out(vty, "\t\t\tReceive interval: %ums\n",
     164           0 :                 bs->timers.required_min_rx / 1000);
     165           0 :         vty_out(vty, "\t\t\tTransmission interval: %ums\n",
     166           0 :                 bs->timers.desired_min_tx / 1000);
     167           0 :         if (bs->timers.required_min_echo_rx != 0)
     168           0 :                 vty_out(vty, "\t\t\tEcho receive interval: %ums\n",
     169             :                         bs->timers.required_min_echo_rx / 1000);
     170             :         else
     171           0 :                 vty_out(vty, "\t\t\tEcho receive interval: disabled\n");
     172           0 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
     173           0 :                 vty_out(vty, "\t\t\tEcho transmission interval: %ums\n",
     174           0 :                         bs->timers.desired_min_echo_tx / 1000);
     175             :         else
     176           0 :                 vty_out(vty, "\t\t\tEcho transmission interval: disabled\n");
     177             : 
     178           0 :         vty_out(vty, "\t\tRemote timers:\n");
     179           0 :         vty_out(vty, "\t\t\tDetect-multiplier: %u\n",
     180           0 :                 bs->remote_detect_mult);
     181           0 :         vty_out(vty, "\t\t\tReceive interval: %ums\n",
     182           0 :                 bs->remote_timers.required_min_rx / 1000);
     183           0 :         vty_out(vty, "\t\t\tTransmission interval: %ums\n",
     184           0 :                 bs->remote_timers.desired_min_tx / 1000);
     185           0 :         if (bs->remote_timers.required_min_echo != 0)
     186           0 :                 vty_out(vty, "\t\t\tEcho receive interval: %ums\n",
     187             :                         bs->remote_timers.required_min_echo / 1000);
     188             :         else
     189           0 :                 vty_out(vty, "\t\t\tEcho receive interval: disabled\n");
     190             : 
     191           0 :         vty_out(vty, "\n");
     192           0 : }
     193             : 
     194          10 : static struct json_object *_peer_json_header(struct bfd_session *bs)
     195             : {
     196          10 :         struct json_object *jo = json_object_new_object();
     197          10 :         char addr_buf[INET6_ADDRSTRLEN];
     198             : 
     199          10 :         if (bs->key.mhop)
     200           0 :                 json_object_boolean_true_add(jo, "multihop");
     201             :         else
     202          10 :                 json_object_boolean_false_add(jo, "multihop");
     203             : 
     204          10 :         json_object_string_add(jo, "peer",
     205          10 :                                inet_ntop(bs->key.family, &bs->key.peer,
     206             :                                          addr_buf, sizeof(addr_buf)));
     207          10 :         if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
     208           0 :                 json_object_string_add(jo, "local",
     209           0 :                                        inet_ntop(bs->key.family, &bs->key.local,
     210             :                                                  addr_buf, sizeof(addr_buf)));
     211             : 
     212          10 :         if (bs->key.vrfname[0])
     213          10 :                 json_object_string_add(jo, "vrf", bs->key.vrfname);
     214          10 :         if (bs->key.ifname[0])
     215          10 :                 json_object_string_add(jo, "interface", bs->key.ifname);
     216             : 
     217          10 :         if (bs->pl)
     218           0 :                 json_object_string_add(jo, "label", bs->pl->pl_label);
     219             : 
     220          10 :         return jo;
     221             : }
     222             : 
     223          10 : static struct json_object *__display_peer_json(struct bfd_session *bs)
     224             : {
     225          10 :         struct json_object *jo = _peer_json_header(bs);
     226          10 :         uint32_t min = 0;
     227          10 :         uint32_t avg = 0;
     228          10 :         uint32_t max = 0;
     229             : 
     230          10 :         json_object_int_add(jo, "id", bs->discrs.my_discr);
     231          10 :         json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
     232          10 :         json_object_boolean_add(jo, "passive-mode",
     233          10 :                                 CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE));
     234          10 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
     235           0 :                 json_object_int_add(jo, "minimum-ttl", bs->mh_ttl);
     236             : 
     237          10 :         switch (bs->ses_state) {
     238           0 :         case PTM_BFD_ADM_DOWN:
     239           0 :                 json_object_string_add(jo, "status", "shutdown");
     240           0 :                 break;
     241          10 :         case PTM_BFD_DOWN:
     242          10 :                 json_object_string_add(jo, "status", "down");
     243          10 :                 json_object_int_add(jo, "downtime",
     244          10 :                                     monotime(NULL) - bs->downtime.tv_sec);
     245          10 :                 break;
     246           0 :         case PTM_BFD_INIT:
     247           0 :                 json_object_string_add(jo, "status", "init");
     248           0 :                 break;
     249           0 :         case PTM_BFD_UP:
     250           0 :                 json_object_string_add(jo, "status", "up");
     251           0 :                 json_object_int_add(jo, "uptime",
     252           0 :                                     monotime(NULL) - bs->uptime.tv_sec);
     253           0 :                 break;
     254             : 
     255           0 :         default:
     256           0 :                 json_object_string_add(jo, "status", "unknown");
     257           0 :                 break;
     258             :         }
     259             : 
     260          10 :         json_object_string_add(jo, "diagnostic", diag2str(bs->local_diag));
     261          10 :         json_object_string_add(jo, "remote-diagnostic",
     262          10 :                                diag2str(bs->remote_diag));
     263             : 
     264          10 :         json_object_int_add(jo, "receive-interval",
     265          10 :                             bs->timers.required_min_rx / 1000);
     266          10 :         json_object_int_add(jo, "transmit-interval",
     267          10 :                             bs->timers.desired_min_tx / 1000);
     268          10 :         json_object_int_add(jo, "echo-receive-interval",
     269          10 :                             bs->timers.required_min_echo_rx / 1000);
     270          10 :         if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
     271           0 :                 json_object_int_add(jo, "echo-transmit-interval",
     272           0 :                                     bs->timers.desired_min_echo_tx / 1000);
     273             :         else
     274          10 :                 json_object_int_add(jo, "echo-transmit-interval", 0);
     275             : 
     276          10 :         json_object_int_add(jo, "detect-multiplier", bs->detect_mult);
     277             : 
     278          10 :         json_object_int_add(jo, "remote-receive-interval",
     279          10 :                             bs->remote_timers.required_min_rx / 1000);
     280          10 :         json_object_int_add(jo, "remote-transmit-interval",
     281          10 :                             bs->remote_timers.desired_min_tx / 1000);
     282          10 :         json_object_int_add(jo, "remote-echo-receive-interval",
     283          10 :                             bs->remote_timers.required_min_echo / 1000);
     284          10 :         json_object_int_add(jo, "remote-detect-multiplier",
     285          10 :                             bs->remote_detect_mult);
     286             : 
     287          10 :         _display_rtt(&min, &avg, &max, bs);
     288          10 :         json_object_int_add(jo, "rtt-min", min);
     289          10 :         json_object_int_add(jo, "rtt-avg", avg);
     290          10 :         json_object_int_add(jo, "rtt-max", max);
     291             : 
     292          10 :         return jo;
     293             : }
     294             : 
     295           0 : static void _display_peer_json(struct vty *vty, struct bfd_session *bs)
     296             : {
     297           0 :         struct json_object *jo = __display_peer_json(bs);
     298             : 
     299           0 :         vty_json(vty, jo);
     300           0 : }
     301             : 
     302             : struct bfd_vrf_tuple {
     303             :         const char *vrfname;
     304             :         struct vty *vty;
     305             :         struct json_object *jo;
     306             : };
     307             : 
     308           0 : static void _display_peer_iter(struct hash_bucket *hb, void *arg)
     309             : {
     310           0 :         struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
     311           0 :         struct vty *vty;
     312           0 :         struct bfd_session *bs = hb->data;
     313             : 
     314           0 :         if (!bvt)
     315             :                 return;
     316           0 :         vty = bvt->vty;
     317             : 
     318           0 :         if (bvt->vrfname) {
     319           0 :                 if (!bs->key.vrfname[0] ||
     320           0 :                     !strmatch(bs->key.vrfname, bvt->vrfname))
     321             :                         return;
     322             :         }
     323           0 :         _display_peer(vty, bs);
     324             : }
     325             : 
     326          10 : static void _display_peer_json_iter(struct hash_bucket *hb, void *arg)
     327             : {
     328          10 :         struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
     329          10 :         struct json_object *jo, *jon = NULL;
     330          10 :         struct bfd_session *bs = hb->data;
     331             : 
     332          10 :         if (!bvt)
     333             :                 return;
     334          10 :         jo = bvt->jo;
     335             : 
     336          10 :         if (bvt->vrfname) {
     337           0 :                 if (!bs->key.vrfname[0] ||
     338           0 :                     !strmatch(bs->key.vrfname, bvt->vrfname))
     339             :                         return;
     340             :         }
     341             : 
     342          10 :         jon = __display_peer_json(bs);
     343          10 :         if (jon == NULL) {
     344           0 :                 zlog_warn("%s: not enough memory", __func__);
     345           0 :                 return;
     346             :         }
     347             : 
     348          10 :         json_object_array_add(jo, jon);
     349             : }
     350             : 
     351           6 : static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json)
     352             : {
     353           6 :         struct json_object *jo;
     354           6 :         struct bfd_vrf_tuple bvt = {0};
     355             : 
     356           6 :         bvt.vrfname = vrfname;
     357             : 
     358           6 :         if (!use_json) {
     359           0 :                 bvt.vty = vty;
     360           0 :                 vty_out(vty, "BFD Peers:\n");
     361           0 :                 bfd_id_iterate(_display_peer_iter, &bvt);
     362           0 :                 return;
     363             :         }
     364             : 
     365           6 :         jo = json_object_new_array();
     366           6 :         bvt.jo = jo;
     367           6 :         bfd_id_iterate(_display_peer_json_iter, &bvt);
     368             : 
     369           6 :         vty_json(vty, jo);
     370             : }
     371             : 
     372           0 : static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
     373             : {
     374           0 :         _display_peer_header(vty, bs);
     375             : 
     376             :         /* Ask data plane for updated counters. */
     377           0 :         if (bfd_dplane_update_session_counters(bs) == -1)
     378           0 :                 zlog_debug("%s: failed to update BFD session counters (%s)",
     379             :                            __func__, bs_to_string(bs));
     380             : 
     381           0 :         vty_out(vty, "\t\tControl packet input: %" PRIu64 " packets\n",
     382             :                 bs->stats.rx_ctrl_pkt);
     383           0 :         vty_out(vty, "\t\tControl packet output: %" PRIu64 " packets\n",
     384             :                 bs->stats.tx_ctrl_pkt);
     385           0 :         vty_out(vty, "\t\tEcho packet input: %" PRIu64 " packets\n",
     386             :                 bs->stats.rx_echo_pkt);
     387           0 :         vty_out(vty, "\t\tEcho packet output: %" PRIu64 " packets\n",
     388             :                 bs->stats.tx_echo_pkt);
     389           0 :         vty_out(vty, "\t\tSession up events: %" PRIu64 "\n",
     390             :                 bs->stats.session_up);
     391           0 :         vty_out(vty, "\t\tSession down events: %" PRIu64 "\n",
     392             :                 bs->stats.session_down);
     393           0 :         vty_out(vty, "\t\tZebra notifications: %" PRIu64 "\n",
     394             :                 bs->stats.znotification);
     395           0 :         vty_out(vty, "\n");
     396           0 : }
     397             : 
     398           0 : static struct json_object *__display_peer_counters_json(struct bfd_session *bs)
     399             : {
     400           0 :         struct json_object *jo = _peer_json_header(bs);
     401             : 
     402             :         /* Ask data plane for updated counters. */
     403           0 :         if (bfd_dplane_update_session_counters(bs) == -1)
     404           0 :                 zlog_debug("%s: failed to update BFD session counters (%s)",
     405             :                            __func__, bs_to_string(bs));
     406             : 
     407           0 :         json_object_int_add(jo, "control-packet-input", bs->stats.rx_ctrl_pkt);
     408           0 :         json_object_int_add(jo, "control-packet-output", bs->stats.tx_ctrl_pkt);
     409           0 :         json_object_int_add(jo, "echo-packet-input", bs->stats.rx_echo_pkt);
     410           0 :         json_object_int_add(jo, "echo-packet-output", bs->stats.tx_echo_pkt);
     411           0 :         json_object_int_add(jo, "session-up", bs->stats.session_up);
     412           0 :         json_object_int_add(jo, "session-down", bs->stats.session_down);
     413           0 :         json_object_int_add(jo, "zebra-notifications", bs->stats.znotification);
     414             : 
     415           0 :         return jo;
     416             : }
     417             : 
     418           0 : static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
     419             : {
     420           0 :         struct json_object *jo = __display_peer_counters_json(bs);
     421             : 
     422           0 :         vty_json(vty, jo);
     423           0 : }
     424             : 
     425           0 : static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg)
     426             : {
     427           0 :         struct bfd_vrf_tuple *bvt = arg;
     428           0 :         struct vty *vty;
     429           0 :         struct bfd_session *bs = hb->data;
     430             : 
     431           0 :         if (!bvt)
     432             :                 return;
     433           0 :         vty = bvt->vty;
     434             : 
     435           0 :         if (bvt->vrfname) {
     436           0 :                 if (!bs->key.vrfname[0] ||
     437           0 :                     !strmatch(bs->key.vrfname, bvt->vrfname))
     438             :                         return;
     439             :         }
     440             : 
     441           0 :         _display_peer_counter(vty, bs);
     442             : }
     443             : 
     444           0 : static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg)
     445             : {
     446           0 :         struct json_object *jo, *jon = NULL;
     447           0 :         struct bfd_session *bs = hb->data;
     448           0 :         struct bfd_vrf_tuple *bvt = arg;
     449             : 
     450           0 :         if (!bvt)
     451             :                 return;
     452           0 :         jo  = bvt->jo;
     453             : 
     454           0 :         if (bvt->vrfname) {
     455           0 :                 if (!bs->key.vrfname[0] ||
     456           0 :                     !strmatch(bs->key.vrfname, bvt->vrfname))
     457             :                         return;
     458             :         }
     459             : 
     460           0 :         jon = __display_peer_counters_json(bs);
     461           0 :         if (jon == NULL) {
     462           0 :                 zlog_warn("%s: not enough memory", __func__);
     463           0 :                 return;
     464             :         }
     465             : 
     466           0 :         json_object_array_add(jo, jon);
     467             : }
     468             : 
     469           0 : static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json)
     470             : {
     471           0 :         struct json_object *jo;
     472           0 :         struct bfd_vrf_tuple bvt = {0};
     473             : 
     474           0 :         bvt.vrfname = vrfname;
     475           0 :         if (!use_json) {
     476           0 :                 bvt.vty = vty;
     477           0 :                 vty_out(vty, "BFD Peers:\n");
     478           0 :                 bfd_id_iterate(_display_peer_counter_iter, &bvt);
     479           0 :                 return;
     480             :         }
     481             : 
     482           0 :         jo = json_object_new_array();
     483           0 :         bvt.jo = jo;
     484           0 :         bfd_id_iterate(_display_peer_counter_json_iter, &bvt);
     485             : 
     486           0 :         vty_json(vty, jo);
     487             : }
     488             : 
     489           0 : static void _clear_peer_counter(struct bfd_session *bs)
     490             : {
     491             :         /* Clear only pkt stats, intention is not to loose system
     492             :            events counters */
     493           0 :         bs->stats.rx_ctrl_pkt = 0;
     494           0 :         bs->stats.tx_ctrl_pkt = 0;
     495           0 :         bs->stats.rx_echo_pkt = 0;
     496           0 :         bs->stats.tx_echo_pkt = 0;
     497             : }
     498             : 
     499           0 : static void _display_peer_brief(struct vty *vty, struct bfd_session *bs)
     500             : {
     501           0 :         char addr_buf[INET6_ADDRSTRLEN];
     502             : 
     503           0 :         vty_out(vty, "%-10u", bs->discrs.my_discr);
     504           0 :         inet_ntop(bs->key.family, &bs->key.local, addr_buf, sizeof(addr_buf));
     505           0 :         vty_out(vty, " %-40s", addr_buf);
     506           0 :         inet_ntop(bs->key.family, &bs->key.peer, addr_buf, sizeof(addr_buf));
     507           0 :         vty_out(vty, " %-40s", addr_buf);
     508           0 :         vty_out(vty, "%-15s\n", state_list[bs->ses_state].str);
     509           0 : }
     510             : 
     511           0 : static void _display_peer_brief_iter(struct hash_bucket *hb, void *arg)
     512             : {
     513           0 :         struct bfd_vrf_tuple *bvt = arg;
     514           0 :         struct vty *vty;
     515           0 :         struct bfd_session *bs = hb->data;
     516             : 
     517           0 :         if (!bvt)
     518             :                 return;
     519           0 :         vty = bvt->vty;
     520             : 
     521           0 :         if (bvt->vrfname) {
     522           0 :                 if (!bs->key.vrfname[0] ||
     523           0 :                         !strmatch(bs->key.vrfname, bvt->vrfname))
     524             :                 return;
     525             :         }
     526             : 
     527           0 :         _display_peer_brief(vty, bs);
     528             : }
     529             : 
     530           0 : static void _display_peers_brief(struct vty *vty, const char *vrfname, bool use_json)
     531             : {
     532           0 :         struct json_object *jo;
     533           0 :         struct bfd_vrf_tuple bvt = {0};
     534             : 
     535           0 :         bvt.vrfname = vrfname;
     536             : 
     537           0 :         if (!use_json) {
     538           0 :                 bvt.vty = vty;
     539             : 
     540           0 :                 vty_out(vty, "Session count: %lu\n", bfd_get_session_count());
     541           0 :                 vty_out(vty, "%-10s", "SessionId");
     542           0 :                 vty_out(vty, " %-40s", "LocalAddress");
     543           0 :                 vty_out(vty, " %-40s", "PeerAddress");
     544           0 :                 vty_out(vty, "%-15s\n", "Status");
     545             : 
     546           0 :                 vty_out(vty, "%-10s", "=========");
     547           0 :                 vty_out(vty, " %-40s", "============");
     548           0 :                 vty_out(vty, " %-40s", "===========");
     549           0 :                 vty_out(vty, "%-15s\n", "======");
     550             : 
     551           0 :                 bfd_id_iterate(_display_peer_brief_iter, &bvt);
     552           0 :                 return;
     553             :         }
     554             : 
     555           0 :         jo = json_object_new_array();
     556           0 :         bvt.jo = jo;
     557             : 
     558           0 :         bfd_id_iterate(_display_peer_json_iter, &bvt);
     559             : 
     560           0 :         vty_json(vty, jo);
     561             : }
     562             : 
     563             : static struct bfd_session *
     564           0 : _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
     565             :                     const char *label, const char *peer_str,
     566             :                     const char *local_str, const char *ifname,
     567             :                     const char *vrfname)
     568             : {
     569           0 :         int idx;
     570           0 :         bool mhop;
     571           0 :         struct bfd_session *bs = NULL;
     572           0 :         struct peer_label *pl;
     573           0 :         struct bfd_peer_cfg bpc;
     574           0 :         struct sockaddr_any psa, lsa, *lsap;
     575           0 :         char errormsg[128];
     576             : 
     577             :         /* Look up the BFD peer. */
     578           0 :         if (label) {
     579           0 :                 pl = pl_find(label);
     580           0 :                 if (pl)
     581           0 :                         bs = pl->pl_bs;
     582           0 :         } else if (peer_str) {
     583           0 :                 strtosa(peer_str, &psa);
     584           0 :                 if (local_str) {
     585           0 :                         strtosa(local_str, &lsa);
     586           0 :                         lsap = &lsa;
     587             :                 } else
     588             :                         lsap = NULL;
     589             : 
     590           0 :                 idx = 0;
     591           0 :                 mhop = argv_find(argv, argc, "multihop", &idx);
     592             : 
     593           0 :                 if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname,
     594             :                                        errormsg, sizeof(errormsg))
     595             :                     != 0) {
     596           0 :                         vty_out(vty, "%% Invalid peer configuration: %s\n",
     597             :                                 errormsg);
     598           0 :                         return NULL;
     599             :                 }
     600             : 
     601           0 :                 bs = bs_peer_find(&bpc);
     602             :         } else {
     603           0 :                 vty_out(vty, "%% Invalid arguments\n");
     604           0 :                 return NULL;
     605             :         }
     606             : 
     607             :         /* Find peer data. */
     608           0 :         if (bs == NULL) {
     609           0 :                 vty_out(vty, "%% Unable to find 'peer %s",
     610             :                         label ? label : peer_str);
     611           0 :                 if (ifname)
     612           0 :                         vty_out(vty, " interface %s", ifname);
     613           0 :                 if (local_str)
     614           0 :                         vty_out(vty, " local-address %s", local_str);
     615           0 :                 if (vrfname)
     616           0 :                         vty_out(vty, " vrf %s", vrfname);
     617           0 :                 vty_out(vty, "'\n");
     618             : 
     619           0 :                 return NULL;
     620             :         }
     621             : 
     622             :         return bs;
     623             : }
     624             : 
     625          10 : void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
     626             :                   struct bfd_session *bs)
     627             : {
     628             : #ifdef BFD_LINUX
     629          10 :         uint8_t i;
     630          10 :         uint32_t average = 0;
     631             : 
     632          10 :         if (bs->rtt_valid == 0)
     633             :                 return;
     634             : 
     635           0 :         *max = bs->rtt[0];
     636           0 :         *min = 1000;
     637           0 :         *avg = 0;
     638             : 
     639           0 :         for (i = 0; i < bs->rtt_valid; i++) {
     640           0 :                 if (bs->rtt[i] < *min)
     641           0 :                         *min = bs->rtt[i];
     642           0 :                 if (bs->rtt[i] > *max)
     643           0 :                         *max = bs->rtt[i];
     644           0 :                 average += bs->rtt[i];
     645             :         }
     646           0 :         *avg = average / bs->rtt_valid;
     647             : 
     648             : #endif
     649             : }
     650             : 
     651             : /*
     652             :  * Show commands.
     653             :  */
     654           6 : DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd [vrf NAME] peers [json]",
     655             :       SHOW_STR
     656             :       "Bidirection Forwarding Detection\n"
     657             :        VRF_CMD_HELP_STR
     658             :       "BFD peers status\n" JSON_STR)
     659             : {
     660           6 :         char *vrf_name = NULL;
     661           6 :         int idx_vrf = 0;
     662             : 
     663           6 :         if (argv_find(argv, argc, "vrf", &idx_vrf))
     664           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
     665             : 
     666           6 :         _display_all_peers(vty, vrf_name, use_json(argc, argv));
     667             : 
     668           6 :         return CMD_SUCCESS;
     669             : }
     670             : 
     671           0 : DEFPY(bfd_show_peer, bfd_show_peer_cmd,
     672             :       "show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]",
     673             :       SHOW_STR
     674             :       "Bidirection Forwarding Detection\n"
     675             :       VRF_CMD_HELP_STR
     676             :       "BFD peers status\n"
     677             :       "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
     678             :               LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR JSON_STR)
     679             : {
     680           0 :         struct bfd_session *bs;
     681             : 
     682             :         /* Look up the BFD peer. */
     683           0 :         bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
     684             :                                  ifname, vrf_name);
     685           0 :         if (bs == NULL)
     686             :                 return CMD_WARNING_CONFIG_FAILED;
     687             : 
     688           0 :         if (use_json(argc, argv)) {
     689           0 :                 _display_peer_json(vty, bs);
     690             :         } else {
     691           0 :                 vty_out(vty, "BFD Peer:\n");
     692           0 :                 _display_peer(vty, bs);
     693             :         }
     694             : 
     695             :         return CMD_SUCCESS;
     696             : }
     697             : 
     698           0 : DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
     699             :       "show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]",
     700             :       SHOW_STR
     701             :       "Bidirection Forwarding Detection\n"
     702             :       VRF_CMD_HELP_STR
     703             :       "BFD peers status\n"
     704             :       "Peer label\n"
     705             :       PEER_IPV4_STR
     706             :       PEER_IPV6_STR
     707             :       MHOP_STR
     708             :       LOCAL_STR
     709             :       LOCAL_IPV4_STR
     710             :       LOCAL_IPV6_STR
     711             :       INTERFACE_STR
     712             :       LOCAL_INTF_STR
     713             :       "Show BFD peer counters information\n"
     714             :       JSON_STR)
     715             : {
     716           0 :         struct bfd_session *bs;
     717             : 
     718             :         /* Look up the BFD peer. */
     719           0 :         bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
     720             :                                  ifname, vrf_name);
     721           0 :         if (bs == NULL)
     722             :                 return CMD_WARNING_CONFIG_FAILED;
     723             : 
     724           0 :         if (use_json(argc, argv))
     725           0 :                 _display_peer_counters_json(vty, bs);
     726             :         else
     727           0 :                 _display_peer_counter(vty, bs);
     728             : 
     729             :         return CMD_SUCCESS;
     730             : }
     731             : 
     732           0 : DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
     733             :       "show bfd [vrf NAME] peers counters [json]",
     734             :       SHOW_STR
     735             :       "Bidirection Forwarding Detection\n"
     736             :       VRF_CMD_HELP_STR
     737             :       "BFD peers status\n"
     738             :       "Show BFD peer counters information\n"
     739             :       JSON_STR)
     740             : {
     741           0 :         char *vrf_name = NULL;
     742           0 :         int idx_vrf = 0;
     743             : 
     744           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf))
     745           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
     746             : 
     747           0 :         _display_peers_counter(vty, vrf_name, use_json(argc, argv));
     748             : 
     749           0 :         return CMD_SUCCESS;
     750             : }
     751             : 
     752           0 : DEFPY(bfd_clear_peer_counters, bfd_clear_peer_counters_cmd,
     753             :       "clear bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters",
     754             :       SHOW_STR
     755             :       "Bidirection Forwarding Detection\n"
     756             :       VRF_CMD_HELP_STR
     757             :       "BFD peers status\n"
     758             :       "Peer label\n"
     759             :       PEER_IPV4_STR
     760             :       PEER_IPV6_STR
     761             :       MHOP_STR
     762             :       LOCAL_STR
     763             :       LOCAL_IPV4_STR
     764             :       LOCAL_IPV6_STR
     765             :       INTERFACE_STR
     766             :       LOCAL_INTF_STR
     767             :       "clear BFD peer counters information\n")
     768             : {
     769           0 :         struct bfd_session *bs;
     770             : 
     771             :         /* Look up the BFD peer. */
     772           0 :         bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
     773             :                                 ifname, vrfname);
     774           0 :         if (bs == NULL)
     775             :                 return CMD_WARNING_CONFIG_FAILED;
     776             : 
     777           0 :         _clear_peer_counter(bs);
     778             : 
     779           0 :         return CMD_SUCCESS;
     780             : }
     781             : 
     782           0 : DEFPY(bfd_show_peers_brief, bfd_show_peers_brief_cmd,
     783             :       "show bfd [vrf <NAME$vrfname>] peers brief [json]",
     784             :       SHOW_STR
     785             :       "Bidirection Forwarding Detection\n"
     786             :       VRF_CMD_HELP_STR
     787             :       "BFD peers status\n"
     788             :       "Show BFD peer information in tabular form\n"
     789             :       JSON_STR)
     790             : {
     791           0 :         char *vrf_name = NULL;
     792           0 :         int idx_vrf = 0;
     793             : 
     794           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf))
     795           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
     796             : 
     797           0 :         _display_peers_brief(vty, vrf_name, use_json(argc, argv));
     798             : 
     799           0 :         return CMD_SUCCESS;
     800             : }
     801             : 
     802           0 : DEFPY(show_bfd_distributed, show_bfd_distributed_cmd,
     803             :       "show bfd distributed",
     804             :       SHOW_STR
     805             :       "Bidirection Forwarding Detection\n"
     806             :       "Show BFD data plane (distributed BFD) statistics\n")
     807             : {
     808           0 :         bfd_dplane_show_counters(vty);
     809           0 :         return CMD_SUCCESS;
     810             : }
     811             : 
     812           0 : DEFPY(
     813             :         bfd_debug_distributed, bfd_debug_distributed_cmd,
     814             :         "[no] debug bfd distributed",
     815             :         NO_STR
     816             :         DEBUG_STR
     817             :         "Bidirection Forwarding Detection\n"
     818             :         "BFD data plane (distributed BFD) debugging\n")
     819             : {
     820           0 :         bglobal.debug_dplane = !no;
     821           0 :         return CMD_SUCCESS;
     822             : }
     823             : 
     824           0 : DEFPY(
     825             :         bfd_debug_peer, bfd_debug_peer_cmd,
     826             :         "[no] debug bfd peer",
     827             :         NO_STR
     828             :         DEBUG_STR
     829             :         "Bidirection Forwarding Detection\n"
     830             :         "Peer events debugging\n")
     831             : {
     832           0 :         bglobal.debug_peer_event = !no;
     833           0 :         return CMD_SUCCESS;
     834             : }
     835             : 
     836           0 : DEFPY(
     837             :         bfd_debug_zebra, bfd_debug_zebra_cmd,
     838             :         "[no] debug bfd zebra",
     839             :         NO_STR
     840             :         DEBUG_STR
     841             :         "Bidirection Forwarding Detection\n"
     842             :         "Zebra events debugging\n")
     843             : {
     844           0 :         bglobal.debug_zebra = !no;
     845           0 :         return CMD_SUCCESS;
     846             : }
     847             : 
     848           0 : DEFPY(
     849             :         bfd_debug_network, bfd_debug_network_cmd,
     850             :         "[no] debug bfd network",
     851             :         NO_STR
     852             :         DEBUG_STR
     853             :         "Bidirection Forwarding Detection\n"
     854             :         "Network layer debugging\n")
     855             : {
     856           0 :         bglobal.debug_network = !no;
     857           0 :         return CMD_SUCCESS;
     858             : }
     859             : 
     860             : /*
     861             :  * Function definitions.
     862             :  */
     863             : 
     864             : /*
     865             :  * Configuration rules:
     866             :  *
     867             :  * Single hop:
     868             :  * peer + (interface name)
     869             :  *
     870             :  * Multi hop:
     871             :  * peer + local + (optional vrf)
     872             :  *
     873             :  * Anything else is misconfiguration.
     874             :  */
     875           0 : static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
     876             :                               const struct sockaddr_any *peer,
     877             :                               const struct sockaddr_any *local,
     878             :                               const char *ifname, const char *vrfname,
     879             :                               char *ebuf, size_t ebuflen)
     880             : {
     881           0 :         memset(bpc, 0, sizeof(*bpc));
     882             : 
     883             :         /* Defaults */
     884           0 :         bpc->bpc_shutdown = false;
     885           0 :         bpc->bpc_detectmultiplier = BPC_DEF_DETECTMULTIPLIER;
     886           0 :         bpc->bpc_recvinterval = BPC_DEF_RECEIVEINTERVAL;
     887           0 :         bpc->bpc_txinterval = BPC_DEF_TRANSMITINTERVAL;
     888           0 :         bpc->bpc_echorecvinterval = BPC_DEF_ECHORECEIVEINTERVAL;
     889           0 :         bpc->bpc_echotxinterval = BPC_DEF_ECHOTRANSMITINTERVAL;
     890           0 :         bpc->bpc_lastevent = monotime(NULL);
     891             : 
     892             :         /* Safety check: when no error buf is provided len must be zero. */
     893           0 :         if (ebuf == NULL)
     894           0 :                 ebuflen = 0;
     895             : 
     896             :         /* Peer is always mandatory. */
     897           0 :         if (peer == NULL) {
     898           0 :                 snprintf(ebuf, ebuflen, "peer must not be empty");
     899           0 :                 return -1;
     900             :         }
     901             : 
     902             :         /* Validate address families. */
     903           0 :         if (peer->sa_sin.sin_family == AF_INET) {
     904           0 :                 if (local && local->sa_sin.sin_family != AF_INET) {
     905           0 :                         snprintf(ebuf, ebuflen,
     906             :                                  "local is IPv6, but peer is IPv4");
     907           0 :                         return -1;
     908             :                 }
     909             : 
     910           0 :                 bpc->bpc_ipv4 = true;
     911           0 :         } else if (peer->sa_sin.sin_family == AF_INET6) {
     912           0 :                 if (local && local->sa_sin.sin_family != AF_INET6) {
     913           0 :                         snprintf(ebuf, ebuflen,
     914             :                                  "local is IPv4, but peer is IPv6");
     915           0 :                         return -1;
     916             :                 }
     917             : 
     918           0 :                 bpc->bpc_ipv4 = false;
     919             :         } else {
     920           0 :                 snprintf(ebuf, ebuflen, "invalid peer address family");
     921           0 :                 return -1;
     922             :         }
     923             : 
     924             :         /* Copy local and/or peer addresses. */
     925           0 :         if (local)
     926           0 :                 bpc->bpc_local = *local;
     927             : 
     928           0 :         bpc->bpc_peer = *peer;
     929           0 :         bpc->bpc_mhop = mhop;
     930             : 
     931             :         /* Handle interface specification configuration. */
     932           0 :         if (ifname) {
     933           0 :                 bpc->bpc_has_localif = true;
     934           0 :                 if (strlcpy(bpc->bpc_localif, ifname, sizeof(bpc->bpc_localif))
     935             :                     > sizeof(bpc->bpc_localif)) {
     936           0 :                         snprintf(ebuf, ebuflen, "interface name too long");
     937           0 :                         return -1;
     938             :                 }
     939             :         }
     940             : 
     941             :         /* Handle VRF configuration. */
     942           0 :         if (vrfname) {
     943           0 :                 bpc->bpc_has_vrfname = true;
     944           0 :                 if (strlcpy(bpc->bpc_vrfname, vrfname, sizeof(bpc->bpc_vrfname))
     945             :                     > sizeof(bpc->bpc_vrfname)) {
     946           0 :                         snprintf(ebuf, ebuflen, "vrf name too long");
     947           0 :                         return -1;
     948             :                 }
     949             :         } else {
     950           0 :                 bpc->bpc_has_vrfname = true;
     951           0 :                 strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
     952             :         }
     953             : 
     954             :         return 0;
     955             : }
     956             : 
     957           0 : DEFUN_NOSH(show_debugging_bfd,
     958             :            show_debugging_bfd_cmd,
     959             :            "show debugging [bfd]",
     960             :            SHOW_STR
     961             :            DEBUG_STR
     962             :            "BFD daemon\n")
     963             : {
     964           0 :         vty_out(vty, "BFD debugging status:\n");
     965           0 :         if (bglobal.debug_dplane)
     966           0 :                 vty_out(vty, "  Distributed BFD debugging is on.\n");
     967           0 :         if (bglobal.debug_peer_event)
     968           0 :                 vty_out(vty, "  Peer events debugging is on.\n");
     969           0 :         if (bglobal.debug_zebra)
     970           0 :                 vty_out(vty, "  Zebra events debugging is on.\n");
     971           0 :         if (bglobal.debug_network)
     972           0 :                 vty_out(vty, "  Network layer debugging is on.\n");
     973             : 
     974           0 :         cmd_show_lib_debugs(vty);
     975             : 
     976           0 :         return CMD_SUCCESS;
     977             : }
     978             : 
     979             : static int bfdd_write_config(struct vty *vty);
     980             : struct cmd_node bfd_node = {
     981             :         .name = "bfd",
     982             :         .node = BFD_NODE,
     983             :         .parent_node = CONFIG_NODE,
     984             :         .prompt = "%s(config-bfd)# ",
     985             :         .config_write = bfdd_write_config,
     986             : };
     987             : 
     988             : struct cmd_node bfd_peer_node = {
     989             :         .name = "bfd peer",
     990             :         .node = BFD_PEER_NODE,
     991             :         .parent_node = BFD_NODE,
     992             :         .prompt = "%s(config-bfd-peer)# ",
     993             : };
     994             : 
     995           0 : static int bfdd_write_config(struct vty *vty)
     996             : {
     997           0 :         struct lyd_node *dnode;
     998           0 :         int written = 0;
     999             : 
    1000           0 :         if (bglobal.debug_dplane) {
    1001           0 :                 vty_out(vty, "debug bfd distributed\n");
    1002           0 :                 written = 1;
    1003             :         }
    1004             : 
    1005           0 :         if (bglobal.debug_peer_event) {
    1006           0 :                 vty_out(vty, "debug bfd peer\n");
    1007           0 :                 written = 1;
    1008             :         }
    1009             : 
    1010           0 :         if (bglobal.debug_zebra) {
    1011           0 :                 vty_out(vty, "debug bfd zebra\n");
    1012           0 :                 written = 1;
    1013             :         }
    1014             : 
    1015           0 :         if (bglobal.debug_network) {
    1016           0 :                 vty_out(vty, "debug bfd network\n");
    1017           0 :                 written = 1;
    1018             :         }
    1019             : 
    1020           0 :         dnode = yang_dnode_get(running_config->dnode, "/frr-bfdd:bfdd");
    1021           0 :         if (dnode) {
    1022           0 :                 nb_cli_show_dnode_cmds(vty, dnode, false);
    1023           0 :                 written = 1;
    1024             :         }
    1025             : 
    1026           0 :         return written;
    1027             : }
    1028             : 
    1029           4 : void bfdd_vty_init(void)
    1030             : {
    1031           4 :         install_element(ENABLE_NODE, &bfd_show_peers_counters_cmd);
    1032           4 :         install_element(ENABLE_NODE, &bfd_show_peer_counters_cmd);
    1033           4 :         install_element(ENABLE_NODE, &bfd_clear_peer_counters_cmd);
    1034           4 :         install_element(ENABLE_NODE, &bfd_show_peers_cmd);
    1035           4 :         install_element(ENABLE_NODE, &bfd_show_peer_cmd);
    1036           4 :         install_element(ENABLE_NODE, &bfd_show_peers_brief_cmd);
    1037           4 :         install_element(ENABLE_NODE, &show_bfd_distributed_cmd);
    1038           4 :         install_element(ENABLE_NODE, &show_debugging_bfd_cmd);
    1039             : 
    1040           4 :         install_element(ENABLE_NODE, &bfd_debug_distributed_cmd);
    1041           4 :         install_element(ENABLE_NODE, &bfd_debug_peer_cmd);
    1042           4 :         install_element(ENABLE_NODE, &bfd_debug_zebra_cmd);
    1043           4 :         install_element(ENABLE_NODE, &bfd_debug_network_cmd);
    1044             : 
    1045           4 :         install_element(CONFIG_NODE, &bfd_debug_distributed_cmd);
    1046           4 :         install_element(CONFIG_NODE, &bfd_debug_peer_cmd);
    1047           4 :         install_element(CONFIG_NODE, &bfd_debug_zebra_cmd);
    1048           4 :         install_element(CONFIG_NODE, &bfd_debug_network_cmd);
    1049             : 
    1050             :         /* Install BFD node and commands. */
    1051           4 :         install_node(&bfd_node);
    1052           4 :         install_default(BFD_NODE);
    1053             : 
    1054             :         /* Install BFD peer node. */
    1055           4 :         install_node(&bfd_peer_node);
    1056           4 :         install_default(BFD_PEER_NODE);
    1057             : 
    1058           4 :         bfdd_cli_init();
    1059           4 : }

Generated by: LCOV version v1.16-topotato