mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
staticd: fix NB dependency hack
Currently, staticd configuration is tightly coupled with VRF existence. Because of that, it has to use a hack in NB infrastructure to create a VRF configuration when at least one static route is configured for this VRF. This hack is incompatible with mgmtd, because mgmtd doesn't execute configuration callbacks. Because of that, the configuration may become out of sync between mgmtd and staticd. There are two main cases: 1. Create static route in a VRF. The VRF data node will be created automatically in staticd by the NB hack, but not in mgmtd. 2. Delete VRF which has some static routes configured. The static route configuration will be deleted from staticd by the NB hack, but not from mgmtd. To fix the problem, decouple configuration of static routes from VRF configuration. Now it is possible to configure static routes even if the VRF doesn't exist yet. Once the VRF is created, staticd applies all the preconfigured routes. This change also fixes the problem with static routes being preserved in the system when staticd "control-plane-protocol" container is deleted but the VRF is still configured. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
parent
5dfa36b6a7
commit
cb781f6097
|
@ -29,6 +29,8 @@ int routing_control_plane_protocols_control_plane_protocol_destroy(
|
||||||
* based on the control plane protocol
|
* based on the control plane protocol
|
||||||
*/
|
*/
|
||||||
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args));
|
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args));
|
||||||
|
DECLARE_HOOK(routing_create, (struct nb_cb_create_args *args), (args));
|
||||||
|
DECLARE_KOOH(routing_destroy, (struct nb_cb_destroy_args *args), (args));
|
||||||
|
|
||||||
void routing_control_plane_protocols_register_vrf_dependency(void);
|
void routing_control_plane_protocols_register_vrf_dependency(void);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
|
|
||||||
DEFINE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args));
|
DEFINE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args));
|
||||||
|
DEFINE_HOOK(routing_create, (struct nb_cb_create_args *args), (args));
|
||||||
|
DEFINE_KOOH(routing_destroy, (struct nb_cb_destroy_args *args), (args));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol
|
||||||
|
@ -49,6 +51,7 @@ int routing_control_plane_protocols_control_plane_protocol_create(
|
||||||
assert(vrf);
|
assert(vrf);
|
||||||
nb_running_set_entry(args->dnode, vrf);
|
nb_running_set_entry(args->dnode, vrf);
|
||||||
}
|
}
|
||||||
|
hook_call(routing_create, args);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +64,8 @@ int routing_control_plane_protocols_control_plane_protocol_destroy(
|
||||||
if (args->event != NB_EV_APPLY)
|
if (args->event != NB_EV_APPLY)
|
||||||
return NB_OK;
|
return NB_OK;
|
||||||
|
|
||||||
|
hook_call(routing_destroy, args);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If dependency on VRF module is registered, then VRF
|
* If dependency on VRF module is registered, then VRF
|
||||||
* pointer was stored and must be cleared.
|
* pointer was stored and must be cleared.
|
||||||
|
|
|
@ -263,14 +263,13 @@ static void static_bfd_show_path_json(struct vty *vty, struct json_object *jo,
|
||||||
static void static_bfd_show_json(struct vty *vty)
|
static void static_bfd_show_json(struct vty *vty)
|
||||||
{
|
{
|
||||||
struct json_object *jo, *jo_path, *jo_afi_safi;
|
struct json_object *jo, *jo_path, *jo_afi_safi;
|
||||||
struct vrf *vrf;
|
struct static_vrf *svrf;
|
||||||
|
|
||||||
jo = json_object_new_object();
|
jo = json_object_new_object();
|
||||||
jo_path = json_object_new_object();
|
jo_path = json_object_new_object();
|
||||||
|
|
||||||
json_object_object_add(jo, "path-list", jo_path);
|
json_object_object_add(jo, "path-list", jo_path);
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
RB_FOREACH (svrf, svrf_name_head, &svrfs) {
|
||||||
const struct static_vrf *svrf = vrf->info;
|
|
||||||
struct route_table *rt;
|
struct route_table *rt;
|
||||||
|
|
||||||
jo_afi_safi = json_object_new_array();
|
jo_afi_safi = json_object_new_array();
|
||||||
|
@ -346,7 +345,7 @@ static void static_bfd_show_path(struct vty *vty, struct route_table *rt)
|
||||||
|
|
||||||
void static_bfd_show(struct vty *vty, bool json)
|
void static_bfd_show(struct vty *vty, bool json)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct static_vrf *svrf;
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
static_bfd_show_json(vty);
|
static_bfd_show_json(vty);
|
||||||
|
@ -355,21 +354,20 @@ void static_bfd_show(struct vty *vty, bool json)
|
||||||
|
|
||||||
vty_out(vty, "Showing BFD monitored static routes:\n");
|
vty_out(vty, "Showing BFD monitored static routes:\n");
|
||||||
vty_out(vty, "\n Next hops:\n");
|
vty_out(vty, "\n Next hops:\n");
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
RB_FOREACH (svrf, svrf_name_head, &svrfs) {
|
||||||
const struct static_vrf *svrf = vrf->info;
|
|
||||||
struct route_table *rt;
|
struct route_table *rt;
|
||||||
|
|
||||||
vty_out(vty, " VRF %s IPv4 Unicast:\n", vrf->name);
|
vty_out(vty, " VRF %s IPv4 Unicast:\n", svrf->name);
|
||||||
rt = svrf->stable[AFI_IP][SAFI_UNICAST];
|
rt = svrf->stable[AFI_IP][SAFI_UNICAST];
|
||||||
if (rt)
|
if (rt)
|
||||||
static_bfd_show_path(vty, rt);
|
static_bfd_show_path(vty, rt);
|
||||||
|
|
||||||
vty_out(vty, "\n VRF %s IPv4 Multicast:\n", vrf->name);
|
vty_out(vty, "\n VRF %s IPv4 Multicast:\n", svrf->name);
|
||||||
rt = svrf->stable[AFI_IP][SAFI_MULTICAST];
|
rt = svrf->stable[AFI_IP][SAFI_MULTICAST];
|
||||||
if (rt)
|
if (rt)
|
||||||
static_bfd_show_path(vty, rt);
|
static_bfd_show_path(vty, rt);
|
||||||
|
|
||||||
vty_out(vty, "\n VRF %s IPv6 Unicast:\n", vrf->name);
|
vty_out(vty, "\n VRF %s IPv6 Unicast:\n", svrf->name);
|
||||||
rt = svrf->stable[AFI_IP6][SAFI_UNICAST];
|
rt = svrf->stable[AFI_IP6][SAFI_UNICAST];
|
||||||
if (rt)
|
if (rt)
|
||||||
static_bfd_show_path(vty, rt);
|
static_bfd_show_path(vty, rt);
|
||||||
|
|
|
@ -168,8 +168,10 @@ int main(int argc, char **argv, char **envp)
|
||||||
|
|
||||||
hook_register(routing_conf_event,
|
hook_register(routing_conf_event,
|
||||||
routing_control_plane_protocols_name_validate);
|
routing_control_plane_protocols_name_validate);
|
||||||
|
hook_register(routing_create,
|
||||||
routing_control_plane_protocols_register_vrf_dependency();
|
routing_control_plane_protocols_staticd_create);
|
||||||
|
hook_register(routing_destroy,
|
||||||
|
routing_control_plane_protocols_staticd_destroy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We set FRR_NO_SPLIT_CONFIG flag to avoid reading our config, but we
|
* We set FRR_NO_SPLIT_CONFIG flag to avoid reading our config, but we
|
||||||
|
|
|
@ -13,6 +13,11 @@ extern "C" {
|
||||||
extern const struct frr_yang_module_info frr_staticd_info;
|
extern const struct frr_yang_module_info frr_staticd_info;
|
||||||
extern const struct frr_yang_module_info frr_staticd_cli_info;
|
extern const struct frr_yang_module_info frr_staticd_cli_info;
|
||||||
|
|
||||||
|
int routing_control_plane_protocols_staticd_create(
|
||||||
|
struct nb_cb_create_args *args);
|
||||||
|
int routing_control_plane_protocols_staticd_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
|
||||||
/* Mandatory callbacks. */
|
/* Mandatory callbacks. */
|
||||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
|
||||||
struct nb_cb_create_args *args);
|
struct nb_cb_create_args *args);
|
||||||
|
|
|
@ -540,6 +540,48 @@ int routing_control_plane_protocols_name_validate(
|
||||||
}
|
}
|
||||||
return NB_OK;
|
return NB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath:
|
||||||
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_staticd_create(struct nb_cb_create_args *args)
|
||||||
|
{
|
||||||
|
struct static_vrf *svrf;
|
||||||
|
const char *vrf;
|
||||||
|
|
||||||
|
vrf = yang_dnode_get_string(args->dnode, "vrf");
|
||||||
|
svrf = static_vrf_alloc(vrf);
|
||||||
|
nb_running_set_entry(args->dnode, svrf);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int routing_control_plane_protocols_staticd_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
struct static_vrf *svrf;
|
||||||
|
struct route_table *stable;
|
||||||
|
struct route_node *rn;
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
|
||||||
|
svrf = nb_running_unset_entry(args->dnode);
|
||||||
|
|
||||||
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
|
stable = svrf->stable[afi][safi];
|
||||||
|
if (!stable)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rn = route_top(stable); rn; rn = route_next(rn))
|
||||||
|
static_del_route(rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_vrf_free(svrf);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPath:
|
* XPath:
|
||||||
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list
|
||||||
|
@ -547,8 +589,7 @@ int routing_control_plane_protocols_name_validate(
|
||||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
|
||||||
struct nb_cb_create_args *args)
|
struct nb_cb_create_args *args)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct static_vrf *svrf;
|
||||||
struct static_vrf *s_vrf;
|
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
const struct lyd_node *vrf_dnode;
|
const struct lyd_node *vrf_dnode;
|
||||||
struct prefix prefix;
|
struct prefix prefix;
|
||||||
|
@ -577,15 +618,14 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_cr
|
||||||
case NB_EV_APPLY:
|
case NB_EV_APPLY:
|
||||||
vrf_dnode = yang_dnode_get_parent(args->dnode,
|
vrf_dnode = yang_dnode_get_parent(args->dnode,
|
||||||
"control-plane-protocol");
|
"control-plane-protocol");
|
||||||
vrf = nb_running_get_entry(vrf_dnode, NULL, true);
|
svrf = nb_running_get_entry(vrf_dnode, NULL, true);
|
||||||
s_vrf = vrf->info;
|
|
||||||
|
|
||||||
yang_dnode_get_prefix(&prefix, args->dnode, "prefix");
|
yang_dnode_get_prefix(&prefix, args->dnode, "prefix");
|
||||||
afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
|
afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
|
||||||
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
|
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
|
||||||
|
|
||||||
rn = static_add_route(afi, safi, &prefix, NULL, s_vrf);
|
rn = static_add_route(afi, safi, &prefix, NULL, svrf);
|
||||||
if (vrf->vrf_id == VRF_UNKNOWN)
|
if (!svrf->vrf || svrf->vrf->vrf_id == VRF_UNKNOWN)
|
||||||
snprintf(
|
snprintf(
|
||||||
args->errmsg, args->errmsg_len,
|
args->errmsg, args->errmsg_len,
|
||||||
"Static Route to %s not installed currently because dependent config not fully available",
|
"Static Route to %s not installed currently because dependent config not fully available",
|
||||||
|
|
|
@ -245,21 +245,20 @@ void static_del_path(struct static_path *pn)
|
||||||
XFREE(MTYPE_STATIC_PATH, pn);
|
XFREE(MTYPE_STATIC_PATH, pn);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct static_nexthop *static_add_nexthop(struct static_path *pn,
|
struct static_nexthop *
|
||||||
enum static_nh_type type,
|
static_add_nexthop(struct static_path *pn, enum static_nh_type type,
|
||||||
struct ipaddr *ipaddr,
|
struct ipaddr *ipaddr, const char *ifname,
|
||||||
const char *ifname,
|
const char *nh_vrfname, uint32_t color)
|
||||||
const char *nh_vrf, uint32_t color)
|
|
||||||
{
|
{
|
||||||
struct route_node *rn = pn->rn;
|
struct route_node *rn = pn->rn;
|
||||||
struct static_nexthop *nh;
|
struct static_nexthop *nh;
|
||||||
struct static_vrf *nh_svrf;
|
struct vrf *nh_vrf;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct static_nexthop *cp;
|
struct static_nexthop *cp;
|
||||||
|
|
||||||
route_lock_node(rn);
|
route_lock_node(rn);
|
||||||
|
|
||||||
nh_svrf = static_vrf_lookup_by_name(nh_vrf);
|
nh_vrf = vrf_lookup_by_name(nh_vrfname);
|
||||||
|
|
||||||
/* Make new static route structure. */
|
/* Make new static route structure. */
|
||||||
nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
|
nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
|
||||||
|
@ -274,8 +273,8 @@ struct static_nexthop *static_add_nexthop(struct static_path *pn,
|
||||||
if (nh->type == STATIC_BLACKHOLE)
|
if (nh->type == STATIC_BLACKHOLE)
|
||||||
nh->bh_type = STATIC_BLACKHOLE_NULL;
|
nh->bh_type = STATIC_BLACKHOLE_NULL;
|
||||||
|
|
||||||
nh->nh_vrf_id = nh_svrf ? nh_svrf->vrf->vrf_id : VRF_UNKNOWN;
|
nh->nh_vrf_id = nh_vrf ? nh_vrf->vrf_id : VRF_UNKNOWN;
|
||||||
strlcpy(nh->nh_vrfname, nh_vrf, sizeof(nh->nh_vrfname));
|
strlcpy(nh->nh_vrfname, nh_vrfname, sizeof(nh->nh_vrfname));
|
||||||
|
|
||||||
if (ifname)
|
if (ifname)
|
||||||
strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
|
strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
|
||||||
|
@ -437,14 +436,10 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct static_nexthop *nh;
|
struct static_nexthop *nh;
|
||||||
struct static_path *pn;
|
struct static_path *pn;
|
||||||
struct vrf *vrf;
|
struct static_vrf *svrf;
|
||||||
struct static_route_info *si;
|
struct static_route_info *si;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
RB_FOREACH (svrf, svrf_name_head, &svrfs) {
|
||||||
struct static_vrf *svrf;
|
|
||||||
|
|
||||||
svrf = vrf->info;
|
|
||||||
|
|
||||||
stable = static_vrf_static_table(afi, safi, svrf);
|
stable = static_vrf_static_table(afi, safi, svrf);
|
||||||
if (!stable)
|
if (!stable)
|
||||||
continue;
|
continue;
|
||||||
|
@ -476,8 +471,8 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
|
||||||
* afi -> The afi to look at
|
* afi -> The afi to look at
|
||||||
* safi -> the safi to look at
|
* safi -> the safi to look at
|
||||||
*/
|
*/
|
||||||
static void static_fixup_vrf(struct static_vrf *svrf,
|
static void static_fixup_vrf(struct vrf *vrf, struct route_table *stable,
|
||||||
struct route_table *stable, afi_t afi, safi_t safi)
|
afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct static_nexthop *nh;
|
struct static_nexthop *nh;
|
||||||
|
@ -491,13 +486,12 @@ static void static_fixup_vrf(struct static_vrf *svrf,
|
||||||
continue;
|
continue;
|
||||||
frr_each(static_path_list, &si->path_list, pn) {
|
frr_each(static_path_list, &si->path_list, pn) {
|
||||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||||
if (strcmp(svrf->vrf->name, nh->nh_vrfname)
|
if (strcmp(vrf->name, nh->nh_vrfname) != 0)
|
||||||
!= 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nh->nh_vrf_id = svrf->vrf->vrf_id;
|
nh->nh_vrf_id = vrf->vrf_id;
|
||||||
nh->nh_registered = false;
|
nh->nh_registered = false;
|
||||||
if (nh->ifindex) {
|
if (nh->ifname[0]) {
|
||||||
ifp = if_lookup_by_name(nh->ifname,
|
ifp = if_lookup_by_name(nh->ifname,
|
||||||
nh->nh_vrf_id);
|
nh->nh_vrf_id);
|
||||||
if (ifp)
|
if (ifp)
|
||||||
|
@ -521,9 +515,7 @@ static void static_fixup_vrf(struct static_vrf *svrf,
|
||||||
* afi -> the afi in question
|
* afi -> the afi in question
|
||||||
* safi -> the safi in question
|
* safi -> the safi in question
|
||||||
*/
|
*/
|
||||||
static void static_enable_vrf(struct static_vrf *svrf,
|
static void static_enable_vrf(struct route_table *stable, afi_t afi, safi_t safi)
|
||||||
struct route_table *stable, afi_t afi,
|
|
||||||
safi_t safi)
|
|
||||||
{
|
{
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct static_nexthop *nh;
|
struct static_nexthop *nh;
|
||||||
|
@ -537,7 +529,9 @@ static void static_enable_vrf(struct static_vrf *svrf,
|
||||||
continue;
|
continue;
|
||||||
frr_each(static_path_list, &si->path_list, pn) {
|
frr_each(static_path_list, &si->path_list, pn) {
|
||||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||||
if (nh->ifindex) {
|
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
if (nh->ifname[0]) {
|
||||||
ifp = if_lookup_by_name(nh->ifname,
|
ifp = if_lookup_by_name(nh->ifname,
|
||||||
nh->nh_vrf_id);
|
nh->nh_vrf_id);
|
||||||
if (ifp)
|
if (ifp)
|
||||||
|
@ -545,8 +539,7 @@ static void static_enable_vrf(struct static_vrf *svrf,
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
|
||||||
continue;
|
|
||||||
static_install_path(pn);
|
static_install_path(pn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,27 +553,26 @@ static void static_enable_vrf(struct static_vrf *svrf,
|
||||||
*
|
*
|
||||||
* enable_svrf -> the vrf being enabled
|
* enable_svrf -> the vrf being enabled
|
||||||
*/
|
*/
|
||||||
void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
|
void static_fixup_vrf_ids(struct vrf *vrf)
|
||||||
{
|
{
|
||||||
struct route_table *stable;
|
struct route_table *stable;
|
||||||
struct vrf *vrf;
|
struct static_vrf *svrf, *enable_svrf;
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
safi_t safi;
|
safi_t safi;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
enable_svrf = vrf->info;
|
||||||
struct static_vrf *svrf;
|
|
||||||
|
|
||||||
svrf = vrf->info;
|
RB_FOREACH (svrf, svrf_name_head, &svrfs) {
|
||||||
/* Install any static routes configured for this VRF. */
|
/* Install any static routes configured for this VRF. */
|
||||||
FOREACH_AFI_SAFI (afi, safi) {
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
stable = svrf->stable[afi][safi];
|
stable = svrf->stable[afi][safi];
|
||||||
if (!stable)
|
if (!stable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
static_fixup_vrf(enable_svrf, stable, afi, safi);
|
static_fixup_vrf(vrf, stable, afi, safi);
|
||||||
|
|
||||||
if (enable_svrf == svrf)
|
if (enable_svrf == svrf)
|
||||||
static_enable_vrf(svrf, stable, afi, safi);
|
static_enable_vrf(stable, afi, safi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -595,8 +587,7 @@ void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
|
||||||
* afi -> the afi in question
|
* afi -> the afi in question
|
||||||
* safi -> the safi in question
|
* safi -> the safi in question
|
||||||
*/
|
*/
|
||||||
static void static_cleanup_vrf(struct static_vrf *svrf,
|
static void static_cleanup_vrf(struct vrf *vrf, struct route_table *stable,
|
||||||
struct route_table *stable,
|
|
||||||
afi_t afi, safi_t safi)
|
afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
|
@ -610,11 +601,13 @@ static void static_cleanup_vrf(struct static_vrf *svrf,
|
||||||
continue;
|
continue;
|
||||||
frr_each(static_path_list, &si->path_list, pn) {
|
frr_each(static_path_list, &si->path_list, pn) {
|
||||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||||
if (strcmp(svrf->vrf->name, nh->nh_vrfname)
|
if (strcmp(vrf->name, nh->nh_vrfname) != 0)
|
||||||
!= 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
static_uninstall_path(pn);
|
static_uninstall_path(pn);
|
||||||
|
|
||||||
|
nh->nh_vrf_id = VRF_UNKNOWN;
|
||||||
|
nh->ifindex = IFINDEX_INTERNAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -642,6 +635,9 @@ static void static_disable_vrf(struct route_table *stable,
|
||||||
continue;
|
continue;
|
||||||
frr_each(static_path_list, &si->path_list, pn) {
|
frr_each(static_path_list, &si->path_list, pn) {
|
||||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||||
|
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
|
||||||
static_uninstall_path(pn);
|
static_uninstall_path(pn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,26 +652,23 @@ static void static_disable_vrf(struct route_table *stable,
|
||||||
*
|
*
|
||||||
* disable_svrf - The vrf being disabled
|
* disable_svrf - The vrf being disabled
|
||||||
*/
|
*/
|
||||||
void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
|
void static_cleanup_vrf_ids(struct vrf *vrf)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct route_table *stable;
|
||||||
|
struct static_vrf *svrf, *disable_svrf;
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
safi_t safi;
|
safi_t safi;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
disable_svrf = vrf->info;
|
||||||
struct static_vrf *svrf;
|
|
||||||
|
|
||||||
svrf = vrf->info;
|
|
||||||
|
|
||||||
|
RB_FOREACH (svrf, svrf_name_head, &svrfs) {
|
||||||
/* Uninstall any static routes configured for this VRF. */
|
/* Uninstall any static routes configured for this VRF. */
|
||||||
FOREACH_AFI_SAFI (afi, safi) {
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
struct route_table *stable;
|
|
||||||
|
|
||||||
stable = svrf->stable[afi][safi];
|
stable = svrf->stable[afi][safi];
|
||||||
if (!stable)
|
if (!stable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
static_cleanup_vrf(disable_svrf, stable, afi, safi);
|
static_cleanup_vrf(vrf, stable, afi, safi);
|
||||||
|
|
||||||
if (disable_svrf == svrf)
|
if (disable_svrf == svrf)
|
||||||
static_disable_vrf(stable, afi, safi);
|
static_disable_vrf(stable, afi, safi);
|
||||||
|
@ -683,71 +676,6 @@ void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This function enables static routes when an interface it relies
|
|
||||||
* on in a different vrf is coming up.
|
|
||||||
*
|
|
||||||
* stable -> The stable we are looking at.
|
|
||||||
* ifp -> interface coming up
|
|
||||||
* afi -> the afi in question
|
|
||||||
* safi -> the safi in question
|
|
||||||
*/
|
|
||||||
static void static_fixup_intf_nh(struct route_table *stable,
|
|
||||||
struct interface *ifp,
|
|
||||||
afi_t afi, safi_t safi)
|
|
||||||
{
|
|
||||||
struct route_node *rn;
|
|
||||||
struct static_nexthop *nh;
|
|
||||||
struct static_path *pn;
|
|
||||||
struct static_route_info *si;
|
|
||||||
|
|
||||||
for (rn = route_top(stable); rn; rn = route_next(rn)) {
|
|
||||||
si = static_route_info_from_rnode(rn);
|
|
||||||
if (!si)
|
|
||||||
continue;
|
|
||||||
frr_each(static_path_list, &si->path_list, pn) {
|
|
||||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
|
||||||
if (nh->nh_vrf_id != ifp->vrf->vrf_id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (nh->ifindex != ifp->ifindex)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
static_install_path(pn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function enables static routes that rely on an interface in
|
|
||||||
* a different vrf when that interface comes up.
|
|
||||||
*/
|
|
||||||
void static_install_intf_nh(struct interface *ifp)
|
|
||||||
{
|
|
||||||
struct route_table *stable;
|
|
||||||
struct vrf *vrf;
|
|
||||||
afi_t afi;
|
|
||||||
safi_t safi;
|
|
||||||
|
|
||||||
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
|
|
||||||
struct static_vrf *svrf = vrf->info;
|
|
||||||
|
|
||||||
/* Not needed if same vrf since happens naturally */
|
|
||||||
if (vrf->vrf_id == ifp->vrf->vrf_id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Install any static routes configured for this interface. */
|
|
||||||
FOREACH_AFI_SAFI (afi, safi) {
|
|
||||||
stable = svrf->stable[afi][safi];
|
|
||||||
if (!stable)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
static_fixup_intf_nh(stable, ifp, afi, safi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
|
/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
|
||||||
void static_ifindex_update(struct interface *ifp, bool up)
|
void static_ifindex_update(struct interface *ifp, bool up)
|
||||||
{
|
{
|
||||||
|
|
|
@ -199,7 +199,8 @@ extern uint32_t zebra_ecmp_count;
|
||||||
|
|
||||||
extern struct zebra_privs_t static_privs;
|
extern struct zebra_privs_t static_privs;
|
||||||
|
|
||||||
void static_fixup_vrf_ids(struct static_vrf *svrf);
|
extern void static_fixup_vrf_ids(struct vrf *vrf);
|
||||||
|
extern void static_cleanup_vrf_ids(struct vrf *vrf);
|
||||||
|
|
||||||
extern struct static_nexthop *
|
extern struct static_nexthop *
|
||||||
static_add_nexthop(struct static_path *pn, enum static_nh_type type,
|
static_add_nexthop(struct static_path *pn, enum static_nh_type type,
|
||||||
|
@ -209,10 +210,6 @@ extern void static_install_nexthop(struct static_nexthop *nh);
|
||||||
|
|
||||||
extern void static_delete_nexthop(struct static_nexthop *nh);
|
extern void static_delete_nexthop(struct static_nexthop *nh);
|
||||||
|
|
||||||
extern void static_cleanup_vrf_ids(struct static_vrf *disable_svrf);
|
|
||||||
|
|
||||||
extern void static_install_intf_nh(struct interface *ifp);
|
|
||||||
|
|
||||||
extern void static_ifindex_update(struct interface *ifp, bool up);
|
extern void static_ifindex_update(struct interface *ifp, bool up);
|
||||||
|
|
||||||
extern void static_install_path(struct static_path *pn);
|
extern void static_install_path(struct static_path *pn);
|
||||||
|
|
|
@ -18,16 +18,37 @@
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info");
|
DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info");
|
||||||
|
|
||||||
static struct static_vrf *static_vrf_alloc(void)
|
static int svrf_name_compare(const struct static_vrf *a,
|
||||||
|
const struct static_vrf *b)
|
||||||
|
{
|
||||||
|
return strcmp(a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_GENERATE(svrf_name_head, static_vrf, entry, svrf_name_compare);
|
||||||
|
|
||||||
|
struct svrf_name_head svrfs = RB_INITIALIZER(&svrfs);
|
||||||
|
|
||||||
|
static struct static_vrf *static_vrf_lookup_by_name(const char *name)
|
||||||
|
{
|
||||||
|
struct static_vrf svrf;
|
||||||
|
|
||||||
|
strlcpy(svrf.name, name, sizeof(svrf.name));
|
||||||
|
return RB_FIND(svrf_name_head, &svrfs, &svrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct static_vrf *static_vrf_alloc(const char *name)
|
||||||
{
|
{
|
||||||
struct route_table *table;
|
struct route_table *table;
|
||||||
struct static_vrf *svrf;
|
struct static_vrf *svrf;
|
||||||
struct stable_info *info;
|
struct stable_info *info;
|
||||||
|
struct vrf *vrf;
|
||||||
safi_t safi;
|
safi_t safi;
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
|
|
||||||
svrf = XCALLOC(MTYPE_STATIC_RTABLE_INFO, sizeof(struct static_vrf));
|
svrf = XCALLOC(MTYPE_STATIC_RTABLE_INFO, sizeof(struct static_vrf));
|
||||||
|
|
||||||
|
strlcpy(svrf->name, name, sizeof(svrf->name));
|
||||||
|
|
||||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||||
if (afi == AFI_IP6)
|
if (afi == AFI_IP6)
|
||||||
|
@ -46,44 +67,34 @@ static struct static_vrf *static_vrf_alloc(void)
|
||||||
svrf->stable[afi][safi] = table;
|
svrf->stable[afi][safi] = table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RB_INSERT(svrf_name_head, &svrfs, svrf);
|
||||||
|
|
||||||
|
vrf = vrf_lookup_by_name(name);
|
||||||
|
if (vrf) {
|
||||||
|
svrf->vrf = vrf;
|
||||||
|
vrf->info = svrf;
|
||||||
|
}
|
||||||
|
|
||||||
return svrf;
|
return svrf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int static_vrf_new(struct vrf *vrf)
|
void static_vrf_free(struct static_vrf *svrf)
|
||||||
{
|
|
||||||
struct static_vrf *svrf;
|
|
||||||
|
|
||||||
svrf = static_vrf_alloc();
|
|
||||||
vrf->info = svrf;
|
|
||||||
svrf->vrf = vrf;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int static_vrf_enable(struct vrf *vrf)
|
|
||||||
{
|
|
||||||
static_zebra_vrf_register(vrf);
|
|
||||||
|
|
||||||
static_fixup_vrf_ids(vrf->info);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int static_vrf_disable(struct vrf *vrf)
|
|
||||||
{
|
|
||||||
static_zebra_vrf_unregister(vrf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int static_vrf_delete(struct vrf *vrf)
|
|
||||||
{
|
{
|
||||||
struct route_table *table;
|
struct route_table *table;
|
||||||
struct static_vrf *svrf;
|
struct vrf *vrf;
|
||||||
safi_t safi;
|
safi_t safi;
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
void *info;
|
void *info;
|
||||||
|
|
||||||
svrf = vrf->info;
|
vrf = svrf->vrf;
|
||||||
|
if (vrf) {
|
||||||
|
vrf->info = NULL;
|
||||||
|
svrf->vrf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_REMOVE(svrf_name_head, &svrfs, svrf);
|
||||||
|
|
||||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||||
table = svrf->stable[afi][safi];
|
table = svrf->stable[afi][safi];
|
||||||
|
@ -93,7 +104,47 @@ static int static_vrf_delete(struct vrf *vrf)
|
||||||
svrf->stable[afi][safi] = NULL;
|
svrf->stable[afi][safi] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XFREE(MTYPE_STATIC_RTABLE_INFO, svrf);
|
XFREE(MTYPE_STATIC_RTABLE_INFO, svrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int static_vrf_new(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
struct static_vrf *svrf;
|
||||||
|
|
||||||
|
svrf = static_vrf_lookup_by_name(vrf->name);
|
||||||
|
if (svrf) {
|
||||||
|
vrf->info = svrf;
|
||||||
|
svrf->vrf = vrf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int static_vrf_enable(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
static_zebra_vrf_register(vrf);
|
||||||
|
static_fixup_vrf_ids(vrf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int static_vrf_disable(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
static_cleanup_vrf_ids(vrf);
|
||||||
|
static_zebra_vrf_unregister(vrf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int static_vrf_delete(struct vrf *vrf)
|
||||||
|
{
|
||||||
|
struct static_vrf *svrf;
|
||||||
|
|
||||||
|
svrf = vrf->info;
|
||||||
|
if (svrf) {
|
||||||
|
svrf->vrf = NULL;
|
||||||
|
vrf->info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,20 +161,6 @@ struct route_table *static_vrf_static_table(afi_t afi, safi_t safi,
|
||||||
return svrf->stable[afi][safi];
|
return svrf->stable[afi][safi];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct static_vrf *static_vrf_lookup_by_name(const char *name)
|
|
||||||
{
|
|
||||||
struct vrf *vrf;
|
|
||||||
|
|
||||||
if (!name)
|
|
||||||
name = VRF_DEFAULT_NAME;
|
|
||||||
|
|
||||||
vrf = vrf_lookup_by_name(name);
|
|
||||||
if (vrf)
|
|
||||||
return ((struct static_vrf *)vrf->info);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void static_vrf_init(void)
|
void static_vrf_init(void)
|
||||||
{
|
{
|
||||||
vrf_init(static_vrf_new, static_vrf_enable, static_vrf_disable,
|
vrf_init(static_vrf_new, static_vrf_enable, static_vrf_disable,
|
||||||
|
@ -134,5 +171,10 @@ void static_vrf_init(void)
|
||||||
|
|
||||||
void static_vrf_terminate(void)
|
void static_vrf_terminate(void)
|
||||||
{
|
{
|
||||||
|
struct static_vrf *svrf, *svrf_next;
|
||||||
|
|
||||||
|
RB_FOREACH_SAFE (svrf, svrf_name_head, &svrfs, svrf_next)
|
||||||
|
static_vrf_free(svrf);
|
||||||
|
|
||||||
vrf_terminate();
|
vrf_terminate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,27 @@
|
||||||
#ifndef __STATIC_VRF_H__
|
#ifndef __STATIC_VRF_H__
|
||||||
#define __STATIC_VRF_H__
|
#define __STATIC_VRF_H__
|
||||||
|
|
||||||
|
#include "openbsd-tree.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct static_vrf {
|
struct static_vrf {
|
||||||
|
RB_ENTRY(static_vrf) entry;
|
||||||
|
|
||||||
|
char name[VRF_NAMSIZ + 1];
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
|
|
||||||
struct route_table *stable[AFI_MAX][SAFI_MAX];
|
struct route_table *stable[AFI_MAX][SAFI_MAX];
|
||||||
};
|
};
|
||||||
|
RB_HEAD(svrf_name_head, static_vrf);
|
||||||
|
RB_PROTOTYPE(svrf_name_head, static_vrf, entry, svrf_name_compare)
|
||||||
|
|
||||||
|
extern struct svrf_name_head svrfs;
|
||||||
|
|
||||||
|
struct static_vrf *static_vrf_alloc(const char *name);
|
||||||
|
void static_vrf_free(struct static_vrf *svrf);
|
||||||
|
|
||||||
struct stable_info {
|
struct stable_info {
|
||||||
struct static_vrf *svrf;
|
struct static_vrf *svrf;
|
||||||
|
@ -25,8 +37,6 @@ struct stable_info {
|
||||||
|
|
||||||
#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id
|
#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id
|
||||||
|
|
||||||
struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name);
|
|
||||||
|
|
||||||
void static_vrf_init(void);
|
void static_vrf_init(void);
|
||||||
|
|
||||||
struct route_table *static_vrf_static_table(afi_t afi, safi_t safi,
|
struct route_table *static_vrf_static_table(afi_t afi, safi_t safi,
|
||||||
|
|
|
@ -111,8 +111,6 @@ static int interface_address_delete(ZAPI_CALLBACK_ARGS)
|
||||||
|
|
||||||
static int static_ifp_up(struct interface *ifp)
|
static int static_ifp_up(struct interface *ifp)
|
||||||
{
|
{
|
||||||
/* Install any static reliant on this interface coming up */
|
|
||||||
static_install_intf_nh(ifp);
|
|
||||||
static_ifindex_update(ifp, true);
|
static_ifindex_update(ifp, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -169,7 +167,7 @@ static void zebra_connected(struct zclient *zclient)
|
||||||
zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST, zclient, true);
|
zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST, zclient, true);
|
||||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||||
|
|
||||||
static_fixup_vrf_ids(vrf_info_lookup(VRF_DEFAULT));
|
static_fixup_vrf_ids(vrf_lookup_by_id(VRF_DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* API to check whether the configured nexthop address is
|
/* API to check whether the configured nexthop address is
|
||||||
|
@ -388,6 +386,9 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)
|
||||||
struct zapi_route api;
|
struct zapi_route api;
|
||||||
uint32_t nh_num = 0;
|
uint32_t nh_num = 0;
|
||||||
|
|
||||||
|
if (!si->svrf->vrf)
|
||||||
|
return;
|
||||||
|
|
||||||
p = src_pp = NULL;
|
p = src_pp = NULL;
|
||||||
srcdest_rnode_prefixes(rn, &p, &src_pp);
|
srcdest_rnode_prefixes(rn, &p, &src_pp);
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,10 @@ static void static_startup(void)
|
||||||
|
|
||||||
hook_register(routing_conf_event,
|
hook_register(routing_conf_event,
|
||||||
routing_control_plane_protocols_name_validate);
|
routing_control_plane_protocols_name_validate);
|
||||||
|
hook_register(routing_create,
|
||||||
routing_control_plane_protocols_register_vrf_dependency();
|
routing_control_plane_protocols_staticd_create);
|
||||||
|
hook_register(routing_destroy,
|
||||||
|
routing_control_plane_protocols_staticd_destroy);
|
||||||
|
|
||||||
// Add a route
|
// Add a route
|
||||||
vty = vty_new();
|
vty = vty_new();
|
||||||
|
|
Loading…
Reference in a new issue