]> git.proxmox.com Git - mirror_frr.git/blobdiff - bfdd/bfdd_vty.c
Merge pull request #3357 from ton31337/fix/optional_args_for_extcommunity-lists
[mirror_frr.git] / bfdd / bfdd_vty.c
index 73ce067618214b004d16ffc5946475ce2d65580b..8f8fff6b1837295139e65c709ff94d3522eef18f 100644 (file)
@@ -58,12 +58,25 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
                              const char *ifname, const char *vrfname,
                              char *ebuf, size_t ebuflen);
 
+static void _display_peer_header(struct vty *vty, struct bfd_session *bs);
 static struct json_object *__display_peer_json(struct bfd_session *bs);
+static struct json_object *_peer_json_header(struct bfd_session *bs);
 static void _display_peer_json(struct vty *vty, struct bfd_session *bs);
 static void _display_peer(struct vty *vty, struct bfd_session *bs);
 static void _display_all_peers(struct vty *vty, bool use_json);
 static void _display_peer_iter(struct hash_backet *hb, void *arg);
 static void _display_peer_json_iter(struct hash_backet *hb, void *arg);
+static void _display_peer_counter(struct vty *vty, struct bfd_session *bs);
+static struct json_object *__display_peer_counters_json(struct bfd_session *bs);
+static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs);
+static void _display_peer_counter_iter(struct hash_backet *hb, void *arg);
+static void _display_peer_counter_json_iter(struct hash_backet *hb, void *arg);
+static void _display_peers_counter(struct vty *vty, bool use_json);
+static struct bfd_session *
+_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
+                   const char *label, const char *peer_str,
+                   const char *local_str, const char *ifname,
+                   const char *vrfname);
 
 
 /*
@@ -77,7 +90,7 @@ DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
 
 DEFUN_NOSH(
        bfd_peer_enter, bfd_peer_enter_cmd,
-       "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
+       "peer <A.B.C.D|X:X::X:X> [{[multihop] local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
        PEER_STR PEER_IPV4_STR PEER_IPV6_STR
        MHOP_STR
        LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
@@ -154,7 +167,11 @@ DEFPY(bfd_peer_detectmultiplier, bfd_peer_detectmultiplier_cmd,
        struct bfd_session *bs;
 
        bs = VTY_GET_CONTEXT(bfd_session);
+       if (bs->detect_mult == multiplier)
+               return CMD_SUCCESS;
+
        bs->detect_mult = multiplier;
+       bfd_set_polling(bs);
 
        return CMD_SUCCESS;
 }
@@ -167,7 +184,11 @@ DEFPY(bfd_peer_recvinterval, bfd_peer_recvinterval_cmd,
        struct bfd_session *bs;
 
        bs = VTY_GET_CONTEXT(bfd_session);
+       if (bs->timers.required_min_rx == (uint32_t)(interval * 1000))
+               return CMD_SUCCESS;
+
        bs->timers.required_min_rx = interval * 1000;
+       bfd_set_polling(bs);
 
        return CMD_SUCCESS;
 }
@@ -180,7 +201,11 @@ DEFPY(bfd_peer_txinterval, bfd_peer_txinterval_cmd,
        struct bfd_session *bs;
 
        bs = VTY_GET_CONTEXT(bfd_session);
+       if (bs->up_min_tx == (uint32_t)(interval * 1000))
+               return CMD_SUCCESS;
+
        bs->up_min_tx = interval * 1000;
+       bfd_set_polling(bs);
 
        return CMD_SUCCESS;
 }
@@ -193,7 +218,11 @@ DEFPY(bfd_peer_echointerval, bfd_peer_echointerval_cmd,
        struct bfd_session *bs;
 
        bs = VTY_GET_CONTEXT(bfd_session);
+       if (bs->timers.required_min_echo == (uint32_t)(interval * 1000))
+               return CMD_SUCCESS;
+
        bs->timers.required_min_echo = interval * 1000;
+       bfd_set_polling(bs);
 
        return CMD_SUCCESS;
 }
@@ -337,11 +366,8 @@ DEFPY(bfd_no_peer, bfd_no_peer_cmd,
 /*
  * Show commands helper functions
  */
-static void _display_peer(struct vty *vty, struct bfd_session *bs)
+static void _display_peer_header(struct vty *vty, struct bfd_session *bs)
 {
-       char buf[256];
-       time_t now;
-
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
                vty_out(vty, "\tpeer %s", satostr(&bs->mhop.peer));
                vty_out(vty, " multihop");
@@ -350,7 +376,10 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
                        vty_out(vty, " vrf %s", bs->mhop.vrf_name);
                vty_out(vty, "\n");
        } else {
-               vty_out(vty, "\tpeer %s", satostr(&bs->mhop.peer));
+               vty_out(vty, "\tpeer %s", satostr(&bs->shop.peer));
+               if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
+                       vty_out(vty, " local-address %s",
+                               satostr(&bs->local_address));
                if (bs->shop.port_name[0])
                        vty_out(vty, " interface %s", bs->shop.port_name);
                vty_out(vty, "\n");
@@ -358,6 +387,14 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
 
        if (bs->pl)
                vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
+}
+
+static void _display_peer(struct vty *vty, struct bfd_session *bs)
+{
+       char buf[256];
+       time_t now;
+
+       _display_peer_header(vty, bs);
 
        vty_out(vty, "\t\tID: %u\n", bs->discrs.my_discr);
        vty_out(vty, "\t\tRemote ID: %u\n", bs->discrs.remote_discr);
@@ -371,7 +408,7 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
                vty_out(vty, "down\n");
 
                now = monotime(NULL);
-               integer2timestr(now - bs->uptime.tv_sec, buf, sizeof(buf));
+               integer2timestr(now - bs->downtime.tv_sec, buf, sizeof(buf));
                vty_out(vty, "\t\tDowntime: %s\n", buf);
                break;
        case PTM_BFD_INIT:
@@ -396,8 +433,13 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
        vty_out(vty, "\t\tLocal timers:\n");
        vty_out(vty, "\t\t\tReceive interval: %" PRIu32 "ms\n",
                bs->timers.required_min_rx / 1000);
-       vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms\n",
+       vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms",
                bs->timers.desired_min_tx / 1000);
+       if (bs->up_min_tx != bs->timers.desired_min_tx)
+               vty_out(vty, " (configured %" PRIu32 "ms)\n",
+                       bs->up_min_tx / 1000);
+       else
+               vty_out(vty, "\n");
 
        vty_out(vty, "\t\t\tEcho transmission interval: ");
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
@@ -417,7 +459,7 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
        vty_out(vty, "\n");
 }
 
-static struct json_object *__display_peer_json(struct bfd_session *bs)
+static struct json_object *_peer_json_header(struct bfd_session *bs)
 {
        struct json_object *jo = json_object_new_object();
 
@@ -430,6 +472,9 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
        } else {
                json_object_boolean_false_add(jo, "multihop");
                json_object_string_add(jo, "peer", satostr(&bs->shop.peer));
+               if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
+                       json_object_string_add(jo, "local",
+                                              satostr(&bs->local_address));
                if (bs->shop.port_name[0])
                        json_object_string_add(jo, "interface",
                                               bs->shop.port_name);
@@ -438,6 +483,13 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
        if (bs->pl)
                json_object_string_add(jo, "label", bs->pl->pl_label);
 
+       return jo;
+}
+
+static struct json_object *__display_peer_json(struct bfd_session *bs)
+{
+       struct json_object *jo = _peer_json_header(bs);
+
        json_object_int_add(jo, "id", bs->discrs.my_discr);
        json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
 
@@ -448,7 +500,7 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
        case PTM_BFD_DOWN:
                json_object_string_add(jo, "status", "down");
                json_object_int_add(jo, "downtime",
-                                   monotime(NULL) - bs->uptime.tv_sec);
+                                   monotime(NULL) - bs->downtime.tv_sec);
                break;
        case PTM_BFD_INIT:
                json_object_string_add(jo, "status", "init");
@@ -523,6 +575,7 @@ static void _display_all_peers(struct vty *vty, bool use_json)
        struct json_object *jo;
 
        if (use_json == false) {
+               vty_out(vty, "BFD Peers:\n");
                bfd_id_iterate(_display_peer_iter, vty);
                return;
        }
@@ -534,37 +587,94 @@ static void _display_all_peers(struct vty *vty, bool use_json)
        json_object_free(jo);
 }
 
-DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd peers [json]",
-      SHOW_STR
-      "Bidirection Forwarding Detection\n"
-      "BFD peers status\n"
-      JSON_STR)
+static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
+{
+       _display_peer_header(vty, bs);
+
+       vty_out(vty, "\t\tControl packet input: %" PRIu64 " packets\n",
+               bs->stats.rx_ctrl_pkt);
+       vty_out(vty, "\t\tControl packet output: %" PRIu64 " packets\n",
+               bs->stats.tx_ctrl_pkt);
+       vty_out(vty, "\t\tEcho packet input: %" PRIu64 " packets\n",
+               bs->stats.rx_echo_pkt);
+       vty_out(vty, "\t\tEcho packet output: %" PRIu64 " packets\n",
+               bs->stats.tx_echo_pkt);
+       vty_out(vty, "\t\tSession up events: %" PRIu64 "\n",
+               bs->stats.session_up);
+       vty_out(vty, "\t\tSession down events: %" PRIu64 "\n",
+               bs->stats.session_down);
+       vty_out(vty, "\t\tZebra notifications: %" PRIu64 "\n",
+               bs->stats.znotification);
+       vty_out(vty, "\n");
+}
+
+static struct json_object *__display_peer_counters_json(struct bfd_session *bs)
 {
-       bool json = use_json(argc, argv);
+       struct json_object *jo = _peer_json_header(bs);
 
-       if (json) {
-               _display_all_peers(vty, true);
-       } else {
+       json_object_int_add(jo, "control-packet-input", bs->stats.rx_ctrl_pkt);
+       json_object_int_add(jo, "control-packet-output", bs->stats.tx_ctrl_pkt);
+       json_object_int_add(jo, "echo-packet-input", bs->stats.rx_echo_pkt);
+       json_object_int_add(jo, "echo-packet-output", bs->stats.tx_echo_pkt);
+       json_object_int_add(jo, "session-up", bs->stats.session_up);
+       json_object_int_add(jo, "session-down", bs->stats.session_down);
+       json_object_int_add(jo, "zebra-notifications", bs->stats.znotification);
+
+       return jo;
+}
+
+static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
+{
+       struct json_object *jo = __display_peer_counters_json(bs);
+
+       vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
+       json_object_free(jo);
+}
+
+static void _display_peer_counter_iter(struct hash_backet *hb, void *arg)
+{
+       struct vty *vty = arg;
+       struct bfd_session *bs = hb->data;
+
+       _display_peer_counter(vty, bs);
+}
+
+static void _display_peer_counter_json_iter(struct hash_backet *hb, void *arg)
+{
+       struct json_object *jo = arg, *jon = NULL;
+       struct bfd_session *bs = hb->data;
+
+       jon = __display_peer_counters_json(bs);
+       if (jon == NULL) {
+               log_warning("%s: not enough memory", __func__);
+               return;
+       }
+
+       json_object_array_add(jo, jon);
+}
+
+static void _display_peers_counter(struct vty *vty, bool use_json)
+{
+       struct json_object *jo;
+
+       if (use_json == false) {
                vty_out(vty, "BFD Peers:\n");
-               _display_all_peers(vty, false);
+               bfd_id_iterate(_display_peer_counter_iter, vty);
+               return;
        }
 
-       return CMD_SUCCESS;
+       jo = json_object_new_array();
+       bfd_id_iterate(_display_peer_counter_json_iter, jo);
+
+       vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
+       json_object_free(jo);
 }
 
-DEFPY(bfd_show_peer, bfd_show_peer_cmd,
-      "show bfd 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|vrf NAME$vrfname}]> [json]",
-      SHOW_STR
-      "Bidirection Forwarding Detection\n"
-      "BFD peers status\n"
-      "Peer label\n"
-      PEER_IPV4_STR PEER_IPV6_STR
-      MHOP_STR
-      LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
-      INTERFACE_STR
-      LOCAL_INTF_STR
-      VRF_STR VRF_NAME_STR
-      JSON_STR)
+static struct bfd_session *
+_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
+                   const char *label, const char *peer_str,
+                   const char *local_str, const char *ifname,
+                   const char *vrfname)
 {
        int idx;
        bool mhop;
@@ -581,7 +691,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
                        bs = pl->pl_bs;
        } else {
                strtosa(peer_str, &psa);
-               if (local) {
+               if (local_str) {
                        strtosa(local_str, &lsa);
                        lsap = &lsa;
                } else
@@ -595,7 +705,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
                    != 0) {
                        vty_out(vty, "%% Invalid peer configuration: %s\n",
                                errormsg);
-                       return CMD_WARNING_CONFIG_FAILED;
+                       return NULL;
                }
 
                bs = bs_peer_find(&bpc);
@@ -607,15 +717,49 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
                        label ? label : peer_str);
                if (ifname)
                        vty_out(vty, " interface %s", ifname);
-               if (local)
+               if (local_str)
                        vty_out(vty, " local-address %s", local_str);
                if (vrfname)
                        vty_out(vty, " vrf %s", vrfname);
                vty_out(vty, "'\n");
 
-               return CMD_WARNING_CONFIG_FAILED;
+               return NULL;
        }
 
+       return bs;
+}
+
+
+/*
+ * Show commands.
+ */
+DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd peers [json]",
+      SHOW_STR
+      "Bidirection Forwarding Detection\n"
+      "BFD peers status\n" JSON_STR)
+{
+       _display_all_peers(vty, use_json(argc, argv));
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(bfd_show_peer, bfd_show_peer_cmd,
+      "show bfd 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|vrf NAME$vrfname}]> [json]",
+      SHOW_STR
+      "Bidirection Forwarding Detection\n"
+      "BFD peers status\n"
+      "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
+             LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR VRF_STR
+                     VRF_NAME_STR JSON_STR)
+{
+       struct bfd_session *bs;
+
+       /* Look up the BFD peer. */
+       bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
+                                ifname, vrfname);
+       if (bs == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
+
        if (use_json(argc, argv)) {
                _display_peer_json(vty, bs);
        } else {
@@ -626,6 +770,54 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
        return CMD_SUCCESS;
 }
 
+DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
+      "show bfd 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|vrf NAME$vrfname}]> counters [json]",
+      SHOW_STR
+      "Bidirection Forwarding Detection\n"
+      "BFD peers status\n"
+      "Peer label\n"
+      PEER_IPV4_STR
+      PEER_IPV6_STR
+      MHOP_STR
+      LOCAL_STR
+      LOCAL_IPV4_STR
+      LOCAL_IPV6_STR
+      INTERFACE_STR
+      LOCAL_INTF_STR
+      VRF_STR
+      VRF_NAME_STR
+      "Show BFD peer counters information\n"
+      JSON_STR)
+{
+       struct bfd_session *bs;
+
+       /* Look up the BFD peer. */
+       bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
+                                ifname, vrfname);
+       if (bs == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
+
+       if (use_json(argc, argv))
+               _display_peer_counters_json(vty, bs);
+       else
+               _display_peer_counter(vty, bs);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
+      "show bfd peers counters [json]",
+      SHOW_STR
+      "Bidirection Forwarding Detection\n"
+      "BFD peers status\n"
+      "Show BFD peer counters information\n"
+      JSON_STR)
+{
+       _display_peers_counter(vty, use_json(argc, argv));
+
+       return CMD_SUCCESS;
+}
+
 
 /*
  * Function definitions.
@@ -635,7 +827,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
  * Configuration rules:
  *
  * Single hop:
- * peer + (optional vxlan or interface name)
+ * peer + (interface name)
  *
  * Multi hop:
  * peer + local + (optional vrf)
@@ -694,33 +886,9 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
        if (local)
                bpc->bpc_local = *local;
 
-       if (peer) {
-               bpc->bpc_peer = *peer;
-       } else {
-               /* Peer configuration is mandatory. */
-               snprintf(ebuf, ebuflen, "no peer configured");
-               return -1;
-       }
-
+       bpc->bpc_peer = *peer;
        bpc->bpc_mhop = mhop;
 
-#if 0
-       /* Handle VxLAN configuration. */
-       if (vxlan >= 0) {
-               if (vxlan > ((1 << 24) - 1)) {
-                       snprintf(ebuf, ebuflen, "invalid VxLAN %d", vxlan);
-                       return -1;
-               }
-               if (bpc->bpc_mhop) {
-                       snprintf(ebuf, ebuflen,
-                                "multihop doesn't accept VxLAN");
-                       return -1;
-               }
-
-               bpc->bpc_vxlan = vxlan;
-       }
-#endif /* VxLAN */
-
        /* Handle interface specification configuration. */
        if (ifname) {
                if (bpc->bpc_mhop) {
@@ -783,9 +951,9 @@ static void _bfdd_peer_write_config(struct hash_backet *hb, void *arg)
        if (bs->timers.required_min_rx != (BPC_DEF_RECEIVEINTERVAL * 1000))
                vty_out(vty, "  receive-interval %" PRIu32 "\n",
                        bs->timers.required_min_rx / 1000);
-       if (bs->timers.desired_min_tx != (BPC_DEF_TRANSMITINTERVAL * 1000))
+       if (bs->up_min_tx != (BPC_DEF_TRANSMITINTERVAL * 1000))
                vty_out(vty, "  transmit-interval %" PRIu32 "\n",
-                       bs->timers.desired_min_tx / 1000);
+                       bs->up_min_tx / 1000);
        if (bs->timers.required_min_echo != (BPC_DEF_ECHOINTERVAL * 1000))
                vty_out(vty, "  echo-interval %" PRIu32 "\n",
                        bs->timers.required_min_echo / 1000);
@@ -820,6 +988,8 @@ struct cmd_node bfd_peer_node = {
 
 void bfdd_vty_init(void)
 {
+       install_element(ENABLE_NODE, &bfd_show_peers_counters_cmd);
+       install_element(ENABLE_NODE, &bfd_show_peer_counters_cmd);
        install_element(ENABLE_NODE, &bfd_show_peers_cmd);
        install_element(ENABLE_NODE, &bfd_show_peer_cmd);
        install_element(CONFIG_NODE, &bfd_enter_cmd);