mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 22:30:43 +00:00
Merge pull request #6296 from vishaldhingra/static
staticd: static route NB configuration code
This commit is contained in:
commit
d58258e909
40
lib/routing_nb.c
Normal file
40
lib/routing_nb.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Vmware
|
||||
* Vishal Dhingra
|
||||
*
|
||||
* 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; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "northbound.h"
|
||||
#include "libfrr.h"
|
||||
#include "routing_nb.h"
|
||||
|
||||
|
||||
|
||||
/* clang-format off */
|
||||
const struct frr_yang_module_info frr_routing_info = {
|
||||
.name = "frr-routing",
|
||||
.nodes = {
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = NULL,
|
||||
},
|
||||
}
|
||||
};
|
24
lib/routing_nb.h
Normal file
24
lib/routing_nb.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef _FRR_ROUTING_NB_H_
|
||||
#define _FRR_ROUTING_NB_H_
|
||||
|
||||
extern const struct frr_yang_module_info frr_routing_info;
|
||||
|
||||
/* Mandatory callbacks. */
|
||||
int routing_control_plane_protocols_control_plane_protocol_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
|
||||
#define FRR_ROUTING_XPATH \
|
||||
"/frr-routing:routing/control-plane-protocols/control-plane-protocol"
|
||||
|
||||
#define FRR_ROUTING_KEY_XPATH \
|
||||
"/frr-routing:routing/control-plane-protocols/" \
|
||||
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']"
|
||||
/*
|
||||
* callbacks for routing to handle configuration events
|
||||
* based on the control plane protocol
|
||||
*/
|
||||
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args))
|
||||
|
||||
#endif /* _FRR_ROUTING_NB_H_ */
|
74
lib/routing_nb_config.c
Normal file
74
lib/routing_nb_config.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Vmware
|
||||
* Vishal Dhingra
|
||||
*
|
||||
* 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; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "northbound.h"
|
||||
#include "libfrr.h"
|
||||
#include "vrf.h"
|
||||
#include "lib_errors.h"
|
||||
#include "routing_nb.h"
|
||||
|
||||
|
||||
DEFINE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args))
|
||||
|
||||
/*
|
||||
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol
|
||||
*/
|
||||
|
||||
int routing_control_plane_protocols_control_plane_protocol_create(
|
||||
struct nb_cb_create_args *args)
|
||||
{
|
||||
struct vrf *vrf;
|
||||
const char *vrfname;
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (hook_call(routing_conf_event, args))
|
||||
return NB_ERR_VALIDATION;
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
vrfname = yang_dnode_get_string(args->dnode, "./vrf");
|
||||
vrf = vrf_lookup_by_name(vrfname);
|
||||
vrf = vrf ? vrf : vrf_get(VRF_UNKNOWN, vrfname);
|
||||
if (!vrf) {
|
||||
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
||||
"vrf creation %s failed", vrfname);
|
||||
return NB_ERR;
|
||||
}
|
||||
nb_running_set_entry(args->dnode, vrf);
|
||||
break;
|
||||
};
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int routing_control_plane_protocols_control_plane_protocol_destroy(
|
||||
struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct vrf *vrf __attribute__((unused));
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
vrf = nb_running_unset_entry(args->dnode);
|
||||
|
||||
return NB_OK;
|
||||
}
|
@ -317,3 +317,13 @@ static ssize_t printfrr_rn(char *buf, size_t bsz, const char *fmt,
|
||||
srcdest2str(dst_p, (const struct prefix_ipv6 *)src_p, buf, bsz);
|
||||
return 2;
|
||||
}
|
||||
|
||||
struct route_table *srcdest_srcnode_table(struct route_node *rn)
|
||||
{
|
||||
if (rnode_is_dstnode(rn)) {
|
||||
struct srcdest_rnode *srn = srcdest_rnode_from_rnode(rn);
|
||||
|
||||
return srn->src_table;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -100,6 +100,8 @@ static inline void *srcdest_rnode_table_info(struct route_node *rn)
|
||||
return route_table_get_info(srcdest_rnode_table(rn));
|
||||
}
|
||||
|
||||
extern struct route_table *srcdest_srcnode_table(struct route_node *rn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -108,6 +108,8 @@ lib_libfrr_la_SOURCES = \
|
||||
lib/printf/printf-pos.c \
|
||||
lib/printf/vfprintf.c \
|
||||
lib/printf/glue.c \
|
||||
lib/routing_nb.c \
|
||||
lib/routing_nb_config.c \
|
||||
# end
|
||||
|
||||
nodist_lib_libfrr_la_SOURCES = \
|
||||
@ -117,6 +119,7 @@ nodist_lib_libfrr_la_SOURCES = \
|
||||
yang/frr-route-types.yang.c \
|
||||
yang/frr-vrf.yang.c \
|
||||
yang/frr-routing.yang.c \
|
||||
yang/frr-nexthop.yang.c \
|
||||
yang/ietf/ietf-routing-types.yang.c \
|
||||
yang/ietf/ietf-interfaces.yang.c \
|
||||
yang/frr-module-translator.yang.c \
|
||||
@ -266,6 +269,7 @@ pkginclude_HEADERS += \
|
||||
lib/zlog.h \
|
||||
lib/zlog_targets.h \
|
||||
lib/pbr.h \
|
||||
lib/routing_nb.h \
|
||||
# end
|
||||
|
||||
|
||||
|
144
lib/yang.c
144
lib/yang.c
@ -749,3 +749,147 @@ void yang_terminate(void)
|
||||
|
||||
ly_ctx_destroy(ly_native_ctx, NULL);
|
||||
}
|
||||
|
||||
const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode,
|
||||
const char *name)
|
||||
{
|
||||
const struct lyd_node *orig_dnode = dnode;
|
||||
|
||||
while (orig_dnode) {
|
||||
switch (orig_dnode->schema->nodetype) {
|
||||
case LYS_LIST:
|
||||
case LYS_CONTAINER:
|
||||
if (!strcmp(orig_dnode->schema->name, name))
|
||||
return orig_dnode;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
orig_dnode = orig_dnode->parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* API to check if the given node is last node in the list */
|
||||
static bool yang_is_last_list_dnode(const struct lyd_node *dnode)
|
||||
{
|
||||
return (((dnode->next == NULL)
|
||||
|| (dnode->next
|
||||
&& (strcmp(dnode->next->schema->name, dnode->schema->name)
|
||||
!= 0)))
|
||||
&& dnode->prev
|
||||
&& ((dnode->prev == dnode)
|
||||
|| (strcmp(dnode->prev->schema->name, dnode->schema->name)
|
||||
!= 0)));
|
||||
}
|
||||
|
||||
/* API to check if the given node is last node in the data tree level */
|
||||
static bool yang_is_last_level_dnode(const struct lyd_node *dnode)
|
||||
{
|
||||
const struct lyd_node *parent;
|
||||
const struct lys_node_list *snode;
|
||||
const struct lyd_node *key_leaf;
|
||||
uint8_t keys_size;
|
||||
|
||||
switch (dnode->schema->nodetype) {
|
||||
case LYS_LIST:
|
||||
assert(dnode->parent);
|
||||
parent = dnode->parent;
|
||||
snode = (struct lys_node_list *)parent->schema;
|
||||
key_leaf = dnode->prev;
|
||||
for (keys_size = 1; keys_size < snode->keys_size; keys_size++)
|
||||
key_leaf = key_leaf->prev;
|
||||
if (key_leaf->prev == dnode)
|
||||
return true;
|
||||
break;
|
||||
case LYS_CONTAINER:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const struct lyd_node *
|
||||
yang_get_subtree_with_no_sibling(const struct lyd_node *dnode)
|
||||
{
|
||||
bool parent = true;
|
||||
const struct lyd_node *node;
|
||||
const struct lys_node_container *snode;
|
||||
|
||||
node = dnode;
|
||||
if (node->schema->nodetype != LYS_LIST)
|
||||
return node;
|
||||
|
||||
while (parent) {
|
||||
switch (node->schema->nodetype) {
|
||||
case LYS_CONTAINER:
|
||||
snode = (struct lys_node_container *)node->schema;
|
||||
if ((!snode->presence)
|
||||
&& yang_is_last_level_dnode(node)) {
|
||||
if (node->parent
|
||||
&& (node->parent->schema->module
|
||||
== dnode->schema->module))
|
||||
node = node->parent;
|
||||
else
|
||||
parent = false;
|
||||
} else
|
||||
parent = false;
|
||||
break;
|
||||
case LYS_LIST:
|
||||
if (yang_is_last_list_dnode(node)
|
||||
&& yang_is_last_level_dnode(node)) {
|
||||
if (node->parent
|
||||
&& (node->parent->schema->module
|
||||
== dnode->schema->module))
|
||||
node = node->parent;
|
||||
else
|
||||
parent = false;
|
||||
} else
|
||||
parent = false;
|
||||
break;
|
||||
default:
|
||||
parent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
uint32_t yang_get_list_pos(const struct lyd_node *node)
|
||||
{
|
||||
return lyd_list_pos(node);
|
||||
}
|
||||
|
||||
uint32_t yang_get_list_elements_count(const struct lyd_node *node)
|
||||
{
|
||||
unsigned int count;
|
||||
struct lys_node *schema;
|
||||
|
||||
if (!node
|
||||
|| ((node->schema->nodetype != LYS_LIST)
|
||||
&& (node->schema->nodetype != LYS_LEAFLIST))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
schema = node->schema;
|
||||
count = 0;
|
||||
do {
|
||||
if (node->schema == schema)
|
||||
++count;
|
||||
node = node->next;
|
||||
} while (node);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode)
|
||||
{
|
||||
if (dnode)
|
||||
return dnode->child;
|
||||
return NULL;
|
||||
}
|
||||
|
53
lib/yang.h
53
lib/yang.h
@ -34,7 +34,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Maximum XPath length. */
|
||||
#define XPATH_MAXLEN 512
|
||||
#define XPATH_MAXLEN 1024
|
||||
|
||||
/* Maximum list key length. */
|
||||
#define LIST_MAXKEYS 8
|
||||
@ -551,6 +551,57 @@ extern void yang_init(bool embedded_modules);
|
||||
*/
|
||||
extern void yang_terminate(void);
|
||||
|
||||
/*
|
||||
* API to return the parent dnode having a given schema-node name
|
||||
* Use case: One has to access the parent dnode's private pointer
|
||||
* for a given child node.
|
||||
* For that there is a need to find parent dnode first.
|
||||
*
|
||||
* dnode The starting node to work on
|
||||
*
|
||||
* name The name of container/list schema-node
|
||||
*
|
||||
* Returns The dnode matched with the given name
|
||||
*/
|
||||
extern const struct lyd_node *
|
||||
yang_dnode_get_parent(const struct lyd_node *dnode, const char *name);
|
||||
|
||||
|
||||
/*
|
||||
* In some cases there is a need to auto delete the parent nodes
|
||||
* if the given node is last in the list.
|
||||
* It tries to delete all the parents in a given tree in a given module.
|
||||
* The use case is with static routes and route maps
|
||||
* example : ip route 1.1.1.1/32 ens33
|
||||
* ip route 1.1.1.1/32 ens34
|
||||
* After this no ip route 1.1.1.1/32 ens34 came, now staticd
|
||||
* has to find out upto which level it has to delete the dnodes.
|
||||
* For this case it has to send delete nexthop
|
||||
* After this no ip route 1.1.1.1/32 ens33 came, now staticd has to
|
||||
* clear nexthop, path and route nodes.
|
||||
* The same scheme is required for routemaps also
|
||||
* dnode The starting node to work on
|
||||
*
|
||||
* Returns The final parent node selected for deletion
|
||||
*/
|
||||
extern const struct lyd_node *
|
||||
yang_get_subtree_with_no_sibling(const struct lyd_node *dnode);
|
||||
|
||||
/* To get the relative position of a node in list */
|
||||
extern uint32_t yang_get_list_pos(const struct lyd_node *node);
|
||||
|
||||
/* To get the number of elements in a list
|
||||
*
|
||||
* dnode : The head of list
|
||||
* Returns : The number of dnodes present in the list
|
||||
*/
|
||||
extern uint32_t yang_get_list_elements_count(const struct lyd_node *node);
|
||||
|
||||
|
||||
/* To get the immediate child of a dnode */
|
||||
const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1191,3 +1191,38 @@ const char *yang_nexthop_type2str(uint32_t ntype)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi)
|
||||
{
|
||||
if (afi == AFI_IP && safi == SAFI_UNICAST)
|
||||
return "frr-routing:ipv4-unicast";
|
||||
if (afi == AFI_IP6 && safi == SAFI_UNICAST)
|
||||
return "frr-routing:ipv6-unicast";
|
||||
if (afi == AFI_IP && safi == SAFI_MULTICAST)
|
||||
return "frr-routing:ipv4-multicast";
|
||||
if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
|
||||
return "frr-routing:ipv6-multicast";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi)
|
||||
{
|
||||
if (strmatch(key, "frr-routing:ipv4-unicast")) {
|
||||
*afi = AFI_IP;
|
||||
*safi = SAFI_UNICAST;
|
||||
} else if (strmatch(key, "frr-routing:ipv6-unicast")) {
|
||||
*afi = AFI_IP6;
|
||||
*safi = SAFI_UNICAST;
|
||||
} else if (strmatch(key, "frr-routing:ipv4-multicast")) {
|
||||
*afi = AFI_IP;
|
||||
*safi = SAFI_MULTICAST;
|
||||
} else if (strmatch(key, "frr-routing:ipv6-multicast")) {
|
||||
*afi = AFI_IP6;
|
||||
*safi = SAFI_MULTICAST;
|
||||
} else {
|
||||
*afi = AFI_UNSPEC;
|
||||
*safi = SAFI_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
@ -191,6 +191,9 @@ extern struct yang_data *yang_data_new_date_and_time(const char *xpath,
|
||||
/* nexthop enum2str */
|
||||
extern const char *yang_nexthop_type2str(uint32_t ntype);
|
||||
|
||||
const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi);
|
||||
void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -31,12 +31,14 @@
|
||||
#include "vrf.h"
|
||||
#include "nexthop.h"
|
||||
#include "filter.h"
|
||||
#include "routing_nb.h"
|
||||
|
||||
#include "static_vrf.h"
|
||||
#include "static_vty.h"
|
||||
#include "static_routes.h"
|
||||
#include "static_zebra.h"
|
||||
#include "static_debug.h"
|
||||
#include "static_nb.h"
|
||||
|
||||
char backup_config_file[256];
|
||||
|
||||
@ -63,10 +65,12 @@ struct option longopts[] = { { 0 } };
|
||||
/* Master of threads. */
|
||||
struct thread_master *master;
|
||||
|
||||
static struct frr_daemon_info staticd_di;
|
||||
/* SIGHUP handler. */
|
||||
static void sighup(void)
|
||||
{
|
||||
zlog_info("SIGHUP received");
|
||||
vty_read_config(NULL, staticd_di.config_file, config_default);
|
||||
}
|
||||
|
||||
/* SIGINT / SIGTERM handler. */
|
||||
@ -108,7 +112,10 @@ struct quagga_signal_t static_signals[] = {
|
||||
|
||||
static const struct frr_yang_module_info *const staticd_yang_modules[] = {
|
||||
&frr_filter_info,
|
||||
&frr_interface_info,
|
||||
&frr_vrf_info,
|
||||
&frr_routing_info,
|
||||
&frr_staticd_info,
|
||||
};
|
||||
|
||||
#define STATIC_VTY_PORT 2616
|
||||
@ -155,6 +162,9 @@ int main(int argc, char **argv, char **envp)
|
||||
static_zebra_init();
|
||||
static_vty_init();
|
||||
|
||||
hook_register(routing_conf_event,
|
||||
routing_control_plane_protocols_name_validate);
|
||||
|
||||
snprintf(backup_config_file, sizeof(backup_config_file),
|
||||
"%s/zebra.conf", frr_sysconfdir);
|
||||
staticd_di.backup_config_file = backup_config_file;
|
||||
|
@ -25,4 +25,4 @@
|
||||
|
||||
DEFINE_MGROUP(STATIC, "staticd")
|
||||
|
||||
DEFINE_MTYPE(STATIC, STATIC_ROUTE, "Static Route");
|
||||
DEFINE_MTYPE(STATIC, STATIC_NEXTHOP, "Static Nexthop");
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
DECLARE_MGROUP(STATIC)
|
||||
|
||||
DECLARE_MTYPE(STATIC_ROUTE);
|
||||
DECLARE_MTYPE(STATIC_NEXTHOP);
|
||||
DECLARE_MTYPE(STATIC_PATH);
|
||||
|
||||
#endif
|
||||
|
188
staticd/static_nb.c
Normal file
188
staticd/static_nb.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Vmware
|
||||
* Vishal Dhingra
|
||||
*
|
||||
* 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; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "northbound.h"
|
||||
#include "libfrr.h"
|
||||
#include "static_nb.h"
|
||||
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
const struct frr_yang_module_info frr_staticd_info = {
|
||||
.name = "frr-staticd",
|
||||
.nodes = {
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/tag",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/table-id",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop",
|
||||
.cbs = {
|
||||
.apply_finish = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish,
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy,
|
||||
.pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy,
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify,
|
||||
.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/src-list",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/tag",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/table-id",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop",
|
||||
.cbs = {
|
||||
.apply_finish = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish,
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy,
|
||||
.pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/bh-type",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/onlink",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry",
|
||||
.cbs = {
|
||||
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class",
|
||||
.cbs = {
|
||||
.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify,
|
||||
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = NULL,
|
||||
},
|
||||
}
|
||||
};
|
166
staticd/static_nb.h
Normal file
166
staticd/static_nb.h
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Vmware
|
||||
* Vishal Dhingra
|
||||
*
|
||||
* 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; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _FRR_STATIC_NB_H_
|
||||
#define _FRR_STATIC_NB_H_
|
||||
|
||||
extern const struct frr_yang_module_info frr_staticd_info;
|
||||
|
||||
/* Mandatory callbacks. */
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
|
||||
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_label_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify(
|
||||
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_ttl_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify(
|
||||
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 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(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
|
||||
/* Optional 'apply_finish' callbacks. */
|
||||
|
||||
void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish(
|
||||
struct nb_cb_apply_finish_args *args);
|
||||
void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish(
|
||||
struct nb_cb_apply_finish_args *args);
|
||||
|
||||
/* Optional 'pre_validate' callbacks. */
|
||||
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate(
|
||||
struct nb_cb_pre_validate_args *args);
|
||||
|
||||
/*
|
||||
* Callback registered with routing_nb lib to validate only
|
||||
* one instance of staticd is allowed
|
||||
*/
|
||||
int routing_control_plane_protocols_name_validate(
|
||||
struct nb_cb_create_args *args);
|
||||
|
||||
/* xpath macros */
|
||||
/* route-list */
|
||||
#define FRR_STATIC_ROUTE_INFO_KEY_XPATH \
|
||||
"/frr-routing:routing/control-plane-protocols/" \
|
||||
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
|
||||
"frr-staticd:staticd/route-list[prefix='%s'][afi-safi='%s']/" \
|
||||
"path-list[distance='%u']"
|
||||
|
||||
|
||||
#define FRR_STATIC_ROUTE_PATH_TAG_XPATH "/tag"
|
||||
|
||||
#define FRR_STATIC_ROUTE_PATH_TABLEID_XPATH "/table-id"
|
||||
|
||||
/* route-list/frr-nexthops */
|
||||
#define FRR_STATIC_ROUTE_NH_KEY_XPATH \
|
||||
"/frr-nexthops/" \
|
||||
"nexthop[nh-type='%s'][vrf='%s'][gateway='%s'][interface='%s']"
|
||||
|
||||
#define FRR_STATIC_ROUTE_NH_ONLINK_XPATH "/onlink"
|
||||
|
||||
#define FRR_STATIC_ROUTE_NH_BH_XPATH "/bh-type"
|
||||
|
||||
#define FRR_STATIC_ROUTE_NH_LABEL_XPATH "/mpls-label-stack"
|
||||
|
||||
#define FRR_STATIC_ROUTE_NHLB_KEY_XPATH "/entry[id='%u']/label"
|
||||
|
||||
/* route-list/srclist */
|
||||
#define FRR_S_ROUTE_SRC_INFO_KEY_XPATH \
|
||||
"/frr-routing:routing/control-plane-protocols/" \
|
||||
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
|
||||
"frr-staticd:staticd/route-list[prefix='%s'][afi-safi='%s']/" \
|
||||
"src-list[src-prefix='%s']/path-list[distance='%u']"
|
||||
|
||||
/* route-list/frr-nexthops */
|
||||
#define FRR_DEL_S_ROUTE_NH_KEY_XPATH \
|
||||
FRR_STATIC_ROUTE_INFO_KEY_XPATH \
|
||||
FRR_STATIC_ROUTE_NH_KEY_XPATH
|
||||
|
||||
/* route-list/src/src-list/frr-nexthops*/
|
||||
#define FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH \
|
||||
FRR_S_ROUTE_SRC_INFO_KEY_XPATH \
|
||||
FRR_STATIC_ROUTE_NH_KEY_XPATH
|
||||
|
||||
#endif
|
1241
staticd/static_nb_config.c
Normal file
1241
staticd/static_nb_config.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -30,33 +30,33 @@
|
||||
#include "static_zebra.h"
|
||||
#include "static_nht.h"
|
||||
|
||||
static void static_nht_update_rn(struct route_node *rn,
|
||||
struct prefix *nhp, uint32_t nh_num,
|
||||
vrf_id_t nh_vrf_id, struct vrf *vrf,
|
||||
safi_t safi)
|
||||
static void static_nht_update_path(struct route_node *rn,
|
||||
struct static_path *pn, struct prefix *nhp,
|
||||
uint32_t nh_num, vrf_id_t nh_vrf_id,
|
||||
struct vrf *vrf, safi_t safi)
|
||||
{
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (si->nh_vrf_id != nh_vrf_id)
|
||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||
if (nh->nh_vrf_id != nh_vrf_id)
|
||||
continue;
|
||||
|
||||
if (si->type != STATIC_IPV4_GATEWAY
|
||||
&& si->type != STATIC_IPV4_GATEWAY_IFNAME
|
||||
&& si->type != STATIC_IPV6_GATEWAY
|
||||
&& si->type != STATIC_IPV6_GATEWAY_IFNAME)
|
||||
if (nh->type != STATIC_IPV4_GATEWAY
|
||||
&& nh->type != STATIC_IPV4_GATEWAY_IFNAME
|
||||
&& nh->type != STATIC_IPV6_GATEWAY
|
||||
&& nh->type != STATIC_IPV6_GATEWAY_IFNAME)
|
||||
continue;
|
||||
|
||||
if (nhp->family == AF_INET
|
||||
&& nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr)
|
||||
si->nh_valid = !!nh_num;
|
||||
&& nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr)
|
||||
nh->nh_valid = !!nh_num;
|
||||
|
||||
if (nhp->family == AF_INET6
|
||||
&& memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0)
|
||||
si->nh_valid = !!nh_num;
|
||||
&& memcmp(&nhp->u.prefix6, &nh->addr.ipv6, 16) == 0)
|
||||
nh->nh_valid = !!nh_num;
|
||||
|
||||
if (si->state == STATIC_START)
|
||||
static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
|
||||
if (nh->state == STATIC_START)
|
||||
static_zebra_route_add(rn, pn, safi, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +67,8 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
|
||||
struct route_table *stable;
|
||||
struct static_vrf *svrf;
|
||||
struct route_node *rn;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
svrf = vrf->info;
|
||||
if (!svrf)
|
||||
@ -78,17 +80,26 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
|
||||
|
||||
if (sp) {
|
||||
rn = srcdest_rnode_lookup(stable, sp, NULL);
|
||||
if (rn) {
|
||||
static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id,
|
||||
vrf, safi);
|
||||
if (rn && rn->info) {
|
||||
si = static_route_info_from_rnode(rn);
|
||||
frr_each(static_path_list, &si->path_list, pn) {
|
||||
static_nht_update_path(rn, pn, nhp, nh_num,
|
||||
nh_vrf_id, vrf, safi);
|
||||
}
|
||||
route_unlock_node(rn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn))
|
||||
static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, vrf, safi);
|
||||
|
||||
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) {
|
||||
static_nht_update_path(rn, pn, nhp, nh_num, nh_vrf_id,
|
||||
vrf, safi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void static_nht_update(struct prefix *sp, struct prefix *nhp,
|
||||
@ -111,8 +122,10 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
|
||||
{
|
||||
struct static_vrf *svrf;
|
||||
struct route_table *stable;
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct route_node *rn;
|
||||
struct static_route_info *si;
|
||||
|
||||
svrf = vrf->info;
|
||||
if (!svrf)
|
||||
@ -123,25 +136,33 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
|
||||
return;
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn)) {
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (si->nh_vrf_id != nh_vrf_id)
|
||||
continue;
|
||||
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 != nh_vrf_id)
|
||||
continue;
|
||||
|
||||
if (nhp->family == AF_INET
|
||||
&& nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr)
|
||||
continue;
|
||||
if (nhp->family == AF_INET
|
||||
&& nhp->u.prefix4.s_addr
|
||||
!= nh->addr.ipv4.s_addr)
|
||||
continue;
|
||||
|
||||
if (nhp->family == AF_INET6
|
||||
&& memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0)
|
||||
continue;
|
||||
if (nhp->family == AF_INET6
|
||||
&& memcmp(&nhp->u.prefix6, &nh->addr.ipv6,
|
||||
16)
|
||||
!= 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We've been told that a nexthop we depend
|
||||
* on has changed in some manner, so reset
|
||||
* the state machine to allow us to start
|
||||
* over.
|
||||
*/
|
||||
si->state = STATIC_START;
|
||||
/*
|
||||
* We've been told that a nexthop we
|
||||
* depend on has changed in some manner,
|
||||
* so reset the state machine to allow
|
||||
* us to start over.
|
||||
*/
|
||||
nh->state = STATIC_START;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,8 +185,10 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
|
||||
{
|
||||
struct static_vrf *svrf;
|
||||
struct route_table *stable;
|
||||
struct static_route *si;
|
||||
struct route_node *rn;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
svrf = vrf->info;
|
||||
if (!svrf)
|
||||
@ -178,9 +201,14 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
|
||||
rn = srcdest_rnode_lookup(stable, sp, NULL);
|
||||
if (!rn)
|
||||
return;
|
||||
|
||||
for (si = rn->info; si; si = si->next)
|
||||
si->state = state;
|
||||
si = rn->info;
|
||||
if (si) {
|
||||
frr_each(static_path_list, &si->path_list, pn) {
|
||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||
nh->state = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
route_unlock_node(rn);
|
||||
}
|
||||
|
@ -32,267 +32,366 @@
|
||||
#include "static_memory.h"
|
||||
#include "static_zebra.h"
|
||||
|
||||
/* Install static route into rib. */
|
||||
static void static_install_route(struct route_node *rn,
|
||||
struct static_route *si_changed, safi_t safi)
|
||||
DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info");
|
||||
DEFINE_MTYPE(STATIC, STATIC_PATH, "Static Path");
|
||||
|
||||
/* Install static path into rib. */
|
||||
void static_install_path(struct route_node *rn, struct static_path *pn,
|
||||
safi_t safi, struct static_vrf *svrf)
|
||||
{
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
|
||||
for (si = rn->info; si; si = si->next)
|
||||
static_zebra_nht_register(rn, si, true);
|
||||
|
||||
si = rn->info;
|
||||
if (si)
|
||||
static_zebra_route_add(rn, si_changed, si->vrf_id, safi, true);
|
||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh)
|
||||
static_zebra_nht_register(rn, nh, true);
|
||||
|
||||
if (static_nexthop_list_count(&pn->nexthop_list) && svrf && svrf->vrf)
|
||||
static_zebra_route_add(rn, pn, safi, true);
|
||||
}
|
||||
|
||||
/* Uninstall static route from RIB. */
|
||||
static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi,
|
||||
struct route_node *rn,
|
||||
struct static_route *si_changed)
|
||||
/* Uninstall static path from RIB. */
|
||||
static void static_uninstall_path(struct route_node *rn, struct static_path *pn,
|
||||
safi_t safi, struct static_vrf *svrf)
|
||||
{
|
||||
|
||||
if (rn->info)
|
||||
static_zebra_route_add(rn, si_changed, vrf_id, safi, true);
|
||||
if (static_nexthop_list_count(&pn->nexthop_list))
|
||||
static_zebra_route_add(rn, pn, safi, true);
|
||||
else
|
||||
static_zebra_route_add(rn, si_changed, vrf_id, safi, false);
|
||||
static_zebra_route_add(rn, pn, safi, false);
|
||||
}
|
||||
|
||||
int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, union g_addr *gate,
|
||||
const char *ifname, enum static_blackhole_type bh_type,
|
||||
route_tag_t tag, uint8_t distance, struct static_vrf *svrf,
|
||||
struct static_vrf *nh_svrf,
|
||||
struct static_nh_label *snh_label, uint32_t table_id,
|
||||
bool onlink)
|
||||
struct route_node *static_add_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p,
|
||||
struct static_vrf *svrf)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct static_route *pp;
|
||||
struct static_route *cp;
|
||||
struct static_route *update = NULL;
|
||||
struct static_route_info *si;
|
||||
struct route_table *stable = svrf->stable[afi][safi];
|
||||
struct interface *ifp;
|
||||
|
||||
if (!stable)
|
||||
return -1;
|
||||
|
||||
if (!gate && (type == STATIC_IPV4_GATEWAY
|
||||
|| type == STATIC_IPV4_GATEWAY_IFNAME
|
||||
|| type == STATIC_IPV6_GATEWAY
|
||||
|| type == STATIC_IPV6_GATEWAY_IFNAME))
|
||||
return -1;
|
||||
|
||||
if (!ifname
|
||||
&& (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME
|
||||
|| type == STATIC_IPV6_GATEWAY_IFNAME))
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
/* Lookup static route prefix. */
|
||||
rn = srcdest_rnode_get(stable, p, src_p);
|
||||
|
||||
/* Do nothing if there is a same static route. */
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (type == si->type
|
||||
&& (!gate
|
||||
|| ((afi == AFI_IP
|
||||
&& IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
|
||||
|| (afi == AFI_IP6
|
||||
&& IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
|
||||
&& (!strcmp(ifname ? ifname : "", si->ifname))
|
||||
&& nh_svrf->vrf->vrf_id == si->nh_vrf_id) {
|
||||
if ((distance == si->distance) && (tag == si->tag)
|
||||
&& (table_id == si->table_id)
|
||||
&& !memcmp(&si->snh_label, snh_label,
|
||||
sizeof(struct static_nh_label))
|
||||
&& si->bh_type == bh_type && si->onlink == onlink) {
|
||||
route_unlock_node(rn);
|
||||
return 0;
|
||||
}
|
||||
update = si;
|
||||
}
|
||||
si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route_info));
|
||||
static_route_info_init(si);
|
||||
|
||||
rn->info = si;
|
||||
|
||||
/* Mark as having FRR configuration */
|
||||
vrf_set_user_cfged(svrf->vrf);
|
||||
|
||||
return rn;
|
||||
}
|
||||
|
||||
/* To delete the srcnodes */
|
||||
static void static_del_src_route(struct route_node *rn, safi_t safi,
|
||||
struct static_vrf *svrf)
|
||||
{
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
si = rn->info;
|
||||
|
||||
frr_each_safe(static_path_list, &si->path_list, pn) {
|
||||
static_del_path(rn, pn, safi, svrf);
|
||||
}
|
||||
|
||||
/* Distance or tag or label changed, delete existing first. */
|
||||
if (update)
|
||||
static_delete_route(afi, safi, type, p, src_p, gate, ifname,
|
||||
update->tag, update->distance, svrf,
|
||||
&update->snh_label, table_id);
|
||||
XFREE(MTYPE_STATIC_ROUTE, rn->info);
|
||||
route_unlock_node(rn);
|
||||
/* If no other FRR config for this VRF, mark accordingly. */
|
||||
if (!static_vrf_has_config(svrf))
|
||||
vrf_reset_user_cfged(svrf->vrf);
|
||||
}
|
||||
|
||||
void static_del_route(struct route_node *rn, safi_t safi,
|
||||
struct static_vrf *svrf)
|
||||
{
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
struct route_table *src_table;
|
||||
struct route_node *src_node;
|
||||
|
||||
si = rn->info;
|
||||
|
||||
frr_each_safe(static_path_list, &si->path_list, pn) {
|
||||
static_del_path(rn, pn, safi, svrf);
|
||||
}
|
||||
|
||||
/* clean up for dst table */
|
||||
src_table = srcdest_srcnode_table(rn);
|
||||
if (src_table) {
|
||||
/* This means the route_node is part of the top hierarchy
|
||||
* and refers to a destination prefix.
|
||||
*/
|
||||
for (src_node = route_top(src_table); src_node;
|
||||
src_node = route_next(src_node)) {
|
||||
static_del_src_route(src_node, safi, svrf);
|
||||
}
|
||||
}
|
||||
XFREE(MTYPE_STATIC_ROUTE, rn->info);
|
||||
route_unlock_node(rn);
|
||||
/* If no other FRR config for this VRF, mark accordingly. */
|
||||
if (!static_vrf_has_config(svrf))
|
||||
vrf_reset_user_cfged(svrf->vrf);
|
||||
}
|
||||
|
||||
bool static_add_nexthop_validate(struct static_vrf *svrf, static_types type,
|
||||
struct ipaddr *ipaddr)
|
||||
{
|
||||
switch (type) {
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
if (if_lookup_exact_address(&ipaddr->ipaddr_v4, AF_INET,
|
||||
svrf->vrf->vrf_id))
|
||||
return false;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
if (if_lookup_exact_address(&ipaddr->ipaddr_v6, AF_INET6,
|
||||
svrf->vrf->vrf_id))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct static_path *static_add_path(struct route_node *rn, uint8_t distance)
|
||||
{
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
route_lock_node(rn);
|
||||
|
||||
/* Make new static route structure. */
|
||||
si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
|
||||
pn = XCALLOC(MTYPE_STATIC_PATH, sizeof(struct static_path));
|
||||
|
||||
si->type = type;
|
||||
si->distance = distance;
|
||||
si->bh_type = bh_type;
|
||||
si->tag = tag;
|
||||
si->vrf_id = svrf->vrf->vrf_id;
|
||||
si->nh_vrf_id = nh_svrf->vrf->vrf_id;
|
||||
strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname));
|
||||
si->table_id = table_id;
|
||||
si->onlink = onlink;
|
||||
pn->distance = distance;
|
||||
static_nexthop_list_init(&(pn->nexthop_list));
|
||||
|
||||
si = rn->info;
|
||||
static_path_list_add_head(&(si->path_list), pn);
|
||||
|
||||
return pn;
|
||||
}
|
||||
|
||||
void static_del_path(struct route_node *rn, struct static_path *pn, safi_t safi,
|
||||
struct static_vrf *svrf)
|
||||
{
|
||||
struct static_route_info *si;
|
||||
struct static_nexthop *nh;
|
||||
|
||||
si = rn->info;
|
||||
|
||||
static_path_list_del(&si->path_list, pn);
|
||||
|
||||
frr_each_safe(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||
static_delete_nexthop(rn, pn, safi, svrf, nh);
|
||||
}
|
||||
|
||||
route_unlock_node(rn);
|
||||
|
||||
XFREE(MTYPE_STATIC_PATH, pn);
|
||||
}
|
||||
|
||||
struct static_nexthop *
|
||||
static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi,
|
||||
struct static_vrf *svrf, static_types type,
|
||||
struct ipaddr *ipaddr, const char *ifname,
|
||||
const char *nh_vrf)
|
||||
{
|
||||
struct static_nexthop *nh;
|
||||
struct static_vrf *nh_svrf;
|
||||
struct interface *ifp;
|
||||
struct static_nexthop *cp;
|
||||
|
||||
route_lock_node(rn);
|
||||
|
||||
nh_svrf = static_vty_get_unknown_vrf(nh_vrf);
|
||||
|
||||
if (!nh_svrf)
|
||||
return NULL;
|
||||
|
||||
/* Make new static route structure. */
|
||||
nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
|
||||
|
||||
nh->type = type;
|
||||
|
||||
nh->nh_vrf_id = nh_svrf->vrf->vrf_id;
|
||||
strlcpy(nh->nh_vrfname, nh_svrf->vrf->name, sizeof(nh->nh_vrfname));
|
||||
|
||||
if (ifname)
|
||||
strlcpy(si->ifname, ifname, sizeof(si->ifname));
|
||||
si->ifindex = IFINDEX_INTERNAL;
|
||||
strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
|
||||
nh->ifindex = IFINDEX_INTERNAL;
|
||||
|
||||
switch (type) {
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
si->addr.ipv4 = gate->ipv4;
|
||||
nh->addr.ipv4 = ipaddr->ipaddr_v4;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
si->addr.ipv6 = gate->ipv6;
|
||||
nh->addr.ipv6 = ipaddr->ipaddr_v6;
|
||||
break;
|
||||
case STATIC_IFNAME:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Save labels, if any. */
|
||||
memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
|
||||
|
||||
/*
|
||||
* Add new static route information to the tree with sort by
|
||||
* distance value and gateway address.
|
||||
* gateway address.
|
||||
*/
|
||||
for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
|
||||
if (si->distance < cp->distance)
|
||||
break;
|
||||
if (si->distance > cp->distance)
|
||||
continue;
|
||||
if (si->type == STATIC_IPV4_GATEWAY
|
||||
frr_each(static_nexthop_list, &pn->nexthop_list, cp) {
|
||||
if (nh->type == STATIC_IPV4_GATEWAY
|
||||
&& cp->type == STATIC_IPV4_GATEWAY) {
|
||||
if (ntohl(si->addr.ipv4.s_addr)
|
||||
if (ntohl(nh->addr.ipv4.s_addr)
|
||||
< ntohl(cp->addr.ipv4.s_addr))
|
||||
break;
|
||||
if (ntohl(si->addr.ipv4.s_addr)
|
||||
if (ntohl(nh->addr.ipv4.s_addr)
|
||||
> ntohl(cp->addr.ipv4.s_addr))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh);
|
||||
|
||||
/* Make linked list. */
|
||||
if (pp)
|
||||
pp->next = si;
|
||||
else
|
||||
rn->info = si;
|
||||
if (cp)
|
||||
cp->prev = si;
|
||||
si->prev = pp;
|
||||
si->next = cp;
|
||||
if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
|
||||
return nh;
|
||||
|
||||
/* check whether interface exists in system & install if it does */
|
||||
switch (si->type) {
|
||||
switch (nh->type) {
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
static_zebra_nht_register(rn, si, true);
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
|
||||
ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
|
||||
if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
|
||||
si->ifindex = ifp->ifindex;
|
||||
nh->ifindex = ifp->ifindex;
|
||||
else
|
||||
zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
|
||||
ifname);
|
||||
zlog_warn(
|
||||
"Static Route using %s interface not installed because the interface does not exist in specified vrf",
|
||||
ifname);
|
||||
|
||||
static_zebra_nht_register(rn, si, true);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
static_install_route(rn, si, safi);
|
||||
break;
|
||||
case STATIC_IFNAME:
|
||||
ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
|
||||
if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
|
||||
si->ifindex = ifp->ifindex;
|
||||
static_install_route(rn, si, safi);
|
||||
nh->ifindex = ifp->ifindex;
|
||||
} else
|
||||
zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
|
||||
ifname);
|
||||
|
||||
zlog_warn(
|
||||
"Static Route using %s interface not installed because the interface does not exist in specified vrf",
|
||||
ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return nh;
|
||||
}
|
||||
|
||||
int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, union g_addr *gate,
|
||||
const char *ifname, route_tag_t tag, uint8_t distance,
|
||||
struct static_vrf *svrf,
|
||||
struct static_nh_label *snh_label,
|
||||
uint32_t table_id)
|
||||
void static_install_nexthop(struct route_node *rn, struct static_path *pn,
|
||||
struct static_nexthop *nh, safi_t safi,
|
||||
struct static_vrf *svrf, const char *ifname,
|
||||
static_types type, const char *nh_vrf)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct route_table *stable;
|
||||
struct static_vrf *nh_svrf;
|
||||
struct interface *ifp;
|
||||
|
||||
/* Lookup table. */
|
||||
stable = static_vrf_static_table(afi, safi, svrf);
|
||||
if (!stable)
|
||||
return -1;
|
||||
nh_svrf = static_vty_get_unknown_vrf(nh_vrf);
|
||||
|
||||
/* Lookup static route prefix. */
|
||||
rn = srcdest_rnode_lookup(stable, p, src_p);
|
||||
if (!rn)
|
||||
return 0;
|
||||
if (!nh_svrf)
|
||||
return;
|
||||
|
||||
/* Find same static route is the tree */
|
||||
for (si = rn->info; si; si = si->next)
|
||||
if (type == si->type
|
||||
&& (!gate
|
||||
|| ((afi == AFI_IP
|
||||
&& IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
|
||||
|| (afi == AFI_IP6
|
||||
&& IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
|
||||
&& (!strcmp(ifname ? ifname : "", si->ifname))
|
||||
&& (!tag || (tag == si->tag))
|
||||
&& (table_id == si->table_id)
|
||||
&& (!snh_label->num_labels
|
||||
|| !memcmp(&si->snh_label, snh_label,
|
||||
sizeof(struct static_nh_label))))
|
||||
break;
|
||||
if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
|
||||
return;
|
||||
|
||||
/* Can't find static route. */
|
||||
if (!si) {
|
||||
route_unlock_node(rn);
|
||||
return 0;
|
||||
/* check whether interface exists in system & install if it does */
|
||||
switch (nh->type) {
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
if (!static_zebra_nh_update(rn, nh))
|
||||
static_zebra_nht_register(rn, nh, true);
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
if (!static_zebra_nh_update(rn, nh))
|
||||
static_zebra_nht_register(rn, nh, true);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
static_install_path(rn, pn, safi, svrf);
|
||||
break;
|
||||
case STATIC_IFNAME:
|
||||
ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
|
||||
if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
|
||||
static_install_path(rn, pn, safi, svrf);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static_zebra_nht_register(rn, si, false);
|
||||
int static_delete_nexthop(struct route_node *rn, struct static_path *pn,
|
||||
safi_t safi, struct static_vrf *svrf,
|
||||
struct static_nexthop *nh)
|
||||
{
|
||||
struct static_vrf *nh_svrf;
|
||||
|
||||
/* Unlink static route from linked list. */
|
||||
if (si->prev)
|
||||
si->prev->next = si->next;
|
||||
else
|
||||
rn->info = si->next;
|
||||
if (si->next)
|
||||
si->next->prev = si->prev;
|
||||
nh_svrf = static_vrf_lookup_by_name(nh->nh_vrfname);
|
||||
|
||||
static_nexthop_list_del(&(pn->nexthop_list), nh);
|
||||
|
||||
if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
|
||||
goto EXIT;
|
||||
|
||||
static_zebra_nht_register(rn, nh, false);
|
||||
/*
|
||||
* If we have other si nodes then route replace
|
||||
* else delete the route
|
||||
*/
|
||||
static_uninstall_route(si->vrf_id, safi, rn, si);
|
||||
route_unlock_node(rn);
|
||||
static_uninstall_path(rn, pn, safi, svrf);
|
||||
|
||||
EXIT:
|
||||
route_unlock_node(rn);
|
||||
/* Free static route configuration. */
|
||||
XFREE(MTYPE_STATIC_ROUTE, si);
|
||||
|
||||
route_unlock_node(rn);
|
||||
XFREE(MTYPE_STATIC_NEXTHOP, nh);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void static_ifindex_update_nh(struct interface *ifp, bool up,
|
||||
struct route_node *rn,
|
||||
struct static_path *pn,
|
||||
struct static_nexthop *nh,
|
||||
struct static_vrf *svrf, safi_t safi)
|
||||
{
|
||||
if (!nh->ifname[0])
|
||||
return;
|
||||
if (up) {
|
||||
if (strcmp(nh->ifname, ifp->name))
|
||||
return;
|
||||
if (nh->nh_vrf_id != ifp->vrf_id)
|
||||
return;
|
||||
nh->ifindex = ifp->ifindex;
|
||||
} else {
|
||||
if (nh->ifindex != ifp->ifindex)
|
||||
return;
|
||||
if (nh->nh_vrf_id != ifp->vrf_id)
|
||||
return;
|
||||
nh->ifindex = IFINDEX_INTERNAL;
|
||||
}
|
||||
|
||||
static_install_path(rn, pn, safi, svrf);
|
||||
}
|
||||
|
||||
static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
struct route_table *stable;
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct vrf *vrf;
|
||||
struct static_route_info *si;
|
||||
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
struct static_vrf *svrf;
|
||||
@ -302,26 +401,17 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
|
||||
stable = static_vrf_static_table(afi, safi, svrf);
|
||||
if (!stable)
|
||||
continue;
|
||||
|
||||
for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (!si->ifname[0])
|
||||
continue;
|
||||
if (up) {
|
||||
if (strcmp(si->ifname, ifp->name))
|
||||
continue;
|
||||
if (si->nh_vrf_id != ifp->vrf_id)
|
||||
continue;
|
||||
si->ifindex = ifp->ifindex;
|
||||
} else {
|
||||
if (si->ifindex != ifp->ifindex)
|
||||
continue;
|
||||
if (si->nh_vrf_id != ifp->vrf_id)
|
||||
continue;
|
||||
si->ifindex = IFINDEX_INTERNAL;
|
||||
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) {
|
||||
static_ifindex_update_nh(ifp, up, rn,
|
||||
pn, nh, svrf,
|
||||
safi);
|
||||
}
|
||||
|
||||
static_install_route(rn, si, safi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,26 +433,34 @@ static void static_fixup_vrf(struct static_vrf *svrf,
|
||||
struct route_table *stable, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
struct interface *ifp;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn)) {
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
|
||||
continue;
|
||||
|
||||
si->nh_vrf_id = svrf->vrf->vrf_id;
|
||||
si->nh_registered = false;
|
||||
if (si->ifindex) {
|
||||
ifp = if_lookup_by_name(si->ifname,
|
||||
si->nh_vrf_id);
|
||||
if (ifp)
|
||||
si->ifindex = ifp->ifindex;
|
||||
else
|
||||
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 (strcmp(svrf->vrf->name, nh->nh_vrfname)
|
||||
!= 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
static_install_route(rn, si, safi);
|
||||
nh->nh_vrf_id = svrf->vrf->vrf_id;
|
||||
nh->nh_registered = false;
|
||||
if (nh->ifindex) {
|
||||
ifp = if_lookup_by_name(nh->ifname,
|
||||
nh->nh_vrf_id);
|
||||
if (ifp)
|
||||
nh->ifindex = ifp->ifindex;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
static_install_path(rn, pn, safi, svrf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -377,26 +475,31 @@ static void static_fixup_vrf(struct static_vrf *svrf,
|
||||
* safi -> the safi in question
|
||||
*/
|
||||
static void static_enable_vrf(struct static_vrf *svrf,
|
||||
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 static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
struct interface *ifp;
|
||||
struct vrf *vrf = svrf->vrf;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn)) {
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
si->vrf_id = vrf->vrf_id;
|
||||
if (si->ifindex) {
|
||||
ifp = if_lookup_by_name(si->ifname,
|
||||
si->nh_vrf_id);
|
||||
if (ifp)
|
||||
si->ifindex = ifp->ifindex;
|
||||
else
|
||||
continue;
|
||||
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->ifindex) {
|
||||
ifp = if_lookup_by_name(nh->ifname,
|
||||
nh->nh_vrf_id);
|
||||
if (ifp)
|
||||
nh->ifindex = ifp->ifindex;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
static_install_path(rn, pn, safi, svrf);
|
||||
}
|
||||
static_install_route(rn, si, safi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -452,14 +555,22 @@ static void static_cleanup_vrf(struct static_vrf *svrf,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn)) {
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
|
||||
continue;
|
||||
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 (strcmp(svrf->vrf->name, nh->nh_vrfname)
|
||||
!= 0)
|
||||
continue;
|
||||
|
||||
static_uninstall_route(si->vrf_id, safi, rn, si);
|
||||
static_uninstall_path(rn, pn, safi, svrf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -476,11 +587,23 @@ static void static_disable_vrf(struct route_table *stable,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct stable_info *info;
|
||||
struct static_route_info *si;
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn))
|
||||
for (si = rn->info; si; si = si->next)
|
||||
static_uninstall_route(si->vrf_id, safi, rn, si);
|
||||
info = route_table_get_info(stable);
|
||||
|
||||
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) {
|
||||
static_uninstall_path(rn, pn, safi, info->svrf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -535,17 +658,27 @@ static void static_fixup_intf_nh(struct route_table *stable,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct stable_info *info;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
info = route_table_get_info(stable);
|
||||
|
||||
for (rn = route_top(stable); rn; rn = route_next(rn)) {
|
||||
for (si = rn->info; si; si = si->next) {
|
||||
if (si->nh_vrf_id != ifp->vrf_id)
|
||||
continue;
|
||||
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_id)
|
||||
continue;
|
||||
|
||||
if (si->ifindex != ifp->ifindex)
|
||||
continue;
|
||||
if (nh->ifindex != ifp->ifindex)
|
||||
continue;
|
||||
|
||||
static_install_route(rn, si, safi);
|
||||
static_install_path(rn, pn, safi, info->svrf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -589,3 +722,40 @@ void static_ifindex_update(struct interface *ifp, bool up)
|
||||
static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
|
||||
static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
|
||||
}
|
||||
|
||||
void static_get_nh_type(static_types stype, char *type, size_t size)
|
||||
{
|
||||
switch (stype) {
|
||||
case STATIC_IFNAME:
|
||||
strlcpy(type, "ifindex", size);
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
strlcpy(type, "ip4", size);
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
strlcpy(type, "ip4-ifindex", size);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
strlcpy(type, "blackhole", size);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
strlcpy(type, "ip6", size);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
strlcpy(type, "ip6-ifindex", size);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
struct stable_info *static_get_stable_info(struct route_node *rn)
|
||||
{
|
||||
struct route_table *table;
|
||||
|
||||
table = srcdest_rnode_table(rn);
|
||||
return table->info;
|
||||
}
|
||||
|
||||
void static_route_info_init(struct static_route_info *si)
|
||||
{
|
||||
static_path_list_init(&(si->path_list));
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define __STATIC_ROUTES_H__
|
||||
|
||||
#include "lib/mpls.h"
|
||||
#include "table.h"
|
||||
|
||||
/* Static route label information */
|
||||
struct static_nh_label {
|
||||
@ -35,13 +36,17 @@ enum static_blackhole_type {
|
||||
STATIC_BLACKHOLE_REJECT
|
||||
};
|
||||
|
||||
/*
|
||||
* The order for below macros should be in sync with
|
||||
* yang model typedef nexthop-type
|
||||
*/
|
||||
typedef enum {
|
||||
STATIC_IFNAME,
|
||||
STATIC_IFNAME = 1,
|
||||
STATIC_IPV4_GATEWAY,
|
||||
STATIC_IPV4_GATEWAY_IFNAME,
|
||||
STATIC_BLACKHOLE,
|
||||
STATIC_IPV6_GATEWAY,
|
||||
STATIC_IPV6_GATEWAY_IFNAME,
|
||||
STATIC_BLACKHOLE,
|
||||
} static_types;
|
||||
|
||||
/*
|
||||
@ -64,14 +69,37 @@ enum static_install_states {
|
||||
STATIC_NOT_INSTALLED,
|
||||
};
|
||||
|
||||
PREDECL_DLIST(static_path_list);
|
||||
PREDECL_DLIST(static_nexthop_list);
|
||||
|
||||
/* Static route information */
|
||||
struct static_route_info {
|
||||
/* path list */
|
||||
struct static_path_list_head path_list;
|
||||
};
|
||||
|
||||
/* Static path information */
|
||||
struct static_path {
|
||||
/* Linkage for static path lists */
|
||||
struct static_path_list_item list;
|
||||
/* Administrative distance. */
|
||||
uint8_t distance;
|
||||
/* Tag */
|
||||
route_tag_t tag;
|
||||
/* Table-id */
|
||||
uint32_t table_id;
|
||||
/* Nexthop list */
|
||||
struct static_nexthop_list_head nexthop_list;
|
||||
};
|
||||
|
||||
DECLARE_DLIST(static_path_list, struct static_path, list);
|
||||
|
||||
/* Static route information. */
|
||||
struct static_route {
|
||||
struct static_nexthop {
|
||||
/* For linked list. */
|
||||
struct static_route *prev;
|
||||
struct static_route *next;
|
||||
struct static_nexthop_list_item list;
|
||||
|
||||
/* VRF identifier. */
|
||||
vrf_id_t vrf_id;
|
||||
vrf_id_t nh_vrf_id;
|
||||
char nh_vrfname[VRF_NAMSIZ + 1];
|
||||
|
||||
@ -81,12 +109,6 @@ struct static_route {
|
||||
*/
|
||||
enum static_install_states state;
|
||||
|
||||
/* Administrative distance. */
|
||||
uint8_t distance;
|
||||
|
||||
/* Tag */
|
||||
route_tag_t tag;
|
||||
|
||||
/* Flag for this static route's type. */
|
||||
static_types type;
|
||||
|
||||
@ -104,8 +126,6 @@ struct static_route {
|
||||
/* Label information */
|
||||
struct static_nh_label snh_label;
|
||||
|
||||
uint32_t table_id;
|
||||
|
||||
/*
|
||||
* Whether to pretend the nexthop is directly attached to the specified
|
||||
* link. Only meaningful when both a gateway address and interface name
|
||||
@ -114,32 +134,64 @@ struct static_route {
|
||||
bool onlink;
|
||||
};
|
||||
|
||||
DECLARE_DLIST(static_nexthop_list, struct static_nexthop, list);
|
||||
|
||||
|
||||
/*
|
||||
* rib_dest_from_rnode
|
||||
*/
|
||||
static inline struct static_route_info *
|
||||
static_route_info_from_rnode(struct route_node *rn)
|
||||
{
|
||||
return (struct static_route_info *)(rn->info);
|
||||
}
|
||||
|
||||
extern bool mpls_enabled;
|
||||
|
||||
extern struct zebra_privs_t static_privs;
|
||||
|
||||
void static_fixup_vrf_ids(struct static_vrf *svrf);
|
||||
|
||||
extern int static_add_route(afi_t afi, safi_t safi, uint8_t type,
|
||||
struct prefix *p, struct prefix_ipv6 *src_p,
|
||||
union g_addr *gate, const char *ifname,
|
||||
enum static_blackhole_type bh_type, route_tag_t tag,
|
||||
uint8_t distance, struct static_vrf *svrf,
|
||||
struct static_vrf *nh_svrf,
|
||||
struct static_nh_label *snh_label,
|
||||
uint32_t table_id, bool onlink);
|
||||
extern struct static_nexthop *
|
||||
static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi,
|
||||
struct static_vrf *svrf, static_types type,
|
||||
struct ipaddr *ipaddr, const char *ifname,
|
||||
const char *nh_vrf);
|
||||
extern void static_install_nexthop(struct route_node *rn,
|
||||
struct static_path *pn,
|
||||
struct static_nexthop *nh, safi_t safi,
|
||||
struct static_vrf *svrf, const char *ifname,
|
||||
static_types type, const char *nh_vrf);
|
||||
|
||||
extern int static_delete_route(afi_t afi, safi_t safi, uint8_t type,
|
||||
struct prefix *p, struct prefix_ipv6 *src_p,
|
||||
union g_addr *gate, const char *ifname,
|
||||
route_tag_t tag, uint8_t distance,
|
||||
struct static_vrf *svrf,
|
||||
struct static_nh_label *snh_label,
|
||||
uint32_t table_id);
|
||||
extern int static_delete_nexthop(struct route_node *rn, struct static_path *pn,
|
||||
safi_t safi, struct static_vrf *svrf,
|
||||
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_install_path(struct route_node *rn, struct static_path *pn,
|
||||
safi_t safi, struct static_vrf *svrf);
|
||||
|
||||
extern struct route_node *static_add_route(afi_t afi, safi_t safi,
|
||||
struct prefix *p,
|
||||
struct prefix_ipv6 *src_p,
|
||||
struct static_vrf *svrf);
|
||||
extern void static_del_route(struct route_node *rn, safi_t safi,
|
||||
struct static_vrf *svrf);
|
||||
|
||||
extern struct static_path *static_add_path(struct route_node *rn,
|
||||
uint8_t distance);
|
||||
extern void static_del_path(struct route_node *rn, struct static_path *pn,
|
||||
safi_t safi, struct static_vrf *svrf);
|
||||
|
||||
extern void static_get_nh_type(static_types stype, char *type, size_t size);
|
||||
extern bool static_add_nexthop_validate(struct static_vrf *svrf,
|
||||
static_types type,
|
||||
struct ipaddr *ipaddr);
|
||||
extern struct stable_info *static_get_stable_info(struct route_node *rn);
|
||||
extern void static_route_info_init(struct static_route_info *si);
|
||||
#endif
|
||||
|
@ -30,26 +30,39 @@
|
||||
#include "static_zebra.h"
|
||||
#include "static_vty.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info");
|
||||
|
||||
static void zebra_stable_node_cleanup(struct route_table *table,
|
||||
struct route_node *node)
|
||||
{
|
||||
struct static_route *si, *next;
|
||||
struct static_nexthop *nh;
|
||||
struct static_path *pn;
|
||||
struct static_route_info *si;
|
||||
|
||||
if (node->info)
|
||||
for (si = node->info; si; si = next) {
|
||||
next = si->next;
|
||||
XFREE(MTYPE_STATIC_ROUTE, si);
|
||||
si = node->info;
|
||||
|
||||
if (si) {
|
||||
frr_each_safe(static_path_list, &si->path_list, pn) {
|
||||
frr_each_safe(static_nexthop_list, &pn->nexthop_list,
|
||||
nh) {
|
||||
static_nexthop_list_del(&pn->nexthop_list, nh);
|
||||
XFREE(MTYPE_STATIC_NEXTHOP, nh);
|
||||
}
|
||||
static_path_list_del(&si->path_list, pn);
|
||||
XFREE(MTYPE_STATIC_PATH, pn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct static_vrf *static_vrf_alloc(void)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct static_vrf *svrf;
|
||||
struct stable_info *info;
|
||||
safi_t safi;
|
||||
afi_t afi;
|
||||
|
||||
svrf = XCALLOC(MTYPE_TMP, sizeof(struct static_vrf));
|
||||
svrf = XCALLOC(MTYPE_STATIC_RTABLE_INFO, sizeof(struct static_vrf));
|
||||
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||
@ -57,6 +70,14 @@ static struct static_vrf *static_vrf_alloc(void)
|
||||
table = srcdest_table_init();
|
||||
else
|
||||
table = route_table_init();
|
||||
|
||||
info = XCALLOC(MTYPE_STATIC_RTABLE_INFO,
|
||||
sizeof(struct stable_info));
|
||||
info->svrf = svrf;
|
||||
info->afi = afi;
|
||||
info->safi = safi;
|
||||
route_table_set_info(table, info);
|
||||
|
||||
table->cleanup = zebra_stable_node_cleanup;
|
||||
svrf->stable[afi][safi] = table;
|
||||
}
|
||||
@ -81,12 +102,6 @@ static int static_vrf_enable(struct vrf *vrf)
|
||||
|
||||
static_fixup_vrf_ids(vrf->info);
|
||||
|
||||
/*
|
||||
* We may have static routes that are now possible to
|
||||
* insert into the appropriate tables
|
||||
*/
|
||||
static_config_install_delayed_routes(vrf->info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -102,16 +117,19 @@ static int static_vrf_delete(struct vrf *vrf)
|
||||
struct static_vrf *svrf;
|
||||
safi_t safi;
|
||||
afi_t afi;
|
||||
void *info;
|
||||
|
||||
svrf = vrf->info;
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||
table = svrf->stable[afi][safi];
|
||||
info = route_table_get_info(table);
|
||||
route_table_finish(table);
|
||||
XFREE(MTYPE_STATIC_RTABLE_INFO, info);
|
||||
svrf->stable[afi][safi] = NULL;
|
||||
}
|
||||
}
|
||||
XFREE(MTYPE_TMP, svrf);
|
||||
XFREE(MTYPE_STATIC_RTABLE_INFO, svrf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -210,3 +228,25 @@ void static_vrf_terminate(void)
|
||||
{
|
||||
vrf_terminate();
|
||||
}
|
||||
|
||||
struct static_vrf *static_vty_get_unknown_vrf(const char *vrf_name)
|
||||
{
|
||||
struct static_vrf *svrf;
|
||||
struct vrf *vrf;
|
||||
|
||||
svrf = static_vrf_lookup_by_name(vrf_name);
|
||||
|
||||
if (svrf)
|
||||
return svrf;
|
||||
|
||||
vrf = vrf_get(VRF_UNKNOWN, vrf_name);
|
||||
if (!vrf)
|
||||
return NULL;
|
||||
svrf = vrf->info;
|
||||
if (!svrf)
|
||||
return NULL;
|
||||
/* Mark as having FRR configuration */
|
||||
vrf_set_user_cfged(vrf);
|
||||
|
||||
return svrf;
|
||||
}
|
||||
|
@ -26,6 +26,14 @@ struct static_vrf {
|
||||
struct route_table *stable[AFI_MAX][SAFI_MAX];
|
||||
};
|
||||
|
||||
struct stable_info {
|
||||
struct static_vrf *svrf;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
};
|
||||
|
||||
#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id
|
||||
|
||||
struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name);
|
||||
struct static_vrf *static_vrf_lookup_by_id(vrf_id_t vrf_id);
|
||||
|
||||
@ -36,4 +44,6 @@ void static_vrf_init(void);
|
||||
struct route_table *static_vrf_static_table(afi_t afi, safi_t safi,
|
||||
struct static_vrf *svrf);
|
||||
extern void static_vrf_terminate(void);
|
||||
|
||||
struct static_vrf *static_vty_get_unknown_vrf(const char *vrf_name);
|
||||
#endif
|
||||
|
1169
staticd/static_vty.c
1169
staticd/static_vty.c
File diff suppressed because it is too large
Load Diff
@ -19,8 +19,6 @@
|
||||
#ifndef __STATIC_VTY_H__
|
||||
#define __STATIC_VTY_H__
|
||||
|
||||
void static_config_install_delayed_routes(struct static_vrf *svrf);
|
||||
|
||||
int static_config(struct vty *vty, struct static_vrf *svrf,
|
||||
afi_t afi, safi_t safi, const char *cmd);
|
||||
|
||||
|
@ -89,7 +89,6 @@ static int static_ifp_up(struct interface *ifp)
|
||||
struct static_vrf *svrf = static_vrf_lookup_by_id(ifp->vrf_id);
|
||||
|
||||
static_fixup_vrf_ids(svrf);
|
||||
static_config_install_delayed_routes(svrf);
|
||||
}
|
||||
|
||||
/* Install any static reliant on this interface coming up */
|
||||
@ -265,8 +264,8 @@ static void static_nht_hash_free(void *data)
|
||||
XFREE(MTYPE_TMP, nhtd);
|
||||
}
|
||||
|
||||
void static_zebra_nht_register(struct route_node *rn,
|
||||
struct static_route *si, bool reg)
|
||||
void static_zebra_nht_register(struct route_node *rn, struct static_nexthop *nh,
|
||||
bool reg)
|
||||
{
|
||||
struct static_nht_data *nhtd, lookup;
|
||||
uint32_t cmd;
|
||||
@ -276,14 +275,14 @@ void static_zebra_nht_register(struct route_node *rn,
|
||||
cmd = (reg) ?
|
||||
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
|
||||
|
||||
if (si->nh_registered && reg)
|
||||
if (nh->nh_registered && reg)
|
||||
return;
|
||||
|
||||
if (!si->nh_registered && !reg)
|
||||
if (!nh->nh_registered && !reg)
|
||||
return;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
switch (si->type) {
|
||||
switch (nh->type) {
|
||||
case STATIC_IFNAME:
|
||||
case STATIC_BLACKHOLE:
|
||||
return;
|
||||
@ -291,23 +290,23 @@ void static_zebra_nht_register(struct route_node *rn,
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = si->addr.ipv4;
|
||||
p.u.prefix4 = nh->addr.ipv4;
|
||||
afi = AFI_IP;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_BITLEN;
|
||||
p.u.prefix6 = si->addr.ipv6;
|
||||
p.u.prefix6 = nh->addr.ipv6;
|
||||
afi = AFI_IP6;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&lookup, 0, sizeof(lookup));
|
||||
lookup.nh = &p;
|
||||
lookup.nh_vrf_id = si->nh_vrf_id;
|
||||
lookup.nh_vrf_id = nh->nh_vrf_id;
|
||||
|
||||
si->nh_registered = reg;
|
||||
nh->nh_registered = reg;
|
||||
|
||||
if (reg) {
|
||||
nhtd = hash_get(static_nht_hash, &lookup,
|
||||
@ -318,8 +317,8 @@ void static_zebra_nht_register(struct route_node *rn,
|
||||
zlog_debug("Registered nexthop(%pFX) for %pRN %d", &p,
|
||||
rn, nhtd->nh_num);
|
||||
if (nhtd->refcount > 1 && nhtd->nh_num) {
|
||||
static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num,
|
||||
afi, si->nh_vrf_id);
|
||||
static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
|
||||
nh->nh_vrf_id);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -335,25 +334,72 @@ void static_zebra_nht_register(struct route_node *rn,
|
||||
static_nht_hash_free(nhtd);
|
||||
}
|
||||
|
||||
if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
|
||||
if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) < 0)
|
||||
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
||||
}
|
||||
/*
|
||||
* When nexthop gets updated via configuration then use the
|
||||
* already registered NH and resend the route to zebra
|
||||
*/
|
||||
int static_zebra_nh_update(struct route_node *rn, struct static_nexthop *nh)
|
||||
{
|
||||
struct static_nht_data *nhtd, lookup = {};
|
||||
struct prefix p = {};
|
||||
afi_t afi = AFI_IP;
|
||||
|
||||
if (!nh->nh_registered)
|
||||
return 0;
|
||||
|
||||
switch (nh->type) {
|
||||
case STATIC_IFNAME:
|
||||
case STATIC_BLACKHOLE:
|
||||
return 0;
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = nh->addr.ipv4;
|
||||
afi = AFI_IP;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_BITLEN;
|
||||
p.u.prefix6 = nh->addr.ipv6;
|
||||
afi = AFI_IP6;
|
||||
break;
|
||||
}
|
||||
|
||||
lookup.nh = &p;
|
||||
lookup.nh_vrf_id = nh->nh_vrf_id;
|
||||
|
||||
nhtd = hash_lookup(static_nht_hash, &lookup);
|
||||
if (nhtd && nhtd->nh_num) {
|
||||
nh->state = STATIC_START;
|
||||
static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
|
||||
nh->nh_vrf_id);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void static_zebra_route_add(struct route_node *rn,
|
||||
struct static_route *si_changed,
|
||||
vrf_id_t vrf_id, safi_t safi, bool install)
|
||||
struct static_path *pn, safi_t safi,
|
||||
bool install)
|
||||
{
|
||||
struct static_route *si = rn->info;
|
||||
struct static_nexthop *nh;
|
||||
const struct prefix *p, *src_pp;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct zapi_route api;
|
||||
uint32_t nh_num = 0;
|
||||
struct stable_info *info;
|
||||
|
||||
p = src_pp = NULL;
|
||||
srcdest_rnode_prefixes(rn, &p, &src_pp);
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = vrf_id;
|
||||
info = static_get_stable_info(rn);
|
||||
api.vrf_id = GET_STABLE_VRF_ID(info);
|
||||
api.type = ZEBRA_ROUTE_STATIC;
|
||||
api.safi = safi;
|
||||
memcpy(&api.prefix, p, sizeof(api.prefix));
|
||||
@ -365,71 +411,65 @@ extern void static_zebra_route_add(struct route_node *rn,
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
if (si_changed->distance) {
|
||||
if (pn->distance) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
|
||||
api.distance = si_changed->distance;
|
||||
api.distance = pn->distance;
|
||||
}
|
||||
if (si_changed->tag) {
|
||||
if (pn->tag) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
||||
api.tag = si_changed->tag;
|
||||
api.tag = pn->tag;
|
||||
}
|
||||
if (si_changed->table_id != 0) {
|
||||
if (pn->table_id != 0) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
|
||||
api.tableid = si_changed->table_id;
|
||||
api.tableid = pn->table_id;
|
||||
}
|
||||
for (/*loaded above*/; si; si = si->next) {
|
||||
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
||||
api_nh = &api.nexthops[nh_num];
|
||||
if (si->nh_vrf_id == VRF_UNKNOWN)
|
||||
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
||||
continue;
|
||||
|
||||
if (si->distance != si_changed->distance)
|
||||
continue;
|
||||
|
||||
if (si->table_id != si_changed->table_id)
|
||||
continue;
|
||||
|
||||
api_nh->vrf_id = si->nh_vrf_id;
|
||||
if (si->onlink)
|
||||
api_nh->vrf_id = nh->nh_vrf_id;
|
||||
if (nh->onlink)
|
||||
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
|
||||
|
||||
si->state = STATIC_SENT_TO_ZEBRA;
|
||||
nh->state = STATIC_SENT_TO_ZEBRA;
|
||||
|
||||
switch (si->type) {
|
||||
switch (nh->type) {
|
||||
case STATIC_IFNAME:
|
||||
if (si->ifindex == IFINDEX_INTERNAL)
|
||||
if (nh->ifindex == IFINDEX_INTERNAL)
|
||||
continue;
|
||||
api_nh->ifindex = si->ifindex;
|
||||
api_nh->ifindex = nh->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
if (!si->nh_valid)
|
||||
if (!nh->nh_valid)
|
||||
continue;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
api_nh->gate = si->addr;
|
||||
api_nh->gate = nh->addr;
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
if (si->ifindex == IFINDEX_INTERNAL)
|
||||
if (nh->ifindex == IFINDEX_INTERNAL)
|
||||
continue;
|
||||
api_nh->ifindex = si->ifindex;
|
||||
api_nh->ifindex = nh->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
api_nh->gate = si->addr;
|
||||
api_nh->gate = nh->addr;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
if (!si->nh_valid)
|
||||
if (!nh->nh_valid)
|
||||
continue;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6;
|
||||
api_nh->gate = si->addr;
|
||||
api_nh->gate = nh->addr;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
if (si->ifindex == IFINDEX_INTERNAL)
|
||||
if (nh->ifindex == IFINDEX_INTERNAL)
|
||||
continue;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
api_nh->ifindex = si->ifindex;
|
||||
api_nh->gate = si->addr;
|
||||
api_nh->ifindex = nh->ifindex;
|
||||
api_nh->gate = nh->addr;
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
switch (si->bh_type) {
|
||||
switch (nh->bh_type) {
|
||||
case STATIC_BLACKHOLE_DROP:
|
||||
case STATIC_BLACKHOLE_NULL:
|
||||
api_nh->bh_type = BLACKHOLE_NULL;
|
||||
@ -440,13 +480,13 @@ extern void static_zebra_route_add(struct route_node *rn,
|
||||
break;
|
||||
}
|
||||
|
||||
if (si->snh_label.num_labels) {
|
||||
if (nh->snh_label.num_labels) {
|
||||
int i;
|
||||
|
||||
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
|
||||
api_nh->label_num = si->snh_label.num_labels;
|
||||
api_nh->label_num = nh->snh_label.num_labels;
|
||||
for (i = 0; i < api_nh->label_num; i++)
|
||||
api_nh->labels[i] = si->snh_label.label[i];
|
||||
api_nh->labels[i] = nh->snh_label.label[i];
|
||||
}
|
||||
nh_num++;
|
||||
}
|
||||
|
@ -22,13 +22,15 @@
|
||||
extern struct thread_master *master;
|
||||
|
||||
extern void static_zebra_nht_register(struct route_node *rn,
|
||||
struct static_route *si, bool reg);
|
||||
struct static_nexthop *nh, bool reg);
|
||||
|
||||
extern void static_zebra_route_add(struct route_node *rn,
|
||||
struct static_route *si_changed,
|
||||
vrf_id_t vrf_id, safi_t safi, bool install);
|
||||
struct static_path *pn, safi_t safi,
|
||||
bool install);
|
||||
extern void static_zebra_init(void);
|
||||
extern void static_zebra_vrf_register(struct vrf *vrf);
|
||||
extern void static_zebra_vrf_unregister(struct vrf *vrf);
|
||||
extern int static_zebra_nh_update(struct route_node *rn,
|
||||
struct static_nexthop *nh);
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,8 @@ staticd_libstatic_a_SOURCES = \
|
||||
staticd/static_zebra.c \
|
||||
staticd/static_vrf.c \
|
||||
staticd/static_vty.c \
|
||||
staticd/static_nb.c \
|
||||
staticd/static_nb_config.c \
|
||||
# end
|
||||
|
||||
noinst_HEADERS += \
|
||||
@ -28,6 +30,7 @@ noinst_HEADERS += \
|
||||
staticd/static_routes.h \
|
||||
staticd/static_vty.h \
|
||||
staticd/static_vrf.h \
|
||||
staticd/static_nb.h \
|
||||
# end
|
||||
|
||||
clippy_scan += \
|
||||
@ -36,3 +39,7 @@ clippy_scan += \
|
||||
|
||||
staticd_staticd_SOURCES = staticd/static_main.c
|
||||
staticd_staticd_LDADD = staticd/libstatic.a lib/libfrr.la $(LIBCAP)
|
||||
|
||||
nodist_staticd_staticd_SOURCES = \
|
||||
yang/frr-staticd.yang.c \
|
||||
# end
|
||||
|
@ -156,7 +156,7 @@ module frr-nexthop {
|
||||
}
|
||||
|
||||
leaf vrf {
|
||||
type frr-vrf:vrf-ref;
|
||||
type string;
|
||||
description
|
||||
"The nexthop vrf name, if different from the route.";
|
||||
}
|
||||
@ -167,7 +167,7 @@ module frr-nexthop {
|
||||
}
|
||||
|
||||
leaf interface {
|
||||
type frr-interface:interface-ref;
|
||||
type string;
|
||||
description
|
||||
"The nexthop egress interface.";
|
||||
}
|
||||
@ -236,7 +236,8 @@ module frr-nexthop {
|
||||
|
||||
grouping nexthop-grouping {
|
||||
list nexthop {
|
||||
key "nh-type gateway interface";
|
||||
key "nh-type vrf gateway interface";
|
||||
min-elements 1;
|
||||
description
|
||||
"A list of nexthop objects.";
|
||||
uses frr-nexthop-attributes;
|
||||
|
@ -72,6 +72,35 @@ module frr-routing {
|
||||
"This identity represents an IPv6 address family.";
|
||||
}
|
||||
|
||||
identity afi-safi-type {
|
||||
description
|
||||
"Base identity type (AFI,SAFI) tuples for RIB";
|
||||
}
|
||||
|
||||
identity ipv4-unicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv4 unicast address family.";
|
||||
}
|
||||
|
||||
identity ipv6-unicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv6 unicast address family.";
|
||||
}
|
||||
|
||||
identity ipv4-multicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv4 multicast address family.";
|
||||
}
|
||||
|
||||
identity ipv6-multicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv6 multicast address family.";
|
||||
}
|
||||
|
||||
identity control-plane-protocol {
|
||||
description
|
||||
"Base identity from which control-plane protocol identities are
|
||||
@ -150,7 +179,7 @@ module frr-routing {
|
||||
instance.";
|
||||
}
|
||||
leaf vrf {
|
||||
type frr-vrf:vrf-ref;
|
||||
type string;
|
||||
description
|
||||
"vrf for control-plane protocol";
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
module frr-staticd {
|
||||
yang-version "1.1";
|
||||
yang-version 1.1;
|
||||
namespace "http://frrouting.org/yang/staticd";
|
||||
|
||||
prefix frr-staticd;
|
||||
|
||||
import frr-routing {
|
||||
prefix "frr-rt";
|
||||
prefix frr-rt;
|
||||
}
|
||||
|
||||
import frr-nexthop {
|
||||
@ -18,11 +17,9 @@ module frr-staticd {
|
||||
|
||||
organization
|
||||
"FRRouting";
|
||||
|
||||
contact
|
||||
"FRR Users List: <mailto:frog@lists.frrouting.org>
|
||||
FRR Development List: <mailto:dev@lists.frrouting.org>";
|
||||
|
||||
description
|
||||
"This module defines a model for managing FRR staticd information.
|
||||
This YANG module augments the ietf-routing with additional
|
||||
@ -58,52 +55,77 @@ module frr-staticd {
|
||||
"Initial revision.";
|
||||
}
|
||||
|
||||
identity static {
|
||||
identity staticd {
|
||||
base frr-rt:routing-protocol;
|
||||
description
|
||||
"'Static' routing pseudo-protocol.";
|
||||
"'Staticd' routing pseudo-protocol.";
|
||||
}
|
||||
|
||||
augment "/frr-rt:routing/frr-rt:control-plane-protocols/"
|
||||
+ "frr-rt:control-plane-protocol" {
|
||||
container staticd {
|
||||
when "../frr-rt:type = 'frr-staticd:static'" {
|
||||
grouping staticd-prefix-attributes {
|
||||
list path-list {
|
||||
key "distance";
|
||||
leaf distance {
|
||||
type frr-rt:administrative-distance;
|
||||
description
|
||||
"This container is only valid for the 'static' routing
|
||||
"Admin distance associated with this route.";
|
||||
}
|
||||
|
||||
leaf tag {
|
||||
type uint32;
|
||||
default "0";
|
||||
description
|
||||
"Route tag";
|
||||
}
|
||||
|
||||
leaf table-id {
|
||||
type uint32;
|
||||
default "0";
|
||||
description
|
||||
"Table-id";
|
||||
}
|
||||
|
||||
uses frr-nexthop:frr-nexthop;
|
||||
}
|
||||
}
|
||||
|
||||
augment "/frr-rt:routing/frr-rt:control-plane-protocols/frr-rt:control-plane-protocol" {
|
||||
container staticd {
|
||||
when "../frr-rt:type = 'frr-staticd:staticd'" {
|
||||
description
|
||||
"This container is only valid for the 'staticd' routing
|
||||
protocol.";
|
||||
}
|
||||
description
|
||||
"Support for a 'static' pseudo-protocol instance
|
||||
consists of a list of routes.";
|
||||
|
||||
list prefix-list {
|
||||
key "destination-prefix";
|
||||
"Support for a 'staticd' pseudo-protocol instance
|
||||
consists of a list of routes.";
|
||||
list route-list {
|
||||
key "prefix afi-safi";
|
||||
description
|
||||
"List of static IP routes.";
|
||||
|
||||
leaf destination-prefix {
|
||||
type inet:ip-address;
|
||||
"List of staticd IP routes.";
|
||||
leaf prefix {
|
||||
type inet:ip-prefix;
|
||||
description
|
||||
"IP destination prefix.";
|
||||
"IP prefix.";
|
||||
}
|
||||
|
||||
leaf distance {
|
||||
type frr-rt:administrative-distance;
|
||||
description
|
||||
"Admin distance associated with this route.";
|
||||
}
|
||||
|
||||
leaf tag {
|
||||
type uint32 {
|
||||
range "1..4294967295";
|
||||
leaf afi-safi {
|
||||
type identityref {
|
||||
base frr-rt:afi-safi-type;
|
||||
}
|
||||
description
|
||||
"Route tag";
|
||||
"AFI-SAFI type.";
|
||||
}
|
||||
container frr-staticd-next-hop {
|
||||
description
|
||||
"Augment static route configuration 'nexthop-list'.";
|
||||
uses frr-nexthop:frr-nexthop;
|
||||
|
||||
uses staticd-prefix-attributes;
|
||||
|
||||
list src-list {
|
||||
key "src-prefix";
|
||||
leaf src-prefix {
|
||||
type inet:ipv6-prefix;
|
||||
description
|
||||
"IPv6 source prefix";
|
||||
}
|
||||
|
||||
uses staticd-prefix-attributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,35 +77,6 @@ module frr-zebra {
|
||||
"Initial revision.";
|
||||
}
|
||||
|
||||
identity afi-safi-type {
|
||||
description
|
||||
"Base identity type (AFI,SAFI) tuples for RIB";
|
||||
}
|
||||
|
||||
identity ipv4-unicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv4 unicast address family.";
|
||||
}
|
||||
|
||||
identity ipv6-unicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv6 unicast address family.";
|
||||
}
|
||||
|
||||
identity ipv4-multicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv4 multicast address family.";
|
||||
}
|
||||
|
||||
identity ipv6-multicast {
|
||||
base afi-safi-type;
|
||||
description
|
||||
"This identity represents the IPv6 multicast address family.";
|
||||
}
|
||||
|
||||
typedef unix-timestamp {
|
||||
type uint32;
|
||||
units "seconds";
|
||||
@ -634,7 +605,7 @@ module frr-zebra {
|
||||
key "afi-safi-name table-id";
|
||||
leaf afi-safi-name {
|
||||
type identityref {
|
||||
base afi-safi-type;
|
||||
base frr-rt:afi-safi-type;
|
||||
}
|
||||
description
|
||||
"AFI, SAFI name.";
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "vrf.h"
|
||||
#include "libfrr.h"
|
||||
#include "routemap.h"
|
||||
#include "routing_nb.h"
|
||||
|
||||
#include "zebra/zebra_router.h"
|
||||
#include "zebra/zebra_errors.h"
|
||||
@ -258,6 +259,7 @@ static const struct frr_yang_module_info *const zebra_yang_modules[] = {
|
||||
&frr_route_map_info,
|
||||
&frr_zebra_info,
|
||||
&frr_vrf_info,
|
||||
&frr_routing_info,
|
||||
};
|
||||
|
||||
FRR_DAEMON_INFO(
|
||||
|
@ -22,40 +22,6 @@
|
||||
#include "libfrr.h"
|
||||
#include "zebra_nb.h"
|
||||
|
||||
const char *zebra_afi_safi_value2identity(afi_t afi, safi_t safi)
|
||||
{
|
||||
if (afi == AFI_IP && safi == SAFI_UNICAST)
|
||||
return "ipv4-unicast";
|
||||
if (afi == AFI_IP6 && safi == SAFI_UNICAST)
|
||||
return "ipv6-unicast";
|
||||
if (afi == AFI_IP && safi == SAFI_MULTICAST)
|
||||
return "ipv4-multicast";
|
||||
if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
|
||||
return "ipv6-multicast";
|
||||
|
||||
return " ";
|
||||
}
|
||||
|
||||
void zebra_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi)
|
||||
{
|
||||
if (strmatch(key, "frr-zebra:ipv4-unicast")) {
|
||||
*afi = AFI_IP;
|
||||
*safi = SAFI_UNICAST;
|
||||
} else if (strmatch(key, "frr-zebra:ipv6-unicast")) {
|
||||
*afi = AFI_IP6;
|
||||
*safi = SAFI_UNICAST;
|
||||
} else if (strmatch(key, "frr-zebra:ipv4-multicast")) {
|
||||
*afi = AFI_IP;
|
||||
*safi = SAFI_MULTICAST;
|
||||
} else if (strmatch(key, "frr-zebra:ipv6-multicast")) {
|
||||
*afi = AFI_IP6;
|
||||
*safi = SAFI_MULTICAST;
|
||||
} else {
|
||||
*afi = AFI_UNSPEC;
|
||||
*safi = SAFI_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
const struct frr_yang_module_info frr_zebra_info = {
|
||||
.name = "frr-zebra",
|
||||
|
@ -26,10 +26,6 @@ extern "C" {
|
||||
|
||||
extern const struct frr_yang_module_info frr_zebra_info;
|
||||
|
||||
/* helper functions */
|
||||
const char *zebra_afi_safi_value2identity(afi_t afi, safi_t safi);
|
||||
void zebra_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi);
|
||||
|
||||
/* prototypes */
|
||||
int get_route_information_rpc(struct nb_cb_rpc_args *args);
|
||||
int get_v6_mroute_info_rpc(struct nb_cb_rpc_args *args);
|
||||
|
@ -1242,7 +1242,7 @@ int lib_vrf_zebra_ribs_rib_create(struct nb_cb_create_args *args)
|
||||
table_id = zvrf->table_id;
|
||||
|
||||
afi_safi_name = yang_dnode_get_string(args->dnode, "./afi-safi-name");
|
||||
zebra_afi_safi_identity2value(afi_safi_name, &afi, &safi);
|
||||
yang_afi_safi_identity2value(afi_safi_name, &afi, &safi);
|
||||
|
||||
zrt = zebra_router_find_zrt(zvrf, table_id, afi, safi);
|
||||
|
||||
|
@ -185,9 +185,8 @@ int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args)
|
||||
|
||||
args->keys->num = 2;
|
||||
|
||||
snprintfrr(args->keys->key[0], sizeof(args->keys->key[0]), "%s:%s",
|
||||
"frr-zebra",
|
||||
zebra_afi_safi_value2identity(zrt->afi, zrt->safi));
|
||||
snprintfrr(args->keys->key[0], sizeof(args->keys->key[0]), "%s",
|
||||
yang_afi_safi_value2identity(zrt->afi, zrt->safi));
|
||||
snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), "%u",
|
||||
zrt->tableid);
|
||||
|
||||
@ -205,7 +204,7 @@ lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args *args)
|
||||
|
||||
zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id);
|
||||
|
||||
zebra_afi_safi_identity2value(args->keys->key[0], &afi, &safi);
|
||||
yang_afi_safi_identity2value(args->keys->key[0], &afi, &safi);
|
||||
table_id = yang_str2uint32(args->keys->key[1]);
|
||||
/* table_id 0 assume vrf's table_id. */
|
||||
if (!table_id)
|
||||
|
Loading…
Reference in New Issue
Block a user