From 20cc36864a0ff0300fd103b56f68546495688e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Thu, 4 Jan 2024 07:47:49 +0100 Subject: [PATCH] OSPF: Enable BFD integration admin@example:/config/> edit routing control-plane-protocol ietf-ospf:ospfv2 name default admin@example:/config/routing/control-plane-protocol/ietf-ospf:ospfv2/name/default/ospf/> set area 0.0.0.0 interface e0 bfd enabled true admin@example:/config/routing/control-plane-protocol/static/name/default/> leave admin@example:/> --- doc/networking.md | 9 +++++ src/confd/bin/bootstrap | 1 + src/confd/src/ietf-routing.c | 42 ++++++++++++++++++-- src/confd/yang/infix-routing@2023-11-23.yang | 7 +++- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/doc/networking.md b/doc/networking.md index 6419a43b..6919c083 100644 --- a/doc/networking.md +++ b/doc/networking.md @@ -439,6 +439,15 @@ To configure a NSSA area with summary routes: admin@example:/config/routing/control-plane-protocol/static/name/default/> leave admin@example:/> +### Bidirectional Forwarding Detection (BFD) +It is possible to enable BFD per interface to speed up detection of +link loss. + + admin@example:/config/> edit routing control-plane-protocol ietf-ospf:ospfv2 name default + admin@example:/config/routing/control-plane-protocol/ietf-ospf:ospfv2/name/default/ospf/> set area 0.0.0.0 interface e0 bfd enabled true + admin@example:/config/routing/control-plane-protocol/static/name/default/> leave + admin@example:/> + ### Debug OSPFv2 Using NETCONF and the YANG model *ietf-routing* it is possible to read the OSPF routing table, neighbors and more, that may be useful for debugging the OSPFv2 setup. diff --git a/src/confd/bin/bootstrap b/src/confd/bin/bootstrap index c0fffb75..422f4431 100755 --- a/src/confd/bin/bootstrap +++ b/src/confd/bin/bootstrap @@ -206,6 +206,7 @@ sysrepoctl -s $SEARCH \ -i ietf-ipv6-unicast-routing@2018-03-13.yang -g wheel -p 0660 \ -i ietf-ipv4-unicast-routing@2018-03-13.yang -g wheel -p 0660 \ -i ietf-ospf@2022-10-19.yang -g wheel -p 0660 \ + -e bfd \ -i iana-if-type@2023-01-26.yang -g wheel -p 0660 \ -i ieee802-dot1q-types@2022-10-29.yang -g wheel -p 0660 \ -i infix-ip@2023-09-14.yang -g wheel -p 0660 \ diff --git a/src/confd/src/ietf-routing.c b/src/confd/src/ietf-routing.c index aca0a195..a6052b08 100644 --- a/src/confd/src/ietf-routing.c +++ b/src/confd/src/ietf-routing.c @@ -15,6 +15,8 @@ #define OSPFD_CONF "/etc/frr/ospfd.conf" #define OSPFD_CONF_NEXT OSPFD_CONF "+" #define OSPFD_CONF_PREV OSPFD_CONF "-" +#define BFDD_CONF "/etc/frr/bfd_enabled" /* Just signal that bfd should be enabled*/ + #define FRR_STATIC_CONFIG "! Generated by Infix\n\ frr defaults traditional\n\ hostname Router\n\ @@ -25,12 +27,16 @@ log syslog informational\n" int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FILE *fp) { struct lyd_node *interface, *interfaces, *area; + int bfd_enabled = 0; LY_LIST_FOR(lyd_child(areas), area) { interfaces = lydx_get_child(area, "interfaces"); const char *area_id = lydx_get_cattr(area, "area-id"); LY_LIST_FOR(lyd_child(interfaces), interface) { const char *hello, *dead, *retransmit, *transmit; if (lydx_get_bool(interface, "enabled")) { + struct lyd_node *bfd; + bfd = lydx_get_child(interface, "bfd"); + bfd_enabled = lydx_get_bool(bfd, "enabled"); fprintf(fp, "interface %s\n", lydx_get_cattr(interface, "name")); hello = lydx_get_cattr(interface, "hello-interval"); dead = lydx_get_cattr(interface, "dead-interval"); @@ -45,10 +51,12 @@ int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FIL fprintf(fp, " ip ospf retransmit-interval %s\n", retransmit); if (transmit) fprintf(fp, " ip ospf transmit-delay %s\n", transmit); + if (bfd_enabled) + fputs(" ip ospf bfd\n", fp); } } } - return 0; + return bfd_enabled; } int parse_ospf_redistribute(sr_session_ctx_t *session, struct lyd_node *redistributes, FILE *fp) @@ -92,6 +100,7 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf) { struct lyd_node *areas; int num_areas = 0; + int bfd_enabled = 0; FILE *fp; fp = fopen(OSPFD_CONF_NEXT, "w"); if (!fp) { @@ -100,16 +109,21 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf) } fputs(FRR_STATIC_CONFIG, fp); areas = lydx_get_child(ospf, "areas"); - parse_ospf_interfaces(session, areas, fp); + bfd_enabled = parse_ospf_interfaces(session, areas, fp); fputs("router ospf\n", fp); num_areas = parse_ospf_areas(session, areas, fp); parse_ospf_redistribute(session, lydx_get_child(ospf, "redistribute"), fp); fclose(fp); + if (!bfd_enabled) + (void)remove(BFDD_CONF); if (!num_areas) { (void)remove(OSPFD_CONF_NEXT); + return 0; } + if (bfd_enabled) + touch(BFDD_CONF); return 0; } @@ -169,8 +183,8 @@ static int parse_static_routes(sr_session_ctx_t *session, struct lyd_node *paren static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { - int staticd_enabled = 0, ospfd_enabled = 0; - bool ospfd_running, staticd_running; + int staticd_enabled = 0, ospfd_enabled = 0, bfdd_enabled = 0; + bool ospfd_running, staticd_running, bfdd_running; struct lyd_node *cplane, *tmp; bool restart_zebra = false; int rc = SR_ERR_OK; @@ -196,8 +210,10 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su /* Check if passed validation in previous event */ staticd_enabled = fexist(STATICD_CONF_NEXT); ospfd_enabled = fexist(OSPFD_CONF_NEXT); + bfdd_enabled = fexist(BFDD_CONF); staticd_running = !systemf("initctl -bfq status staticd"); ospfd_running = !systemf("initctl -bfq status ospfd"); + bfdd_running = !systemf("initctl -bfq status bfdd"); if (staticd_running && !staticd_enabled) { if (systemf("initctl -bfq disable staticd")) { ERROR("Failed to disable static routing daemon"); @@ -207,6 +223,15 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su /* Remove all generated files */ (void)remove(STATICD_CONF); } + if (bfdd_running && !bfdd_enabled) { + if (systemf("initctl -bfq disable bfdd")) { + ERROR("Failed to disable BFD routing daemon"); + rc = SR_ERR_INTERNAL; + goto err_abandon; + } + /* Remove all generated files */ + (void)remove(BFDD_CONF); + } if (ospfd_running && !ospfd_enabled) { if (systemf("initctl -bfq disable ospfd")) { ERROR("Failed to disable OSPF routing daemon"); @@ -216,6 +241,15 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su /* Remove all generated files */ (void)remove(OSPFD_CONF); } + if (bfdd_enabled) { + if (!bfdd_running) { + if (systemf("initctl -bfq enable bfdd")) { + ERROR("Failed to enable OSPF routing daemon"); + rc = SR_ERR_INTERNAL; + goto err_abandon; + } + } + } if (ospfd_enabled) { (void)remove(OSPFD_CONF_PREV); (void)rename(OSPFD_CONF, OSPFD_CONF_PREV); diff --git a/src/confd/yang/infix-routing@2023-11-23.yang b/src/confd/yang/infix-routing@2023-11-23.yang index 9f42dc4f..1db49b43 100644 --- a/src/confd/yang/infix-routing@2023-11-23.yang +++ b/src/confd/yang/infix-routing@2023-11-23.yang @@ -266,11 +266,14 @@ module infix-routing { deviation "/ietf-r:routing/ietf-r:control-plane-protocols/ietf-r:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:node-flag" { deviate not-supported; } - deviation "/ietf-r:routing/ietf-r:control-plane-protocols/ietf-r:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:bfd" + deviation "/ietf-r:routing/ietf-r:control-plane-protocols/ietf-r:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:bfd/ospf:local-multiplier" + { + deviate not-supported; + } + deviation "/ietf-r:routing/ietf-r:control-plane-protocols/ietf-r:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:bfd/ospf:interval-config-type" { deviate not-supported; } - deviation "/ietf-r:routing/ietf-r:control-plane-protocols/ietf-r:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface/ospf:interface-type" { deviate not-supported;