summaryrefslogtreecommitdiffstats
path: root/bfdd
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@opensourcerouting.org>2020-08-18 22:00:33 +0200
committerRafael Zalamena <rzalamena@opensourcerouting.org>2020-11-24 11:54:07 +0100
commit400632a9a2edbdac79befb5574480db661f33213 (patch)
tree8202fa8ee0857f701e4439a64b2f5d82bbc710a1 /bfdd
parentbfdd: integrate distributed BFD (diff)
downloadfrr-400632a9a2edbdac79befb5574480db661f33213.tar.xz
frr-400632a9a2edbdac79befb5574480db661f33213.zip
bfdd: distributed BFD show commands
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>
Diffstat (limited to 'bfdd')
-rw-r--r--bfdd/bfd.h12
-rw-r--r--bfdd/bfdd_vty.c21
-rw-r--r--bfdd/dplane.c118
3 files changed, 151 insertions, 0 deletions
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 8b06ccdd0..d6e762c52 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -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_ */
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index 7a00d0a02..53e23cf6c 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -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);
diff --git a/bfdd/dplane.c b/bfdd/dplane.c
index 5785c349c..f68fd2cb2 100644
--- a/bfdd/dplane.c
+++ b/bfdd/dplane.c
@@ -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;
+}