/* Initialize BFD integration library. */
bfd_protocol_integration_init(zc, tm);
}
+
+/*
+ * Display functions
+ */
+static void static_bfd_show_nexthop_json(struct vty *vty,
+ struct json_object *jo,
+ const struct static_nexthop *sn)
+{
+ const struct prefix *dst_p, *src_p;
+ struct json_object *jo_nh;
+
+ jo_nh = json_object_new_object();
+
+ srcdest_rnode_prefixes(sn->rn, &dst_p, &src_p);
+ if (src_p)
+ json_object_string_addf(jo_nh, "from", "%pFX", src_p);
+
+ json_object_string_addf(jo_nh, "prefix", "%pFX", dst_p);
+ json_object_string_add(jo_nh, "vrf", sn->nh_vrfname);
+
+ json_object_boolean_add(jo_nh, "installed", !sn->path_down);
+
+ json_object_array_add(jo, jo_nh);
+}
+
+static void static_bfd_show_path_json(struct vty *vty, struct json_object *jo,
+ struct route_table *rt)
+{
+ struct route_node *rn;
+
+ for (rn = route_top(rt); rn; rn = srcdest_route_next(rn)) {
+ struct static_route_info *si = static_route_info_from_rnode(rn);
+ struct static_path *sp;
+
+ if (si == NULL)
+ continue;
+
+ frr_each (static_path_list, &si->path_list, sp) {
+ struct static_nexthop *sn;
+
+ frr_each (static_nexthop_list, &sp->nexthop_list, sn) {
+ /* Skip non configured BFD sessions. */
+ if (sn->bsp == NULL)
+ continue;
+
+ static_bfd_show_nexthop_json(vty, jo, sn);
+ }
+ }
+ }
+}
+
+static void static_bfd_show_json(struct vty *vty)
+{
+ struct json_object *jo, *jo_path, *jo_afi_safi;
+ struct vrf *vrf;
+
+ jo = json_object_new_object();
+ jo_path = json_object_new_object();
+
+ json_object_object_add(jo, "path-list", jo_path);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ const struct static_vrf *svrf = vrf->info;
+ struct route_table *rt;
+
+ jo_afi_safi = json_object_new_array();
+ json_object_object_add(jo_path, "ipv4-unicast", jo_afi_safi);
+ rt = svrf->stable[AFI_IP][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path_json(vty, jo_afi_safi, rt);
+
+ jo_afi_safi = json_object_new_array();
+ json_object_object_add(jo_path, "ipv4-multicast", jo_afi_safi);
+ rt = svrf->stable[AFI_IP][SAFI_MULTICAST];
+ if (rt)
+ static_bfd_show_path_json(vty, jo_afi_safi, rt);
+
+ jo_afi_safi = json_object_new_array();
+ json_object_object_add(jo_path, "ipv6-unicast", jo_afi_safi);
+ rt = svrf->stable[AFI_IP6][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path_json(vty, jo_afi_safi, rt);
+ }
+
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
+ json_object_free(jo);
+}
+
+static void static_bfd_show_nexthop(struct vty *vty,
+ const struct static_nexthop *sn)
+{
+ vty_out(vty, " %pRN", sn->rn);
+
+ if (sn->bsp == NULL) {
+ vty_out(vty, "\n");
+ return;
+ }
+
+ if (sn->type == STATIC_IPV4_GATEWAY ||
+ sn->type == STATIC_IPV4_GATEWAY_IFNAME)
+ vty_out(vty, " peer %pI4", &sn->addr.ipv4);
+ else if (sn->type == STATIC_IPV6_GATEWAY ||
+ sn->type == STATIC_IPV6_GATEWAY_IFNAME)
+ vty_out(vty, " peer %pI6", &sn->addr.ipv6);
+ else
+ vty_out(vty, " peer unknown");
+
+ vty_out(vty, " (status: %s)\n",
+ sn->path_down ? "uninstalled" : "installed");
+}
+
+static void static_bfd_show_path(struct vty *vty, struct route_table *rt)
+{
+ struct route_node *rn;
+
+ for (rn = route_top(rt); rn; rn = srcdest_route_next(rn)) {
+ struct static_route_info *si = static_route_info_from_rnode(rn);
+ struct static_path *sp;
+
+ if (si == NULL)
+ continue;
+
+ frr_each (static_path_list, &si->path_list, sp) {
+ struct static_nexthop *sn;
+
+ frr_each (static_nexthop_list, &sp->nexthop_list, sn) {
+ /* Skip non configured BFD sessions. */
+ if (sn->bsp == NULL)
+ continue;
+
+ static_bfd_show_nexthop(vty, sn);
+ }
+ }
+ }
+}
+
+void static_bfd_show(struct vty *vty, bool json)
+{
+ struct vrf *vrf;
+
+ if (json) {
+ static_bfd_show_json(vty);
+ return;
+ }
+
+ vty_out(vty, "Showing BFD monitored static routes:\n");
+ vty_out(vty, "\n Next hops:\n");
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ const struct static_vrf *svrf = vrf->info;
+ struct route_table *rt;
+
+ vty_out(vty, " VRF %s IPv4 Unicast:\n", vrf->name);
+ rt = svrf->stable[AFI_IP][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path(vty, rt);
+
+ vty_out(vty, "\n VRF %s IPv4 Multicast:\n", vrf->name);
+ rt = svrf->stable[AFI_IP][SAFI_MULTICAST];
+ if (rt)
+ static_bfd_show_path(vty, rt);
+
+ vty_out(vty, "\n VRF %s IPv6 Unicast:\n", vrf->name);
+ rt = svrf->stable[AFI_IP6][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path(vty, rt);
+ }
+
+ vty_out(vty, "\n");
+}