mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 11:50:21 +00:00
staticd: BFD integration northbound support
Implement all BFD integration northbound callbacks and integrate BFD with `staticd` route installation procedure. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
parent
73df597f5e
commit
351ad68405
219
staticd/static_bfd.c
Normal file
219
staticd/static_bfd.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Static daemon BFD integration.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Network Device Education Foundation, Inc. ("NetDEF")
|
||||
* Rafael Zalamena
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "lib/bfd.h"
|
||||
#include "lib/printfrr.h"
|
||||
#include "lib/srcdest_table.h"
|
||||
|
||||
#include "staticd/static_routes.h"
|
||||
#include "staticd/static_zebra.h"
|
||||
|
||||
#include "lib/openbsd-queue.h"
|
||||
|
||||
/*
|
||||
* Next hop BFD monitoring settings.
|
||||
*/
|
||||
static void static_next_hop_bfd_change(struct static_nexthop *sn,
|
||||
const struct bfd_session_status *bss)
|
||||
{
|
||||
switch (bss->state) {
|
||||
case BSS_UNKNOWN:
|
||||
/* FALLTHROUGH: no known state yet. */
|
||||
case BSS_ADMIN_DOWN:
|
||||
/* NOTHING: we or the remote end administratively shutdown. */
|
||||
break;
|
||||
case BSS_DOWN:
|
||||
/* Peer went down, remove this next hop. */
|
||||
zlog_info("%s: next hop is down, remove it from RIB", __func__);
|
||||
sn->path_down = true;
|
||||
static_zebra_route_add(sn->pn, true);
|
||||
break;
|
||||
case BSS_UP:
|
||||
/* Peer is back up, add this next hop. */
|
||||
zlog_info("%s: next hop is up, add it to RIB", __func__);
|
||||
sn->path_down = false;
|
||||
static_zebra_route_add(sn->pn, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void static_next_hop_bfd_updatecb(
|
||||
__attribute__((unused)) struct bfd_session_params *bsp,
|
||||
const struct bfd_session_status *bss, void *arg)
|
||||
{
|
||||
static_next_hop_bfd_change(arg, bss);
|
||||
}
|
||||
|
||||
static inline int
|
||||
static_next_hop_type_to_family(const struct static_nexthop *sn)
|
||||
{
|
||||
switch (sn->type) {
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
if (sn->type == STATIC_IPV4_GATEWAY ||
|
||||
sn->type == STATIC_IPV4_GATEWAY_IFNAME)
|
||||
return AF_INET;
|
||||
else
|
||||
return AF_INET6;
|
||||
break;
|
||||
case STATIC_IFNAME:
|
||||
case STATIC_BLACKHOLE:
|
||||
default:
|
||||
zlog_err("%s: invalid next hop type", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
|
||||
void static_next_hop_bfd_monitor_enable(struct static_nexthop *sn,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
bool use_interface;
|
||||
bool use_profile;
|
||||
bool use_source;
|
||||
bool onlink;
|
||||
bool mhop;
|
||||
int family;
|
||||
struct ipaddr source;
|
||||
|
||||
use_interface = false;
|
||||
use_source = yang_dnode_exists(dnode, "./source");
|
||||
use_profile = yang_dnode_exists(dnode, "./profile");
|
||||
onlink = yang_dnode_exists(dnode, "../onlink") &&
|
||||
yang_dnode_get_bool(dnode, "../onlink");
|
||||
mhop = yang_dnode_get_bool(dnode, "./multi-hop");
|
||||
|
||||
|
||||
family = static_next_hop_type_to_family(sn);
|
||||
if (family == AF_UNSPEC)
|
||||
return;
|
||||
|
||||
if (sn->type == STATIC_IPV4_GATEWAY_IFNAME ||
|
||||
sn->type == STATIC_IPV6_GATEWAY_IFNAME)
|
||||
use_interface = true;
|
||||
|
||||
/* Reconfigure or allocate new memory. */
|
||||
if (sn->bsp == NULL)
|
||||
sn->bsp = bfd_sess_new(static_next_hop_bfd_updatecb, sn);
|
||||
|
||||
/* Configure the session. */
|
||||
if (use_source)
|
||||
yang_dnode_get_ip(&source, dnode, "./source");
|
||||
|
||||
if (onlink || mhop == false)
|
||||
bfd_sess_set_auto_source(sn->bsp, false);
|
||||
else
|
||||
bfd_sess_set_auto_source(sn->bsp, !use_source);
|
||||
|
||||
/* Configure the session.*/
|
||||
if (family == AF_INET)
|
||||
bfd_sess_set_ipv4_addrs(sn->bsp,
|
||||
use_source ? &source.ip._v4_addr : NULL,
|
||||
&sn->addr.ipv4);
|
||||
else if (family == AF_INET6)
|
||||
bfd_sess_set_ipv6_addrs(sn->bsp,
|
||||
use_source ? &source.ip._v6_addr : NULL,
|
||||
&sn->addr.ipv6);
|
||||
|
||||
bfd_sess_set_interface(sn->bsp, use_interface ? sn->ifname : NULL);
|
||||
|
||||
bfd_sess_set_profile(sn->bsp, use_profile ? yang_dnode_get_string(
|
||||
dnode, "./profile")
|
||||
: NULL);
|
||||
|
||||
bfd_sess_set_hop_count(sn->bsp, (onlink || mhop == false) ? 1 : 254);
|
||||
|
||||
/* Install or update the session. */
|
||||
bfd_sess_install(sn->bsp);
|
||||
|
||||
/* Update current path status. */
|
||||
sn->path_down = (bfd_sess_status(sn->bsp) != BSS_UP);
|
||||
}
|
||||
|
||||
void static_next_hop_bfd_monitor_disable(struct static_nexthop *sn)
|
||||
{
|
||||
bfd_sess_free(&sn->bsp);
|
||||
|
||||
/* Reset path status. */
|
||||
sn->path_down = false;
|
||||
}
|
||||
|
||||
void static_next_hop_bfd_source(struct static_nexthop *sn,
|
||||
const struct ipaddr *source)
|
||||
{
|
||||
int family;
|
||||
|
||||
if (sn->bsp == NULL)
|
||||
return;
|
||||
|
||||
family = static_next_hop_type_to_family(sn);
|
||||
if (family == AF_UNSPEC)
|
||||
return;
|
||||
|
||||
bfd_sess_set_auto_source(sn->bsp, false);
|
||||
if (family == AF_INET)
|
||||
bfd_sess_set_ipv4_addrs(sn->bsp, &source->ip._v4_addr,
|
||||
&sn->addr.ipv4);
|
||||
else if (family == AF_INET6)
|
||||
bfd_sess_set_ipv6_addrs(sn->bsp, &source->ip._v6_addr,
|
||||
&sn->addr.ipv6);
|
||||
|
||||
bfd_sess_install(sn->bsp);
|
||||
}
|
||||
|
||||
void static_next_hop_bfd_auto_source(struct static_nexthop *sn)
|
||||
{
|
||||
if (sn->bsp == NULL)
|
||||
return;
|
||||
|
||||
bfd_sess_set_auto_source(sn->bsp, true);
|
||||
bfd_sess_install(sn->bsp);
|
||||
}
|
||||
|
||||
void static_next_hop_bfd_multi_hop(struct static_nexthop *sn, bool mhop)
|
||||
{
|
||||
if (sn->bsp == NULL)
|
||||
return;
|
||||
|
||||
bfd_sess_set_hop_count(sn->bsp, mhop ? 254 : 1);
|
||||
bfd_sess_install(sn->bsp);
|
||||
}
|
||||
|
||||
void static_next_hop_bfd_profile(struct static_nexthop *sn, const char *name)
|
||||
{
|
||||
if (sn->bsp == NULL)
|
||||
return;
|
||||
|
||||
bfd_sess_set_profile(sn->bsp, name);
|
||||
bfd_sess_install(sn->bsp);
|
||||
}
|
||||
|
||||
void static_bfd_initialize(struct zclient *zc, struct thread_master *tm)
|
||||
{
|
||||
/* Initialize BFD integration library. */
|
||||
bfd_protocol_integration_init(zc, tm);
|
||||
}
|
@ -116,6 +116,33 @@ const struct frr_yang_module_info frr_staticd_info = {
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring",
|
||||
.cbs = {
|
||||
.create = route_next_hop_bfd_create,
|
||||
.destroy = route_next_hop_bfd_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/source",
|
||||
.cbs = {
|
||||
.modify = route_next_hop_bfd_source_modify,
|
||||
.destroy = route_next_hop_bfd_source_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/multi-hop",
|
||||
.cbs = {
|
||||
.modify = route_next_hop_bfd_multi_hop_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/profile",
|
||||
.cbs = {
|
||||
.modify = route_next_hop_bfd_profile_modify,
|
||||
.destroy = route_next_hop_bfd_profile_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list",
|
||||
.cbs = {
|
||||
|
@ -63,6 +63,13 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int route_next_hop_bfd_create(struct nb_cb_create_args *args);
|
||||
int route_next_hop_bfd_destroy(struct nb_cb_destroy_args *args);
|
||||
int route_next_hop_bfd_source_modify(struct nb_cb_modify_args *args);
|
||||
int route_next_hop_bfd_source_destroy(struct nb_cb_destroy_args *args);
|
||||
int route_next_hop_bfd_profile_modify(struct nb_cb_modify_args *args);
|
||||
int route_next_hop_bfd_profile_destroy(struct nb_cb_destroy_args *args);
|
||||
int route_next_hop_bfd_multi_hop_modify(struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy(
|
||||
|
@ -748,6 +748,113 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring
|
||||
*/
|
||||
int route_next_hop_bfd_create(struct nb_cb_create_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
static_next_hop_bfd_monitor_enable(sn, args->dnode);
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int route_next_hop_bfd_destroy(struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
static_next_hop_bfd_monitor_disable(sn);
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/source
|
||||
*/
|
||||
int route_next_hop_bfd_source_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
struct ipaddr source;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
yang_dnode_get_ip(&source, args->dnode, NULL);
|
||||
static_next_hop_bfd_source(sn, &source);
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int route_next_hop_bfd_source_destroy(struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
static_next_hop_bfd_auto_source(sn);
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/multi-hop
|
||||
*/
|
||||
int route_next_hop_bfd_multi_hop_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
static_next_hop_bfd_multi_hop(sn,
|
||||
yang_dnode_get_bool(args->dnode, NULL));
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/profile
|
||||
*/
|
||||
int route_next_hop_bfd_profile_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
static_next_hop_bfd_profile(sn,
|
||||
yang_dnode_get_string(args->dnode, NULL));
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int route_next_hop_bfd_profile_destroy(struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct static_nexthop *sn;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
sn = nb_running_get_entry(args->dnode, NULL, true);
|
||||
static_next_hop_bfd_profile(sn, NULL);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list
|
||||
|
@ -276,6 +276,8 @@ struct static_nexthop *static_add_nexthop(struct static_path *pn,
|
||||
/* Make new static route structure. */
|
||||
nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
|
||||
|
||||
/* Copy back pointers. */
|
||||
nh->rn = rn;
|
||||
nh->pn = pn;
|
||||
|
||||
nh->type = type;
|
||||
@ -393,6 +395,8 @@ void static_delete_nexthop(struct static_nexthop *nh)
|
||||
struct route_node *rn = pn->rn;
|
||||
|
||||
static_nexthop_list_del(&(pn->nexthop_list), nh);
|
||||
/* Remove BFD session/configuration if any. */
|
||||
bfd_sess_free(&nh->bsp);
|
||||
|
||||
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
||||
goto EXIT;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#ifndef __STATIC_ROUTES_H__
|
||||
#define __STATIC_ROUTES_H__
|
||||
|
||||
#include "lib/bfd.h"
|
||||
#include "lib/mpls.h"
|
||||
#include "table.h"
|
||||
#include "memory.h"
|
||||
@ -30,6 +31,8 @@ extern "C" {
|
||||
|
||||
DECLARE_MGROUP(STATIC);
|
||||
|
||||
#include "staticd/static_vrf.h"
|
||||
|
||||
/* Static route label information */
|
||||
struct static_nh_label {
|
||||
uint8_t num_labels;
|
||||
@ -148,6 +151,13 @@ struct static_nexthop {
|
||||
|
||||
/* SR-TE color */
|
||||
uint32_t color;
|
||||
|
||||
/** BFD integration data. */
|
||||
struct bfd_session_params *bsp;
|
||||
/** Back pointer for route node. */
|
||||
struct route_node *rn;
|
||||
/** Path connection status. */
|
||||
bool path_down;
|
||||
};
|
||||
|
||||
DECLARE_DLIST(static_nexthop_list, struct static_nexthop, list);
|
||||
@ -218,6 +228,22 @@ extern void zebra_stable_node_cleanup(struct route_table *table,
|
||||
extern void static_get_nh_str(struct static_nexthop *nh, char *nexthop,
|
||||
size_t size);
|
||||
|
||||
/*
|
||||
* BFD integration.
|
||||
*/
|
||||
extern void static_next_hop_bfd_source(struct static_nexthop *sn,
|
||||
const struct ipaddr *source);
|
||||
extern void static_next_hop_bfd_auto_source(struct static_nexthop *sn);
|
||||
extern void static_next_hop_bfd_monitor_enable(struct static_nexthop *sn,
|
||||
const struct lyd_node *dnode);
|
||||
extern void static_next_hop_bfd_monitor_disable(struct static_nexthop *sn);
|
||||
extern void static_next_hop_bfd_profile(struct static_nexthop *sn,
|
||||
const char *name);
|
||||
extern void static_next_hop_bfd_multi_hop(struct static_nexthop *sn, bool mhop);
|
||||
|
||||
/** Call this function after zebra client initialization. */
|
||||
extern void static_bfd_initialize(struct zclient *zc, struct thread_master *tm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -441,6 +441,9 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)
|
||||
api_nh = &api.nexthops[nh_num];
|
||||
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
||||
continue;
|
||||
/* Skip next hop which peer is down. */
|
||||
if (nh->path_down)
|
||||
continue;
|
||||
|
||||
api_nh->vrf_id = nh->nh_vrf_id;
|
||||
if (nh->onlink)
|
||||
@ -545,6 +548,7 @@ void static_zebra_init(void)
|
||||
zclient->zebra_connected = zebra_connected;
|
||||
|
||||
static_nht_hash_init(static_nht_hash);
|
||||
static_bfd_initialize(zclient, master);
|
||||
}
|
||||
|
||||
/* static_zebra_stop used by tests/lib/test_grpc.cpp */
|
||||
|
@ -10,6 +10,7 @@ man8 += $(MANBUILD)/frr-staticd.8
|
||||
endif
|
||||
|
||||
staticd_libstatic_a_SOURCES = \
|
||||
staticd/static_bfd.c \
|
||||
staticd/static_debug.c \
|
||||
staticd/static_nht.c \
|
||||
staticd/static_routes.c \
|
||||
@ -38,5 +39,6 @@ staticd_staticd_SOURCES = staticd/static_main.c
|
||||
staticd_staticd_LDADD = staticd/libstatic.a lib/libfrr.la $(LIBCAP)
|
||||
|
||||
nodist_staticd_staticd_SOURCES = \
|
||||
yang/frr-bfdd.yang.c \
|
||||
yang/frr-staticd.yang.c \
|
||||
# end
|
||||
|
Loading…
Reference in New Issue
Block a user