]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bfdd: distributed BFD show commands
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 18 Aug 2020 20:00:33 +0000 (17:00 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 24 Nov 2020 10:54:07 +0000 (07:54 -0300)
Show BFD sessions updated counters by asking the data plane for this
information and show data plane statistics.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
bfdd/bfd.h
bfdd/bfdd_vty.c
bfdd/dplane.c

index 8b06ccdd0de273bd7694d150a8dee352b39636fe..d6e762c5237de81d9de9befd201afd21e283277d 100644 (file)
@@ -794,4 +794,16 @@ int bfd_dplane_update_session(const struct bfd_session *bs);
  */
 int bfd_dplane_delete_session(struct bfd_session *bs);
 
+/**
+ * Asks the data plane for updated counters and update the session data
+ * structure.
+ *
+ * \param bs the BFD session that needs updating.
+ *
+ * \returns `0` on success otherwise `-1` on failure.
+ */
+int bfd_dplane_update_session_counters(struct bfd_session *bs);
+
+void bfd_dplane_show_counters(struct vty *vty);
+
 #endif /* _BFD_H_ */
index 7a00d0a029d5be3ac4db8f0f93938913f098dc98..53e23cf6c2139d2c072c659456ef72c1a002d2cd 100644 (file)
@@ -348,6 +348,11 @@ static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
 {
        _display_peer_header(vty, bs);
 
+       /* Ask data plane for updated counters. */
+       if (bfd_dplane_update_session_counters(bs) == -1)
+               zlog_debug("%s: failed to update BFD session counters (%s)",
+                          __func__, bs_to_string(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",
@@ -369,6 +374,11 @@ static struct json_object *__display_peer_counters_json(struct bfd_session *bs)
 {
        struct json_object *jo = _peer_json_header(bs);
 
+       /* Ask data plane for updated counters. */
+       if (bfd_dplane_update_session_counters(bs) == -1)
+               zlog_debug("%s: failed to update BFD session counters (%s)",
+                          __func__, bs_to_string(bs));
+
        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);
@@ -748,6 +758,16 @@ DEFPY(bfd_show_peers_brief, bfd_show_peers_brief_cmd,
        return CMD_SUCCESS;
 }
 
+DEFPY(show_bfd_distributed, show_bfd_distributed_cmd,
+      "show bfd distributed",
+      SHOW_STR
+      "Bidirection Forwarding Detection\n"
+      "Show BFD data plane (distributed BFD) statistics\n")
+{
+       bfd_dplane_show_counters(vty);
+       return CMD_SUCCESS;
+}
+
 DEFPY(
        bfd_debug_distributed, bfd_debug_distributed_cmd,
        "[no] debug bfd distributed",
@@ -970,6 +990,7 @@ void bfdd_vty_init(void)
        install_element(ENABLE_NODE, &bfd_show_peers_cmd);
        install_element(ENABLE_NODE, &bfd_show_peer_cmd);
        install_element(ENABLE_NODE, &bfd_show_peers_brief_cmd);
+       install_element(ENABLE_NODE, &show_bfd_distributed_cmd);
        install_element(ENABLE_NODE, &show_debugging_bfd_cmd);
 
        install_element(ENABLE_NODE, &bfd_debug_distributed_cmd);
index 5785c349c130c3524556f2660f8bf707d1e86774..f68fd2cb26d991c7d2a0508c0c5683908cc524c5 100644 (file)
@@ -244,6 +244,24 @@ static void bfd_dplane_debug_message(const struct bfddp_message *msg)
        }
 }
 
+/**
+ * Gets the next unused non zero identification.
+ *
+ * \param bdc the data plane context.
+ *
+ * \returns next usable id.
+ */
+static uint16_t bfd_dplane_next_id(struct bfd_dplane_ctx *bdc)
+{
+       bdc->last_id++;
+
+       /* Don't use reserved id `0`. */
+       if (bdc->last_id == 0)
+               bdc->last_id = 1;
+
+       return bdc->last_id;
+}
+
 static ssize_t bfd_dplane_flush(struct bfd_dplane_ctx *bdc)
 {
        ssize_t total = 0;
@@ -717,6 +735,52 @@ static int _bfd_dplane_add_session(struct bfd_dplane_ctx *bdc,
        return rv;
 }
 
+static void _bfd_dplane_update_session_counters(struct bfddp_message *msg,
+                                               void *arg)
+{
+       struct bfd_session *bs = arg;
+
+       bs->stats.rx_ctrl_pkt =
+               be64toh(msg->data.session_counters.control_input_packets);
+       bs->stats.tx_ctrl_pkt =
+               be64toh(msg->data.session_counters.control_output_packets);
+       bs->stats.rx_echo_pkt =
+               be64toh(msg->data.session_counters.echo_input_packets);
+       bs->stats.tx_echo_pkt =
+               be64toh(msg->data.session_counters.echo_output_bytes);
+}
+
+/**
+ * Send message to data plane requesting the session counters.
+ *
+ * \param bs the BFD session.
+ *
+ * \returns `0` on failure or the request id.
+ */
+static uint16_t bfd_dplane_request_counters(const struct bfd_session *bs)
+{
+       struct bfddp_message msg = {};
+       size_t msglen = sizeof(msg.header) + sizeof(msg.data.counters_req);
+
+       /* Fill header information. */
+       msg.header.version = BFD_DP_VERSION;
+       msg.header.length = htons(msglen);
+       msg.header.type = htons(DP_REQUEST_SESSION_COUNTERS);
+       msg.header.id = htons(bfd_dplane_next_id(bs->bdc));
+
+       /* Session to get counters. */
+       msg.data.counters_req.lid = htonl(bs->discrs.my_discr);
+
+       /* If enqueue failed, let caller know. */
+       if (bfd_dplane_enqueue(bs->bdc, &msg, msglen) == -1)
+               return 0;
+
+       /* Flush socket. */
+       bfd_dplane_flush(bs->bdc);
+
+       return ntohs(msg.header.id);
+}
+
 /*
  * Data plane listening socket.
  */
@@ -876,3 +940,57 @@ int bfd_dplane_delete_session(struct bfd_session *bs)
 
        return rv;
 }
+
+/*
+ * Data plane CLI.
+ */
+void bfd_dplane_show_counters(struct vty *vty)
+{
+       struct bfd_dplane_ctx *bdc;
+
+#define SHOW_COUNTER(label, counter, formatter)                                \
+       vty_out(vty, "%28s: %" formatter "\n", (label), (counter))
+
+       vty_out(vty, "%28s\n%28s\n", "Data plane", "==========");
+       TAILQ_FOREACH (bdc, &bglobal.bg_dplaneq, entry) {
+               SHOW_COUNTER("File descriptor", bdc->sock, "d");
+               SHOW_COUNTER("Input bytes", bdc->in_bytes, PRIu64);
+               SHOW_COUNTER("Input bytes peak", bdc->in_bytes_peak, PRIu64);
+               SHOW_COUNTER("Input messages", bdc->in_msgs, PRIu64);
+               SHOW_COUNTER("Input current usage", STREAM_READABLE(bdc->inbuf),
+                            "zu");
+               SHOW_COUNTER("Output bytes", bdc->out_bytes, PRIu64);
+               SHOW_COUNTER("Output bytes peak", bdc->out_bytes_peak, PRIu64);
+               SHOW_COUNTER("Output messages", bdc->out_msgs, PRIu64);
+               SHOW_COUNTER("Output full events", bdc->out_fullev, PRIu64);
+               SHOW_COUNTER("Output current usage",
+                            STREAM_READABLE(bdc->inbuf), "zu");
+               vty_out(vty, "\n");
+       }
+#undef SHOW_COUNTER
+}
+
+int bfd_dplane_update_session_counters(struct bfd_session *bs)
+{
+       uint16_t id;
+       int rv;
+
+       /* If session is not using data plane, then just return success. */
+       if (bs->bdc == NULL)
+               return 0;
+
+       /* Make the request. */
+       id = bfd_dplane_request_counters(bs);
+       if (id == 0) {
+               zlog_debug("%s: counters request failed", __func__);
+               return -1;
+       }
+
+       /* Handle interruptions. */
+       do {
+               rv = bfd_dplane_expect(bs->bdc, id,
+                                      _bfd_dplane_update_session_counters, bs);
+       } while (rv == -2);
+
+       return rv;
+}