ns2: Dump frame relay state to VTY during "show ns"

When doing a "show ns", let's also dump the state of the frame
relay network, with all its links and DLCs (if any).

Change-Id: I798af3e97dc014b6e0fcde86560a1809852f7510
Related: OS#4877
diff --git a/src/gb/frame_relay.c b/src/gb/frame_relay.c
index 84cd17f..4d1df67 100644
--- a/src/gb/frame_relay.c
+++ b/src/gb/frame_relay.c
@@ -1014,3 +1014,38 @@
 	}
 	return NULL;
 }
+
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/tdef_vty.h>
+
+static void fr_dlc_dump_vty(struct vty *vty, const struct osmo_fr_dlc *dlc)
+{
+	vty_out(vty, "  FR DLC %05u: %s%s%s%s", dlc->dlci,
+		dlc->active ? "ACTIVE" : "INACTIVE",
+		dlc->add ? " ADDED" : "", dlc->del ? " DELETED" : "", VTY_NEWLINE);
+}
+
+static void fr_link_dump_vty(struct vty *vty, const struct osmo_fr_link *link)
+{
+	const struct osmo_fr_dlc *dlc;
+
+	vty_out(vty, "FR Link '%s': Role %s, LastRxSeq %u, LastTxSeq %u%s",
+		link->name, link->role == FR_ROLE_USER_EQUIPMENT ? "USER" : "NETWORK",
+		link->last_rx_seq, link->last_tx_seq, VTY_NEWLINE);
+	llist_for_each_entry(dlc, &link->dlc_list, list) {
+		fr_dlc_dump_vty(vty, dlc);
+	}
+}
+
+void osmo_fr_network_dump_vty(struct vty *vty, const struct osmo_fr_network *net)
+{
+	struct osmo_fr_link *link;
+
+	vty_out(vty, "FR Network: N391 %u, N392 %u, N393 %u%s",
+		net->n391, net->n392, net->n393, VTY_NEWLINE);
+	osmo_tdef_vty_out_all(vty, net->T_defs, "    ");
+	llist_for_each_entry(link, &net->links, list) {
+		fr_link_dump_vty(vty, link);
+	}
+}
diff --git a/src/gb/gprs_ns2_vty.c b/src/gb/gprs_ns2_vty.c
index b678db4..1ef22f5 100644
--- a/src/gb/gprs_ns2_vty.c
+++ b/src/gb/gprs_ns2_vty.c
@@ -1922,6 +1922,8 @@
 {
 	dump_ns_entities(vty, vty_nsi, false, false);
 	dump_ns_bind(vty, vty_nsi, false);
+	if (vty_fr_network && llist_count(&vty_fr_network->links))
+		osmo_fr_network_dump_vty(vty, vty_fr_network);
 	return CMD_SUCCESS;
 }