Merge pull request #3548 from opensourcerouting/rip-vrf

rip(ng)d: add VRF support
This commit is contained in:
Donald Sharp 2019-04-04 19:24:14 -04:00 committed by GitHub
commit f61f266a0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 2900 additions and 1714 deletions

View File

@ -1310,8 +1310,8 @@ static int lib_interface_create(enum nb_event event,
return NB_OK;
}
static int lib_interface_delete(enum nb_event event,
const struct lyd_node *dnode)
static int lib_interface_destroy(enum nb_event event,
const struct lyd_node *dnode)
{
struct interface *ifp;
@ -1357,8 +1357,8 @@ static int lib_interface_description_modify(enum nb_event event,
return NB_OK;
}
static int lib_interface_description_delete(enum nb_event event,
const struct lyd_node *dnode)
static int lib_interface_description_destroy(enum nb_event event,
const struct lyd_node *dnode)
{
struct interface *ifp;
@ -1378,13 +1378,13 @@ const struct frr_yang_module_info frr_interface_info = {
{
.xpath = "/frr-interface:lib/interface",
.cbs.create = lib_interface_create,
.cbs.destroy = lib_interface_delete,
.cbs.destroy = lib_interface_destroy,
.cbs.cli_show = cli_show_interface,
},
{
.xpath = "/frr-interface:lib/interface/description",
.cbs.modify = lib_interface_description_modify,
.cbs.destroy = lib_interface_description_delete,
.cbs.destroy = lib_interface_description_destroy,
.cbs.cli_show = cli_show_interface_desc,
},
{

View File

@ -1297,7 +1297,7 @@ DEFPY (show_yang_operational_data,
yang_dnode_free(dnode);
return CMD_WARNING;
}
lyd_validate(&dnode, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, ly_ctx);
lyd_validate(&dnode, LYD_OPT_GET, ly_ctx);
/* Display the data. */
if (lyd_print_mem(&strp, dnode, format,

View File

@ -573,7 +573,7 @@ static int vrf_default_accepts_vrf(int type)
/* Create a socket for the VRF. */
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
char *interfacename)
const char *interfacename)
{
int ret, save_errno, ret2;
@ -944,7 +944,7 @@ vrf_id_t vrf_get_default_id(void)
return VRF_DEFAULT_INTERNAL;
}
int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
int vrf_bind(vrf_id_t vrf_id, int fd, const char *name)
{
int ret = 0;
@ -1003,7 +1003,7 @@ int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
}
int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
char *interfacename)
const char *interfacename)
{
int ret, save_errno, ret2;

View File

@ -220,12 +220,12 @@ extern void vrf_terminate(void);
/* Create a socket serving for the given VRF */
extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
char *name);
const char *name);
extern int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
char *name);
const char *name);
extern int vrf_bind(vrf_id_t vrf_id, int fd, char *name);
extern int vrf_bind(vrf_id_t vrf_id, int fd, const char *name);
/* VRF ioctl operations */
extern int vrf_getaddrinfo(const char *node, const char *service,

View File

@ -610,6 +610,25 @@ struct list *yang_data_list_new(void)
return list;
}
struct yang_data *yang_data_list_find(const struct list *list,
const char *xpath_fmt, ...)
{
char xpath[XPATH_MAXLEN];
struct yang_data *data;
struct listnode *node;
va_list ap;
va_start(ap, xpath_fmt);
vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
va_end(ap);
for (ALL_LIST_ELEMENTS_RO(list, node, data))
if (strmatch(data->xpath, xpath))
return data;
return NULL;
}
static void *ly_dup_cb(const void *priv)
{
/* Make a shallow copy of the priv pointer. */

View File

@ -513,6 +513,21 @@ extern void yang_data_free(struct yang_data *data);
*/
extern struct list *yang_data_list_new(void);
/*
* Find the yang_data structure corresponding to an XPath in a list.
*
* list
* list of yang_data structures to operate on.
*
* xpath_fmt
* XPath to search for (format string).
*
* Returns:
* Pointer to yang_data if found, NULL otherwise.
*/
extern struct yang_data *yang_data_list_find(const struct list *list,
const char *xpath_fmt, ...);
/*
* Create and set up a libyang context (for use by the translator)
*/

View File

@ -39,31 +39,46 @@
*/
DEFPY_NOSH (router_rip,
router_rip_cmd,
"router rip",
"router rip [vrf NAME]",
"Enable a routing process\n"
"Routing Information Protocol (RIP)\n")
"Routing Information Protocol (RIP)\n"
VRF_CMD_HELP_STR)
{
char xpath[XPATH_MAXLEN];
int ret;
nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_CREATE,
NULL);
/* Build RIP instance XPath. */
if (!vrf)
vrf = VRF_DEFAULT_NAME;
snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
vrf);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(RIP_NODE, "/frr-ripd:ripd/instance");
VTY_PUSH_XPATH(RIP_NODE, xpath);
return ret;
}
DEFPY (no_router_rip,
no_router_rip_cmd,
"no router rip",
"no router rip [vrf NAME]",
NO_STR
"Enable a routing process\n"
"Routing Information Protocol (RIP)\n")
"Routing Information Protocol (RIP)\n"
VRF_CMD_HELP_STR)
{
nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_DESTROY,
NULL);
char xpath[XPATH_MAXLEN];
/* Build RIP instance XPath. */
if (!vrf)
vrf = VRF_DEFAULT_NAME;
snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
vrf);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
@ -71,8 +86,15 @@ DEFPY (no_router_rip,
void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
const char *vrf_name;
vrf_name = yang_dnode_get_string(dnode, "./vrf");
vty_out(vty, "!\n");
vty_out(vty, "router rip\n");
vty_out(vty, "router rip");
if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
vty_out(vty, " vrf %s", vrf_name);
vty_out(vty, "\n");
}
/*
@ -902,7 +924,7 @@ DEFPY (no_ip_rip_authentication_string,
"Authentication string\n"
"Authentication string\n")
{
nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
@ -970,12 +992,24 @@ void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
*/
DEFPY (clear_ip_rip,
clear_ip_rip_cmd,
"clear ip rip",
"clear ip rip [vrf WORD]",
CLEAR_STR
IP_STR
"Clear IP RIP database\n")
"Clear IP RIP database\n"
VRF_CMD_HELP_STR)
{
return nb_cli_rpc("/frr-ripd:clear-rip-route", NULL, NULL);
struct list *input;
input = list_new();
if (vrf) {
struct yang_data *yang_vrf;
yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf",
vrf);
listnode_add(input, yang_vrf);
}
return nb_cli_rpc("/frr-ripd:clear-rip-route", input, NULL);
}
void rip_cli_init(void)

View File

@ -50,9 +50,9 @@ DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
static void rip_enable_apply(struct interface *);
static void rip_passive_interface_apply(struct interface *);
static int rip_if_down(struct interface *ifp);
static int rip_enable_if_lookup(const char *ifname);
static int rip_enable_if_lookup(struct rip *rip, const char *ifname);
static int rip_enable_network_lookup2(struct connected *connected);
static void rip_enable_apply_all(void);
static void rip_enable_apply_all(struct rip *rip);
const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_2, "2"},
@ -60,15 +60,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_NONE, "none"},
{0}};
/* RIP enabled network vector. */
vector rip_enable_interface;
/* RIP enabled interface table. */
struct route_table *rip_enable_network;
/* Vector to store passive-interface name. */
vector Vrip_passive_nondefault;
/* Join to the RIP version 2 multicast group. */
static int ipv4_multicast_join(int sock, struct in_addr group,
struct in_addr ifa, ifindex_t ifindex)
@ -208,7 +199,7 @@ static void rip_request_interface(struct interface *ifp)
/* If there is no version configuration in the interface,
use rip's version setting. */
vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send
vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send
: ri->ri_send);
if (vsend & RIPv1)
rip_request_interface_send(ifp, RIPv1);
@ -329,12 +320,11 @@ static int rip_if_ipv4_address_check(struct interface *ifp)
/* Does this address belongs to me ? */
int if_check_address(struct in_addr addr)
int if_check_address(struct rip *rip, struct in_addr addr)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) {
FOR_ALL_INTERFACES (rip->vrf, ifp) {
struct listnode *cnode;
struct connected *connected;
@ -369,13 +359,14 @@ int rip_interface_down(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
rip_interface_sync(ifp);
rip_if_down(ifp);
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface %s index %d flags %llx metric %d mtu %d is down",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu);
"interface %s vrf %u index %d flags %llx metric %d mtu %d is down",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
return 0;
}
@ -395,9 +386,11 @@ int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length,
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface %s index %d flags %#llx metric %d mtu %d is up",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu);
"interface %s vrf %u index %d flags %#llx metric %d mtu %d is up",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
rip_interface_sync(ifp);
/* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp);
@ -418,12 +411,13 @@ int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length,
struct interface *ifp;
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
rip_interface_sync(ifp);
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface add %s index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu);
"interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
/* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp);
@ -456,13 +450,15 @@ int rip_interface_delete(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
rip_interface_sync(ifp);
if (if_is_up(ifp)) {
rip_if_down(ifp);
}
zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu);
zlog_info(
"interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
/* To support pseudo interface do not free interface structure. */
/* if_delete(ifp); */
@ -471,6 +467,28 @@ int rip_interface_delete(int command, struct zclient *zclient,
return 0;
}
/* VRF update for an interface. */
int rip_interface_vrf_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
vrf_id_t new_vrf_id;
ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
&new_vrf_id);
if (!ifp)
return 0;
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
ifp->name, vrf_id, new_vrf_id);
if_update_to_new_vrf(ifp, new_vrf_id);
rip_interface_sync(ifp);
return 0;
}
static void rip_interface_clean(struct rip_interface *ri)
{
ri->enable_network = 0;
@ -483,12 +501,11 @@ static void rip_interface_clean(struct rip_interface *ri)
}
}
void rip_interfaces_clean(void)
void rip_interfaces_clean(struct rip *rip)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_interface_clean(ifp->info);
}
@ -531,20 +548,22 @@ static void rip_interface_reset(struct rip_interface *ri)
int rip_if_down(struct interface *ifp)
{
struct rip *rip;
struct route_node *rp;
struct rip_info *rinfo;
struct rip_interface *ri = NULL;
struct list *list = NULL;
struct listnode *listnode = NULL, *nextnode = NULL;
ri = ifp->info;
rip = ri->rip;
if (rip) {
for (rp = route_top(rip->table); rp; rp = route_next(rp))
if ((list = rp->info) != NULL)
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo))
if (rinfo->nh.ifindex == ifp->ifindex)
rip_ecmp_delete(rinfo);
ri = ifp->info;
rip_ecmp_delete(rip, rinfo);
if (ri->running) {
if (IS_RIP_DEBUG_EVENT)
@ -560,18 +579,10 @@ int rip_if_down(struct interface *ifp)
return 0;
}
/* Needed for stop RIP process. */
void rip_if_down_all(void)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
rip_if_down(ifp);
}
static void rip_apply_address_add(struct connected *ifc)
{
struct rip_interface *ri = ifc->ifp->info;
struct rip *rip = ri->rip;
struct prefix_ipv4 address;
struct nexthop nh;
struct prefix *p;
@ -597,10 +608,11 @@ static void rip_apply_address_add(struct connected *ifc)
/* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */
if ((rip_enable_if_lookup(ifc->ifp->name) >= 0)
if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
|| (rip_enable_network_lookup2(ifc) >= 0))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, &nh, 0, 0, 0);
rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
0);
}
int rip_interface_address_add(int command, struct zclient *zclient,
@ -634,6 +646,8 @@ int rip_interface_address_add(int command, struct zclient *zclient,
static void rip_apply_address_del(struct connected *ifc)
{
struct rip_interface *ri = ifc->ifp->info;
struct rip *rip = ri->rip;
struct prefix_ipv4 address;
struct prefix *p;
@ -651,7 +665,7 @@ static void rip_apply_address_del(struct connected *ifc)
address.prefixlen = p->prefixlen;
apply_mask_ipv4(&address);
rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, ifc->ifp->ifindex);
}
@ -689,10 +703,15 @@ int rip_interface_address_delete(int command, struct zclient *zclient,
* is within the ripng_enable_network table. */
static int rip_enable_network_lookup_if(struct interface *ifp)
{
struct rip_interface *ri = ifp->info;
struct rip *rip = ri->rip;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv4 address;
if (!rip)
return -1;
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
struct prefix *p;
struct route_node *n;
@ -704,7 +723,7 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
address.prefix = p->u.prefix4;
address.prefixlen = IPV4_MAX_BITLEN;
n = route_node_match(rip_enable_network,
n = route_node_match(rip->enable_network,
(struct prefix *)&address);
if (n) {
route_unlock_node(n);
@ -716,8 +735,10 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
}
/* Check wether connected is within the ripng_enable_network table. */
int rip_enable_network_lookup2(struct connected *connected)
static int rip_enable_network_lookup2(struct connected *connected)
{
struct rip_interface *ri = connected->ifp->info;
struct rip *rip = ri->rip;
struct prefix_ipv4 address;
struct prefix *p;
@ -731,8 +752,8 @@ int rip_enable_network_lookup2(struct connected *connected)
address.prefixlen = IPV4_MAX_BITLEN;
/* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
* rip_enable_network */
node = route_node_match(rip_enable_network,
* rip->enable_network */
node = route_node_match(rip->enable_network,
(struct prefix *)&address);
if (node) {
@ -744,11 +765,11 @@ int rip_enable_network_lookup2(struct connected *connected)
return -1;
}
/* Add RIP enable network. */
int rip_enable_network_add(struct prefix *p)
int rip_enable_network_add(struct rip *rip, struct prefix *p)
{
struct route_node *node;
node = route_node_get(rip_enable_network, p);
node = route_node_get(rip->enable_network, p);
if (node->info) {
route_unlock_node(node);
@ -757,17 +778,17 @@ int rip_enable_network_add(struct prefix *p)
node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */
rip_enable_apply_all();
rip_enable_apply_all(rip);
return NB_OK;
}
/* Delete RIP enable network. */
int rip_enable_network_delete(struct prefix *p)
int rip_enable_network_delete(struct rip *rip, struct prefix *p)
{
struct route_node *node;
node = route_node_lookup(rip_enable_network, p);
node = route_node_lookup(rip->enable_network, p);
if (node) {
node->info = NULL;
@ -778,7 +799,7 @@ int rip_enable_network_delete(struct prefix *p)
route_unlock_node(node);
/* XXX: One should find a better solution than a generic one */
rip_enable_apply_all();
rip_enable_apply_all(rip);
return NB_OK;
}
@ -787,50 +808,53 @@ int rip_enable_network_delete(struct prefix *p)
}
/* Check interface is enabled by ifname statement. */
static int rip_enable_if_lookup(const char *ifname)
static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
{
unsigned int i;
char *str;
for (i = 0; i < vector_active(rip_enable_interface); i++)
if ((str = vector_slot(rip_enable_interface, i)) != NULL)
if (!rip)
return -1;
for (i = 0; i < vector_active(rip->enable_interface); i++)
if ((str = vector_slot(rip->enable_interface, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
}
/* Add interface to rip_enable_if. */
int rip_enable_if_add(const char *ifname)
int rip_enable_if_add(struct rip *rip, const char *ifname)
{
int ret;
ret = rip_enable_if_lookup(ifname);
ret = rip_enable_if_lookup(rip, ifname);
if (ret >= 0)
return NB_ERR_INCONSISTENCY;
vector_set(rip_enable_interface,
vector_set(rip->enable_interface,
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
rip_enable_apply_all(); /* TODOVJ */
rip_enable_apply_all(rip); /* TODOVJ */
return NB_OK;
}
/* Delete interface from rip_enable_if. */
int rip_enable_if_delete(const char *ifname)
int rip_enable_if_delete(struct rip *rip, const char *ifname)
{
int index;
char *str;
index = rip_enable_if_lookup(ifname);
index = rip_enable_if_lookup(rip, ifname);
if (index < 0)
return NB_ERR_INCONSISTENCY;
str = vector_slot(rip_enable_interface, index);
str = vector_slot(rip->enable_interface, index);
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
vector_unset(rip_enable_interface, index);
vector_unset(rip->enable_interface, index);
rip_enable_apply_all(); /* TODOVJ */
rip_enable_apply_all(rip); /* TODOVJ */
return NB_OK;
}
@ -848,7 +872,7 @@ static int rip_interface_wakeup(struct thread *t)
ri->t_wakeup = NULL;
/* Join to multicast group. */
if (rip_multicast_join(ifp, rip->sock) < 0) {
if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"multicast join failed, interface %s not running",
ifp->name);
@ -866,6 +890,8 @@ static int rip_interface_wakeup(struct thread *t)
static void rip_connect_set(struct interface *ifp, int set)
{
struct rip_interface *ri = ifp->info;
struct rip *rip = ri->rip;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv4 address;
@ -890,17 +916,18 @@ static void rip_connect_set(struct interface *ifp, int set)
if (set) {
/* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */
if ((rip_enable_if_lookup(connected->ifp->name) >= 0)
if ((rip_enable_if_lookup(rip, connected->ifp->name)
>= 0)
|| (rip_enable_network_lookup2(connected) >= 0))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT,
rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE,
&address, &nh, 0, 0, 0);
} else {
rip_redistribute_delete(ZEBRA_ROUTE_CONNECT,
rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, &address,
connected->ifp->ifindex);
if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT,
if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_REDISTRIBUTE,
&address, &nh, 0, 0, 0);
}
@ -929,7 +956,7 @@ void rip_enable_apply(struct interface *ifp)
ri->enable_network = 0;
/* Check interface name configuration. */
ret = rip_enable_if_lookup(ifp->name);
ret = rip_enable_if_lookup(ri->rip, ifp->name);
if (ret >= 0)
ri->enable_interface = 1;
else
@ -962,17 +989,16 @@ void rip_enable_apply(struct interface *ifp)
}
/* Apply network configuration to all interface. */
void rip_enable_apply_all(void)
static void rip_enable_apply_all(struct rip *rip)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
/* Check each interface. */
FOR_ALL_INTERFACES (vrf, ifp)
FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_enable_apply(ifp);
}
int rip_neighbor_lookup(struct sockaddr_in *from)
int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
{
struct prefix_ipv4 p;
struct route_node *node;
@ -991,7 +1017,7 @@ int rip_neighbor_lookup(struct sockaddr_in *from)
}
/* Add new RIP neighbor to the neighbor tree. */
int rip_neighbor_add(struct prefix_ipv4 *p)
int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
{
struct route_node *node;
@ -1006,7 +1032,7 @@ int rip_neighbor_add(struct prefix_ipv4 *p)
}
/* Delete RIP neighbor from the neighbor tree. */
int rip_neighbor_delete(struct prefix_ipv4 *p)
int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
{
struct route_node *node;
@ -1027,50 +1053,51 @@ int rip_neighbor_delete(struct prefix_ipv4 *p)
}
/* Clear all network and neighbor configuration. */
void rip_clean_network(void)
void rip_clean_network(struct rip *rip)
{
unsigned int i;
char *str;
struct route_node *rn;
/* rip_enable_network. */
for (rn = route_top(rip_enable_network); rn; rn = route_next(rn))
/* rip->enable_network. */
for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
if (rn->info) {
rn->info = NULL;
route_unlock_node(rn);
}
/* rip_enable_interface. */
for (i = 0; i < vector_active(rip_enable_interface); i++)
if ((str = vector_slot(rip_enable_interface, i)) != NULL) {
/* rip->enable_interface. */
for (i = 0; i < vector_active(rip->enable_interface); i++)
if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
vector_slot(rip_enable_interface, i) = NULL;
vector_slot(rip->enable_interface, i) = NULL;
}
}
/* Utility function for looking up passive interface settings. */
static int rip_passive_nondefault_lookup(const char *ifname)
static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
{
unsigned int i;
char *str;
for (i = 0; i < vector_active(Vrip_passive_nondefault); i++)
if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL)
for (i = 0; i < vector_active(rip->passive_nondefault); i++)
if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
}
void rip_passive_interface_apply(struct interface *ifp)
static void rip_passive_interface_apply(struct interface *ifp)
{
struct rip *rip;
struct rip_interface *ri;
ri = ifp->info;
rip = ri->rip;
if (rip == NULL)
return;
ri = ifp->info;
ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0)
ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
? rip->passive_default
: !rip->passive_default);
@ -1079,39 +1106,38 @@ void rip_passive_interface_apply(struct interface *ifp)
ri->passive);
}
static void rip_passive_interface_apply_all(void)
static void rip_passive_interface_apply_all(struct rip *rip)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_passive_interface_apply(ifp);
}
/* Passive interface. */
int rip_passive_nondefault_set(const char *ifname)
int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
{
if (rip_passive_nondefault_lookup(ifname) >= 0)
if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
/*
* Don't return an error, this can happen after changing
* 'passive-default'.
*/
return NB_OK;
vector_set(Vrip_passive_nondefault,
vector_set(rip->passive_nondefault,
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
rip_passive_interface_apply_all();
rip_passive_interface_apply_all(rip);
return NB_OK;
}
int rip_passive_nondefault_unset(const char *ifname)
int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
{
int i;
char *str;
i = rip_passive_nondefault_lookup(ifname);
i = rip_passive_nondefault_lookup(rip, ifname);
if (i < 0)
/*
* Don't return an error, this can happen after changing
@ -1119,61 +1145,64 @@ int rip_passive_nondefault_unset(const char *ifname)
*/
return NB_OK;
str = vector_slot(Vrip_passive_nondefault, i);
str = vector_slot(rip->passive_nondefault, i);
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
vector_unset(Vrip_passive_nondefault, i);
vector_unset(rip->passive_nondefault, i);
rip_passive_interface_apply_all();
rip_passive_interface_apply_all(rip);
return NB_OK;
}
/* Free all configured RIP passive-interface settings. */
void rip_passive_nondefault_clean(void)
void rip_passive_nondefault_clean(struct rip *rip)
{
unsigned int i;
char *str;
for (i = 0; i < vector_active(Vrip_passive_nondefault); i++)
if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) {
for (i = 0; i < vector_active(rip->passive_nondefault); i++)
if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
vector_slot(Vrip_passive_nondefault, i) = NULL;
vector_slot(rip->passive_nondefault, i) = NULL;
}
rip_passive_interface_apply_all();
rip_passive_interface_apply_all(rip);
}
/* Write rip configuration of each interface. */
static int rip_interface_config_write(struct vty *vty)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct vrf *vrf;
int write = 0;
FOR_ALL_INTERFACES (vrf, ifp) {
struct lyd_node *dnode;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
struct interface *ifp;
dnode = yang_dnode_get(
running_config->dnode,
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
ifp->name, vrf->name);
if (dnode == NULL)
continue;
FOR_ALL_INTERFACES (vrf, ifp) {
struct lyd_node *dnode;
write = 1;
nb_cli_show_dnode_cmds(vty, dnode, false);
dnode = yang_dnode_get(
running_config->dnode,
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
ifp->name, vrf->name);
if (dnode == NULL)
continue;
write = 1;
nb_cli_show_dnode_cmds(vty, dnode, false);
}
}
return write;
}
int rip_show_network_config(struct vty *vty)
int rip_show_network_config(struct vty *vty, struct rip *rip)
{
unsigned int i;
char *ifname;
struct route_node *node;
/* Network type RIP enable interface statement. */
for (node = route_top(rip_enable_network); node;
for (node = route_top(rip->enable_network); node;
node = route_next(node))
if (node->info)
vty_out(vty, " %s/%u\n",
@ -1181,8 +1210,8 @@ int rip_show_network_config(struct vty *vty)
node->p.prefixlen);
/* Interface name RIP enable statement. */
for (i = 0; i < vector_active(rip_enable_interface); i++)
if ((ifname = vector_slot(rip_enable_interface, i)) != NULL)
for (i = 0; i < vector_active(rip->enable_interface); i++)
if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
vty_out(vty, " %s\n", ifname);
/* RIP neighbors listing. */
@ -1197,10 +1226,26 @@ static struct cmd_node interface_node = {
INTERFACE_NODE, "%s(config-if)# ", 1,
};
void rip_interface_sync(struct interface *ifp)
{
struct vrf *vrf;
vrf = vrf_lookup_by_id(ifp->vrf_id);
if (vrf) {
struct rip_interface *ri;
ri = ifp->info;
if (ri)
ri->rip = vrf->info;
}
}
/* Called when interface structure allocated. */
static int rip_interface_new_hook(struct interface *ifp)
{
ifp->info = rip_interface_new();
rip_interface_sync(ifp);
return 0;
}
@ -1220,13 +1265,6 @@ void rip_if_init(void)
hook_register_prio(if_add, 0, rip_interface_new_hook);
hook_register_prio(if_del, 0, rip_interface_delete_hook);
/* RIP network init. */
rip_enable_interface = vector_init(1);
rip_enable_network = route_table_init();
/* RIP passive interface. */
Vrip_passive_nondefault = vector_init(1);
/* Install interface node. */
install_node(&interface_node, rip_interface_config_write);
if_cmd_init();

View File

@ -20,6 +20,8 @@
#ifndef _QUAGGA_RIP_INTERFACE_H
#define _QUAGGA_RIP_INTERFACE_H
#include "zclient.h"
extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t);
extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t);
extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t);
@ -28,5 +30,8 @@ extern int rip_interface_address_add(int, struct zclient *, zebra_size_t,
vrf_id_t);
extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t,
vrf_id_t);
extern int rip_interface_vrf_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id);
extern void rip_interface_sync(struct interface *ifp);
#endif /* _QUAGGA_RIP_INTERFACE_H */

View File

@ -34,6 +34,7 @@
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
#include "if_rmap.h"
#include "libfrr.h"
#include "ripd/ripd.h"
@ -46,7 +47,7 @@
static struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
/* ripd privileges */
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
struct zebra_privs_t ripd_privs = {
#if defined(FRR_USER)
@ -59,7 +60,7 @@ struct zebra_privs_t ripd_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = 2,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
/* Master of threads. */
@ -81,8 +82,8 @@ static void sigint(void)
{
zlog_notice("Terminating on signal");
rip_clean();
rip_vrf_terminate();
if_rmap_terminate();
rip_zclient_stop();
frr_fini();
@ -171,14 +172,13 @@ int main(int argc, char **argv)
/* Library initialization. */
rip_error_init();
keychain_init();
vrf_init(NULL, NULL, NULL, NULL, NULL);
rip_vrf_init();
/* RIP related initialization. */
rip_init();
rip_if_init();
rip_cli_init();
rip_zclient_init(master);
rip_peer_init();
frr_config_fork();
frr_run(master);

View File

@ -27,6 +27,7 @@
DEFINE_MGROUP(RIPD, "ripd")
DEFINE_MTYPE(RIPD, RIP, "RIP structure")
DEFINE_MTYPE(RIPD, RIP_VRF_NAME, "RIP VRF name")
DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info")
DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface")
DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String")

View File

@ -26,6 +26,7 @@
DECLARE_MGROUP(RIPD)
DECLARE_MTYPE(RIP)
DECLARE_MTYPE(RIP_VRF_NAME)
DECLARE_MTYPE(RIP_INFO)
DECLARE_MTYPE(RIP_INTERFACE)
DECLARE_MTYPE(RIP_INTERFACE_STRING)

File diff suppressed because it is too large Load Diff

View File

@ -29,28 +29,27 @@
#include "ripd/ripd.h"
static struct list *rip_offset_list_master;
#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric)
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
struct rip_offset_list *rip_offset_list_new(const char *ifname)
struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname)
{
struct rip_offset_list *offset;
offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list));
offset->rip = rip;
offset->ifname = strdup(ifname);
listnode_add_sort(rip_offset_list_master, offset);
listnode_add_sort(rip->offset_list_master, offset);
return offset;
}
void offset_list_del(struct rip_offset_list *offset)
{
listnode_delete(rip_offset_list_master, offset);
listnode_delete(offset->rip->offset_list_master, offset);
if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_NAME(offset))
@ -59,12 +58,13 @@ void offset_list_del(struct rip_offset_list *offset)
XFREE(MTYPE_RIP_OFFSET_LIST, offset);
}
struct rip_offset_list *rip_offset_list_lookup(const char *ifname)
struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
const char *ifname)
{
struct rip_offset_list *offset;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) {
for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) {
if (strcmp(offset->ifname, ifname) == 0)
return offset;
}
@ -75,11 +75,12 @@ struct rip_offset_list *rip_offset_list_lookup(const char *ifname)
int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric)
{
struct rip_interface *ri = ifp->info;
struct rip_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
offset = rip_offset_list_lookup(ifp->name);
offset = rip_offset_list_lookup(ri->rip, ifp->name);
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
@ -92,7 +93,7 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
return 0;
}
/* Look up offset-list without interface name. */
offset = rip_offset_list_lookup("*");
offset = rip_offset_list_lookup(ri->rip, "*");
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
@ -111,11 +112,12 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric)
{
struct rip_interface *ri = ifp->info;
struct rip_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
offset = rip_offset_list_lookup(ifp->name);
offset = rip_offset_list_lookup(ri->rip, ifp->name);
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP,
OFFSET_LIST_OUT_NAME(offset));
@ -130,7 +132,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
}
/* Look up offset-list without interface name. */
offset = rip_offset_list_lookup("*");
offset = rip_offset_list_lookup(ri->rip, "*");
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP,
OFFSET_LIST_OUT_NAME(offset));
@ -146,24 +148,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
return 0;
}
static int offset_list_cmp(struct rip_offset_list *o1,
struct rip_offset_list *o2)
int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2)
{
return strcmp(o1->ifname, o2->ifname);
}
void rip_offset_init(void)
{
rip_offset_list_master = list_new();
rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
rip_offset_list_master->del = (void (*)(void *))offset_list_del;
}
void rip_offset_clean(void)
{
list_delete(&rip_offset_list_master);
rip_offset_list_master = list_new();
rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
rip_offset_list_master->del = (void (*)(void *))offset_list_del;
}

View File

@ -29,9 +29,6 @@
#include "ripd/ripd.h"
/* Linked list of RIP peer. */
struct list *peer_list;
static struct rip_peer *rip_peer_new(void)
{
return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer));
@ -39,27 +36,28 @@ static struct rip_peer *rip_peer_new(void)
static void rip_peer_free(struct rip_peer *peer)
{
RIP_TIMER_OFF(peer->t_timeout);
XFREE(MTYPE_RIP_PEER, peer);
}
struct rip_peer *rip_peer_lookup(struct in_addr *addr)
struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr)
{
struct rip_peer *peer;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
if (IPV4_ADDR_SAME(&peer->addr, addr))
return peer;
}
return NULL;
}
struct rip_peer *rip_peer_lookup_next(struct in_addr *addr)
struct rip_peer *rip_peer_lookup_next(struct rip *rip, struct in_addr *addr)
{
struct rip_peer *peer;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
if (htonl(peer->addr.s_addr) > htonl(addr->s_addr))
return peer;
}
@ -72,26 +70,27 @@ static int rip_peer_timeout(struct thread *t)
struct rip_peer *peer;
peer = THREAD_ARG(t);
listnode_delete(peer_list, peer);
listnode_delete(peer->rip->peer_list, peer);
rip_peer_free(peer);
return 0;
}
/* Get RIP peer. At the same time update timeout thread. */
static struct rip_peer *rip_peer_get(struct in_addr *addr)
static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr)
{
struct rip_peer *peer;
peer = rip_peer_lookup(addr);
peer = rip_peer_lookup(rip, addr);
if (peer) {
if (peer->t_timeout)
thread_cancel(peer->t_timeout);
} else {
peer = rip_peer_new();
peer->rip = rip;
peer->addr = *addr;
listnode_add_sort(peer_list, peer);
listnode_add_sort(rip->peer_list, peer);
}
/* Update timeout thread. */
@ -105,24 +104,24 @@ static struct rip_peer *rip_peer_get(struct in_addr *addr)
return peer;
}
void rip_peer_update(struct sockaddr_in *from, uint8_t version)
void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version)
{
struct rip_peer *peer;
peer = rip_peer_get(&from->sin_addr);
peer = rip_peer_get(rip, &from->sin_addr);
peer->version = version;
}
void rip_peer_bad_route(struct sockaddr_in *from)
void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from)
{
struct rip_peer *peer;
peer = rip_peer_get(&from->sin_addr);
peer = rip_peer_get(rip, &from->sin_addr);
peer->recv_badroutes++;
}
void rip_peer_bad_packet(struct sockaddr_in *from)
void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from)
{
struct rip_peer *peer;
peer = rip_peer_get(&from->sin_addr);
peer = rip_peer_get(rip, &from->sin_addr);
peer->recv_badpackets++;
}
@ -155,14 +154,14 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
return buf;
}
void rip_peer_display(struct vty *vty)
void rip_peer_display(struct vty *vty, struct rip *rip)
{
struct rip_peer *peer;
struct listnode *node, *nnode;
#define RIP_UPTIME_LEN 25
char timebuf[RIP_UPTIME_LEN];
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
vty_out(vty, " %-16s %9d %9d %9d %s\n",
inet_ntoa(peer->addr), peer->recv_badpackets,
peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT,
@ -170,7 +169,7 @@ void rip_peer_display(struct vty *vty)
}
}
static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
{
if (p2->addr.s_addr == p1->addr.s_addr)
return 0;
@ -178,8 +177,7 @@ static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1;
}
void rip_peer_init(void)
void rip_peer_list_del(void *arg)
{
peer_list = list_new();
peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
rip_peer_free(arg);
}

View File

@ -156,17 +156,23 @@ static uint8_t *rip2Globals(struct variable *v, oid name[], size_t *length,
int exact, size_t *var_len,
WriteMethod **write_method)
{
struct rip *rip;
if (smux_header_generic(v, name, length, exact, var_len, write_method)
== MATCH_FAILED)
return NULL;
rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (!rip)
return NULL;
/* Retrun global counter. */
switch (v->magic) {
case RIP2GLOBALROUTECHANGES:
return SNMP_INTEGER(rip_global_route_changes);
return SNMP_INTEGER(rip->counters.route_changes);
break;
case RIP2GLOBALQUERIES:
return SNMP_INTEGER(rip_global_queries);
return SNMP_INTEGER(rip->counters.queries);
break;
default:
return NULL;
@ -281,9 +287,14 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
size_t *length, struct in_addr *addr,
int exact)
{
struct rip *rip;
int len;
struct rip_peer *peer;
rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (!rip)
return NULL;
if (exact) {
/* Check the length. */
if (*length - v->namelen != sizeof(struct in_addr) + 1)
@ -291,7 +302,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr);
peer = rip_peer_lookup(addr);
peer = rip_peer_lookup(rip, addr);
if (peer->domain
== (int)name[v->namelen + sizeof(struct in_addr)])
@ -306,7 +317,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
oid2in_addr(name + v->namelen, len, addr);
len = *length - v->namelen;
peer = rip_peer_lookup(addr);
peer = rip_peer_lookup(rip, addr);
if (peer) {
if ((len < (int)sizeof(struct in_addr) + 1)
|| (peer->domain
@ -321,7 +332,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
return peer;
}
}
peer = rip_peer_lookup_next(addr);
peer = rip_peer_lookup_next(rip, addr);
if (!peer)
return NULL;
@ -402,10 +413,10 @@ static long rip2IfConfSend(struct rip_interface *ri)
return ripVersion2;
else if (ri->ri_send & RIPv1)
return ripVersion1;
else if (rip) {
if (rip->version_send == RIPv2)
else if (ri->rip) {
if (ri->rip->version_send == RIPv2)
return ripVersion2;
else if (rip->version_send == RIPv1)
else if (ri->rip->version_send == RIPv1)
return ripVersion1;
}
return doNotSend;
@ -423,7 +434,7 @@ static long rip2IfConfReceive(struct rip_interface *ri)
if (!ri->running)
return doNotReceive;
recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv
recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? ri->rip->version_recv
: ri->ri_receive;
if (recvv == RI_RIP_VERSION_1_AND_2)
return rip1OrRip2;

View File

@ -36,7 +36,8 @@
struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */
static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp,
uint8_t cmd)
{
struct list *list = (struct list *)rp->info;
struct zapi_route api;
@ -46,7 +47,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
int count = 0;
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.vrf_id = rip->vrf->vrf_id;
api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST;
@ -55,7 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
api_nh->vrf_id = VRF_DEFAULT;
api_nh->vrf_id = rip->vrf->vrf_id;
api_nh->gate = rinfo->nh.gate;
api_nh->type = NEXTHOP_TYPE_IPV4;
if (cmd == ZEBRA_ROUTE_ADD)
@ -101,28 +102,30 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
}
rip_global_route_changes++;
rip->counters.route_changes++;
}
/* Add/update ECMP routes to zebra. */
void rip_zebra_ipv4_add(struct route_node *rp)
void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp)
{
rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD);
}
/* Delete ECMP routes from zebra. */
void rip_zebra_ipv4_delete(struct route_node *rp)
void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp)
{
rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE);
}
/* Zebra route add and delete treatment. */
static int rip_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct rip *rip;
struct zapi_route api;
struct nexthop nh;
rip = rip_lookup_by_vrf_id(vrf_id);
if (!rip)
return 0;
@ -136,68 +139,95 @@ static int rip_zebra_read_route(int command, struct zclient *zclient,
/* Then fetch IPv4 prefixes. */
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix, &nh,
api.metric, api.distance, api.tag);
else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix,
nh.ifindex);
return 0;
}
void rip_redistribute_conf_update(int type)
void rip_redistribute_conf_update(struct rip *rip, int type)
{
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
0, VRF_DEFAULT);
0, rip->vrf->vrf_id);
}
void rip_redistribute_conf_delete(int type)
void rip_redistribute_conf_delete(struct rip *rip, int type)
{
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
AFI_IP, type, 0, VRF_DEFAULT);
AFI_IP, type, 0, rip->vrf->vrf_id);
/* Remove the routes from RIP table. */
rip_redistribute_withdraw(type);
rip_redistribute_withdraw(rip, type);
}
int rip_redistribute_check(int type)
int rip_redistribute_check(struct rip *rip, int type)
{
return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT);
return rip->redist[type].enabled;
}
void rip_redistribute_clean(void)
void rip_redistribute_enable(struct rip *rip)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], VRF_DEFAULT))
if (!rip_redistribute_check(rip, i))
continue;
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
zclient, AFI_IP, i, 0,
VRF_DEFAULT);
vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT);
/* Remove the routes from RIP table. */
rip_redistribute_withdraw(i);
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
i, 0, rip->vrf->vrf_id);
}
}
void rip_show_redistribute_config(struct vty *vty)
void rip_redistribute_disable(struct rip *rip)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!rip_redistribute_check(rip, i))
continue;
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
AFI_IP, i, 0, rip->vrf->vrf_id);
}
}
void rip_show_redistribute_config(struct vty *vty, struct rip *rip)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default
|| !vrf_bitmap_check(zclient->redist[AFI_IP][i],
VRF_DEFAULT))
|| !rip_redistribute_check(rip, i))
continue;
vty_out(vty, " %s", zebra_route_string(i));
}
}
void rip_zebra_vrf_register(struct vrf *vrf)
{
if (vrf->vrf_id == VRF_DEFAULT)
return;
if (IS_RIP_DEBUG_EVENT)
zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
vrf->name, vrf->vrf_id);
zclient_send_reg_requests(zclient, vrf->vrf_id);
}
void rip_zebra_vrf_deregister(struct vrf *vrf)
{
if (vrf->vrf_id == VRF_DEFAULT)
return;
if (IS_RIP_DEBUG_EVENT)
zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
vrf->name, vrf->vrf_id);
zclient_send_dereg_requests(zclient, vrf->vrf_id);
}
static void rip_zebra_connected(struct zclient *zclient)
{
zclient_send_reg_requests(zclient, VRF_DEFAULT);
@ -215,6 +245,7 @@ void rip_zclient_init(struct thread_master *master)
zclient->interface_address_delete = rip_interface_address_delete;
zclient->interface_up = rip_interface_up;
zclient->interface_down = rip_interface_down;
zclient->interface_vrf_update = rip_interface_vrf_update;
zclient->redistribute_route_add = rip_zebra_read_route;
zclient->redistribute_route_del = rip_zebra_read_route;
}

File diff suppressed because it is too large Load Diff

View File

@ -99,6 +99,17 @@
/* RIP structure. */
struct rip {
RB_ENTRY(rip) entry;
/* VRF this routing instance is associated with. */
char *vrf_name;
/* VRF backpointer (might be NULL if the VRF doesn't exist). */
struct vrf *vrf;
/* Status of the routing instance. */
bool enabled;
/* RIP socket. */
int sock;
@ -112,9 +123,12 @@ struct rip {
/* RIP routing information base. */
struct route_table *table;
/* RIP neighbor. */
/* RIP static neighbors. */
struct route_table *neighbor;
/* Linked list of RIP peers. */
struct list *peer_list;
/* RIP threads. */
struct thread *t_read;
@ -144,20 +158,46 @@ struct rip {
/* Are we in passive-interface default mode? */
bool passive_default;
/* For redistribute route map. */
/* RIP enabled interfaces. */
vector enable_interface;
/* RIP enabled networks. */
struct route_table *enable_network;
/* Vector to store passive-interface name. */
vector passive_nondefault;
/* RIP offset-lists. */
struct list *offset_list_master;
/* RIP redistribute configuration. */
struct {
char *name;
struct route_map *map;
bool enabled;
struct {
char *name;
struct route_map *map;
} route_map;
bool metric_config;
uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX];
} redist[ZEBRA_ROUTE_MAX];
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
/* For if_rmap container */
struct if_rmap_ctx *if_rmap_ctx;
/* Counters for SNMP. */
struct {
/* RIP route changes. */
long route_changes;
/* RIP queries. */
long queries;
} counters;
};
RB_HEAD(rip_instance_head, rip);
RB_PROTOTYPE(rip_instance_head, rip, entry, rip_instance_compare)
/* RIP routing table entry which belong to rip_packet. */
struct rte {
@ -225,11 +265,6 @@ struct rip_info {
struct route_node *rp;
uint8_t distance;
#ifdef NEW_RIP_TABLE
struct rip_info *next;
struct rip_info *prev;
#endif /* NEW_RIP_TABLE */
};
typedef enum {
@ -240,6 +275,9 @@ typedef enum {
/* RIP specific interface configuration. */
struct rip_interface {
/* Parent routing instance. */
struct rip *rip;
/* RIP is enabled on this interface. */
int enable_network;
int enable_interface;
@ -297,6 +335,9 @@ struct rip_interface {
/* RIP peer information. */
struct rip_peer {
/* Parent routing instance. */
struct rip *rip;
/* Peer address. */
struct in_addr addr;
@ -369,6 +410,9 @@ enum rip_event {
#define RIP_OFFSET_LIST_MAX 2
struct rip_offset_list {
/* Parent routing instance. */
struct rip *rip;
char *ifname;
struct {
@ -380,104 +424,114 @@ struct rip_offset_list {
/* Prototypes. */
extern void rip_init(void);
extern void rip_clean(void);
extern void rip_clean_network(void);
extern void rip_interfaces_clean(void);
extern int rip_passive_nondefault_set(const char *ifname);
extern int rip_passive_nondefault_unset(const char *ifname);
extern void rip_passive_nondefault_clean(void);
extern void rip_clean(struct rip *rip);
extern void rip_clean_network(struct rip *rip);
extern void rip_interfaces_clean(struct rip *rip);
extern int rip_passive_nondefault_set(struct rip *rip, const char *ifname);
extern int rip_passive_nondefault_unset(struct rip *rip, const char *ifname);
extern void rip_passive_nondefault_clean(struct rip *rip);
extern void rip_if_init(void);
extern void rip_if_down_all(void);
extern void rip_route_map_init(void);
extern void rip_zebra_vrf_register(struct vrf *vrf);
extern void rip_zebra_vrf_deregister(struct vrf *vrf);
extern void rip_zclient_init(struct thread_master *);
extern void rip_zclient_stop(void);
extern int if_check_address(struct in_addr addr);
extern int rip_create(int socket);
extern int if_check_address(struct rip *rip, struct in_addr addr);
extern struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id);
extern struct rip *rip_lookup_by_vrf_name(const char *vrf_name);
extern struct rip *rip_create(const char *vrf_name, struct vrf *vrf,
int socket);
extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
struct connected *);
extern int rip_neighbor_lookup(struct sockaddr_in *);
extern int rip_neighbor_add(struct prefix_ipv4 *p);
extern int rip_neighbor_delete(struct prefix_ipv4 *p);
extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from);
extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p);
extern int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p);
extern int rip_enable_network_add(struct prefix *p);
extern int rip_enable_network_delete(struct prefix *p);
extern int rip_enable_if_add(const char *ifname);
extern int rip_enable_if_delete(const char *ifname);
extern int rip_enable_network_add(struct rip *rip, struct prefix *p);
extern int rip_enable_network_delete(struct rip *rip, struct prefix *p);
extern int rip_enable_if_add(struct rip *rip, const char *ifname);
extern int rip_enable_if_delete(struct rip *rip, const char *ifname);
extern void rip_event(enum rip_event, int);
extern void rip_ecmp_disable(void);
extern void rip_event(struct rip *rip, enum rip_event event, int sock);
extern void rip_ecmp_disable(struct rip *rip);
extern int rip_create_socket(void);
extern int rip_create_socket(struct vrf *vrf);
extern int rip_redistribute_check(int);
extern void rip_redistribute_conf_update(int type);
extern void rip_redistribute_conf_delete(int type);
extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
struct nexthop *nh, unsigned int metric,
unsigned char distance, route_tag_t tag);
extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t);
extern void rip_redistribute_withdraw(int);
extern void rip_zebra_ipv4_add(struct route_node *);
extern void rip_zebra_ipv4_delete(struct route_node *);
extern int rip_redistribute_check(struct rip *rip, int type);
extern void rip_redistribute_conf_update(struct rip *rip, int type);
extern void rip_redistribute_conf_delete(struct rip *rip, int type);
extern void rip_redistribute_add(struct rip *rip, int type, int sub_type,
struct prefix_ipv4 *p, struct nexthop *nh,
unsigned int metric, unsigned char distance,
route_tag_t tag);
extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
struct prefix_ipv4 *p, ifindex_t ifindex);
extern void rip_redistribute_withdraw(struct rip *rip, int type);
extern void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp);
extern void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp);
extern void rip_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *);
extern void rip_if_rmap_update_interface(struct interface *ifp);
extern int rip_show_network_config(struct vty *);
extern void rip_show_redistribute_config(struct vty *);
extern void rip_peer_init(void);
extern void rip_peer_update(struct sockaddr_in *, uint8_t);
extern void rip_peer_bad_route(struct sockaddr_in *);
extern void rip_peer_bad_packet(struct sockaddr_in *);
extern void rip_peer_display(struct vty *);
extern struct rip_peer *rip_peer_lookup(struct in_addr *);
extern struct rip_peer *rip_peer_lookup_next(struct in_addr *);
extern int rip_show_network_config(struct vty *vty, struct rip *rip);
extern void rip_show_redistribute_config(struct vty *vty, struct rip *rip);
extern void rip_peer_update(struct rip *rip, struct sockaddr_in *from,
uint8_t version);
extern void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from);
extern void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from);
extern void rip_peer_display(struct vty *vty, struct rip *rip);
extern struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr);
extern struct rip_peer *rip_peer_lookup_next(struct rip *rip,
struct in_addr *addr);
extern int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2);
extern void rip_peer_list_del(void *arg);
extern void rip_info_free(struct rip_info *);
extern struct rip *rip_info_get_instance(const struct rip_info *rinfo);
extern struct rip_distance *rip_distance_new(void);
extern void rip_distance_free(struct rip_distance *rdistance);
extern uint8_t rip_distance_apply(struct rip_info *);
extern void rip_redistribute_clean(void);
extern uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo);
extern void rip_redistribute_enable(struct rip *rip);
extern void rip_redistribute_disable(struct rip *rip);
extern int rip_route_rte(struct rip_info *rinfo);
extern struct rip_info *rip_ecmp_add(struct rip_info *);
extern struct rip_info *rip_ecmp_replace(struct rip_info *);
extern struct rip_info *rip_ecmp_delete(struct rip_info *);
extern struct rip_info *rip_ecmp_add(struct rip *rip,
struct rip_info *rinfo_new);
extern struct rip_info *rip_ecmp_replace(struct rip *rip,
struct rip_info *rinfo_new);
extern struct rip_info *rip_ecmp_delete(struct rip *rip,
struct rip_info *rinfo);
extern struct rip_offset_list *rip_offset_list_new(const char *ifname);
extern struct rip_offset_list *rip_offset_list_new(struct rip *rip,
const char *ifname);
extern void offset_list_del(struct rip_offset_list *offset);
extern struct rip_offset_list *rip_offset_list_lookup(const char *ifname);
extern struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
const char *ifname);
extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *,
uint32_t *);
extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *,
uint32_t *);
extern void rip_offset_init(void);
extern void rip_offset_clean(void);
extern int offset_list_cmp(struct rip_offset_list *o1,
struct rip_offset_list *o2);
extern void rip_vrf_init(void);
extern void rip_vrf_terminate(void);
/* YANG notifications */
extern void ripd_notif_send_auth_type_failure(const char *ifname);
extern void ripd_notif_send_auth_failure(const char *ifname);
/* There is only one rip strucutre. */
extern struct rip *rip;
extern struct zebra_privs_t ripd_privs;
extern struct rip_instance_head rip_instances;
/* Master thread strucutre. */
extern struct thread_master *master;
/* RIP statistics for SNMP. */
extern long rip_global_route_changes;
extern long rip_global_queries;
DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc))
DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
extern struct list *peer_list;
extern struct route_table *rip_distance_table;
extern vector Vrip_passive_nondefault;
/* Northbound. */
extern void rip_cli_init(void);
extern const struct frr_yang_module_info frr_ripd_info;

View File

@ -39,31 +39,46 @@
*/
DEFPY_NOSH (router_ripng,
router_ripng_cmd,
"router ripng",
"router ripng [vrf NAME]",
"Enable a routing process\n"
"Make RIPng instance command\n")
"Make RIPng instance command\n"
VRF_CMD_HELP_STR)
{
char xpath[XPATH_MAXLEN];
int ret;
nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE,
NULL);
/* Build RIPng instance XPath. */
if (!vrf)
vrf = VRF_DEFAULT_NAME;
snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
vrf);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance");
VTY_PUSH_XPATH(RIPNG_NODE, xpath);
return ret;
}
DEFPY (no_router_ripng,
no_router_ripng_cmd,
"no router ripng",
"no router ripng [vrf NAME]",
NO_STR
"Enable a routing process\n"
"Make RIPng instance command\n")
"Make RIPng instance command\n"
VRF_CMD_HELP_STR)
{
nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DESTROY,
NULL);
char xpath[XPATH_MAXLEN];
/* Build RIPng instance XPath. */
if (!vrf)
vrf = VRF_DEFAULT_NAME;
snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
vrf);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
@ -71,8 +86,15 @@ DEFPY (no_router_ripng,
void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
const char *vrf_name;
vrf_name = yang_dnode_get_string(dnode, "./vrf");
vty_out(vty, "!\n");
vty_out(vty, "router ripng\n");
vty_out(vty, "router ripng");
if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
vty_out(vty, " vrf %s", vrf_name);
vty_out(vty, "\n");
}
/*
@ -456,12 +478,24 @@ void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
*/
DEFPY (clear_ipv6_rip,
clear_ipv6_rip_cmd,
"clear ipv6 ripng",
"clear ipv6 ripng [vrf WORD]",
CLEAR_STR
IPV6_STR
"Clear IPv6 RIP database\n")
"Clear IPv6 RIP database\n"
VRF_CMD_HELP_STR)
{
return nb_cli_rpc("/frr-ripngd:clear-ripng-route", NULL, NULL);
struct list *input;
input = list_new();
if (vrf) {
struct yang_data *yang_vrf;
yang_vrf = yang_data_new(
"/frr-ripngd:clear-ripng-route/input/vrf", vrf);
listnode_add(input, yang_vrf);
}
return nb_cli_rpc("/frr-ripngd:clear-ripng-route", input, NULL);
}
void ripng_cli_init(void)

View File

@ -52,12 +52,12 @@
/* Static utility function. */
static void ripng_enable_apply(struct interface *);
static void ripng_passive_interface_apply(struct interface *);
static int ripng_enable_if_lookup(const char *);
static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname);
static int ripng_enable_network_lookup2(struct connected *);
static void ripng_enable_apply_all(void);
static void ripng_enable_apply_all(struct ripng *ripng);
/* Join to the all rip routers multicast group. */
static int ripng_multicast_join(struct interface *ifp)
static int ripng_multicast_join(struct interface *ifp, int sock)
{
int ret;
struct ipv6_mreq mreq;
@ -75,8 +75,7 @@ static int ripng_multicast_join(struct interface *ifp)
*/
frr_elevate_privs(&ripngd_privs) {
ret = setsockopt(ripng->sock, IPPROTO_IPV6,
IPV6_JOIN_GROUP,
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char *)&mreq, sizeof(mreq));
save_errno = errno;
@ -111,7 +110,7 @@ static int ripng_multicast_join(struct interface *ifp)
}
/* Leave from the all rip routers multicast group. */
static int ripng_multicast_leave(struct interface *ifp)
static int ripng_multicast_leave(struct interface *ifp, int sock)
{
int ret;
struct ipv6_mreq mreq;
@ -121,7 +120,7 @@ static int ripng_multicast_leave(struct interface *ifp)
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = ifp->ifindex;
ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
(char *)&mreq, sizeof(mreq));
if (ret < 0)
zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s",
@ -163,9 +162,13 @@ static int ripng_if_down(struct interface *ifp)
struct agg_node *rp;
struct ripng_info *rinfo;
struct ripng_interface *ri;
struct ripng *ripng;
struct list *list = NULL;
struct listnode *listnode = NULL, *nextnode = NULL;
ri = ifp->info;
ripng = ri->ripng;
if (ripng)
for (rp = agg_route_top(ripng->table); rp;
rp = agg_route_next(rp))
@ -173,16 +176,15 @@ static int ripng_if_down(struct interface *ifp)
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo))
if (rinfo->ifindex == ifp->ifindex)
ripng_ecmp_delete(rinfo);
ripng_ecmp_delete(ripng, rinfo);
ri = ifp->info;
if (ri->running) {
if (IS_RIPNG_DEBUG_EVENT)
zlog_debug("turn off %s", ifp->name);
/* Leave from multicast group. */
ripng_multicast_leave(ifp);
ripng_multicast_leave(ifp, ripng->sock);
ri->running = 0;
}
@ -207,9 +209,11 @@ int ripng_interface_up(int command, struct zclient *zclient,
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"interface up %s index %d flags %llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu6);
"interface up %s vrf %u index %d flags %llx metric %d mtu %d",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
ripng_interface_sync(ifp);
/* Check if this interface is RIPng enabled or not. */
ripng_enable_apply(ifp);
@ -238,13 +242,14 @@ int ripng_interface_down(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
ripng_interface_sync(ifp);
ripng_if_down(ifp);
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"interface down %s index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu6);
"interface down %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
return 0;
}
@ -256,12 +261,13 @@ int ripng_interface_add(int command, struct zclient *zclient,
struct interface *ifp;
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
ripng_interface_sync(ifp);
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"RIPng interface add %s index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu6);
"RIPng interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
/* Check is this interface is RIP enabled or not.*/
ripng_enable_apply(ifp);
@ -289,13 +295,15 @@ int ripng_interface_delete(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
ripng_interface_sync(ifp);
if (if_is_up(ifp)) {
ripng_if_down(ifp);
}
zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu6);
zlog_info(
"interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
/* To support pseudo interface do not free interface structure. */
/* if_delete(ifp); */
@ -304,13 +312,34 @@ int ripng_interface_delete(int command, struct zclient *zclient,
return 0;
}
void ripng_interface_clean(void)
/* VRF update for an interface. */
int ripng_interface_vrf_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
vrf_id_t new_vrf_id;
ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
&new_vrf_id);
if (!ifp)
return 0;
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
ifp->name, vrf_id, new_vrf_id);
if_update_to_new_vrf(ifp, new_vrf_id);
ripng_interface_sync(ifp);
return 0;
}
void ripng_interface_clean(struct ripng *ripng)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct ripng_interface *ri;
FOR_ALL_INTERFACES (vrf, ifp) {
FOR_ALL_INTERFACES (ripng->vrf, ifp) {
ri = ifp->info;
ri->enable_network = 0;
@ -326,6 +355,8 @@ void ripng_interface_clean(void)
static void ripng_apply_address_add(struct connected *ifc)
{
struct ripng_interface *ri = ifc->ifp->info;
struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
@ -345,9 +376,9 @@ static void ripng_apply_address_add(struct connected *ifc)
/* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */
if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0)
if ((ripng_enable_if_lookup(ripng, ifc->ifp->name) >= 0)
|| (ripng_enable_network_lookup2(ifc) >= 0))
ripng_redistribute_add(ZEBRA_ROUTE_CONNECT,
ripng_redistribute_add(ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
ifc->ifp->ifindex, NULL, 0);
}
@ -395,6 +426,8 @@ int ripng_interface_address_add(int command, struct zclient *zclient,
static void ripng_apply_address_del(struct connected *ifc)
{
struct ripng_interface *ri = ifc->ifp->info;
struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
@ -412,8 +445,9 @@ static void ripng_apply_address_del(struct connected *ifc)
address.prefixlen = p->prefixlen;
apply_mask_ipv6(&address);
ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
&address, ifc->ifp->ifindex);
ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
ifc->ifp->ifindex);
}
int ripng_interface_address_delete(int command, struct zclient *zclient,
@ -446,21 +480,20 @@ int ripng_interface_address_delete(int command, struct zclient *zclient,
return 0;
}
/* RIPng enable interface vector. */
vector ripng_enable_if;
/* RIPng enable network table. */
struct agg_table *ripng_enable_network;
/* Lookup RIPng enable network. */
/* Check wether the interface has at least a connected prefix that
* is within the ripng_enable_network table. */
* is within the ripng->enable_network table. */
static int ripng_enable_network_lookup_if(struct interface *ifp)
{
struct ripng_interface *ri = ifp->info;
struct ripng *ripng = ri->ripng;
struct listnode *node;
struct connected *connected;
struct prefix_ipv6 address;
if (!ripng)
return -1;
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
struct prefix *p;
struct agg_node *n;
@ -472,7 +505,7 @@ static int ripng_enable_network_lookup_if(struct interface *ifp)
address.prefix = p->u.prefix6;
address.prefixlen = IPV6_MAX_BITLEN;
n = agg_node_match(ripng_enable_network,
n = agg_node_match(ripng->enable_network,
(struct prefix *)&address);
if (n) {
agg_unlock_node(n);
@ -483,12 +516,17 @@ static int ripng_enable_network_lookup_if(struct interface *ifp)
return -1;
}
/* Check wether connected is within the ripng_enable_network table. */
/* Check wether connected is within the ripng->enable_network table. */
static int ripng_enable_network_lookup2(struct connected *connected)
{
struct ripng_interface *ri = connected->ifp->info;
struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
if (!ripng)
return -1;
p = connected->address;
if (p->family == AF_INET6) {
@ -499,8 +537,8 @@ static int ripng_enable_network_lookup2(struct connected *connected)
address.prefixlen = IPV6_MAX_BITLEN;
/* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within
* ripng_enable_network */
node = agg_node_match(ripng_enable_network,
* ripng->enable_network */
node = agg_node_match(ripng->enable_network,
(struct prefix *)&address);
if (node) {
@ -513,11 +551,11 @@ static int ripng_enable_network_lookup2(struct connected *connected)
}
/* Add RIPng enable network. */
int ripng_enable_network_add(struct prefix *p)
int ripng_enable_network_add(struct ripng *ripng, struct prefix *p)
{
struct agg_node *node;
node = agg_node_get(ripng_enable_network, p);
node = agg_node_get(ripng->enable_network, p);
if (node->info) {
agg_unlock_node(node);
@ -526,17 +564,17 @@ int ripng_enable_network_add(struct prefix *p)
node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */
ripng_enable_apply_all();
ripng_enable_apply_all(ripng);
return NB_OK;
}
/* Delete RIPng enable network. */
int ripng_enable_network_delete(struct prefix *p)
int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p)
{
struct agg_node *node;
node = agg_node_lookup(ripng_enable_network, p);
node = agg_node_lookup(ripng->enable_network, p);
if (node) {
node->info = NULL;
@ -553,49 +591,50 @@ int ripng_enable_network_delete(struct prefix *p)
}
/* Lookup function. */
static int ripng_enable_if_lookup(const char *ifname)
static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname)
{
unsigned int i;
char *str;
for (i = 0; i < vector_active(ripng_enable_if); i++)
if ((str = vector_slot(ripng_enable_if, i)) != NULL)
if (!ripng)
return -1;
for (i = 0; i < vector_active(ripng->enable_if); i++)
if ((str = vector_slot(ripng->enable_if, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
}
/* Add interface to ripng_enable_if. */
int ripng_enable_if_add(const char *ifname)
int ripng_enable_if_add(struct ripng *ripng, const char *ifname)
{
int ret;
ret = ripng_enable_if_lookup(ifname);
ret = ripng_enable_if_lookup(ripng, ifname);
if (ret >= 0)
return NB_ERR_INCONSISTENCY;
vector_set(ripng_enable_if, strdup(ifname));
vector_set(ripng->enable_if, strdup(ifname));
ripng_enable_apply_all();
ripng_enable_apply_all(ripng);
return NB_OK;
}
/* Delete interface from ripng_enable_if. */
int ripng_enable_if_delete(const char *ifname)
int ripng_enable_if_delete(struct ripng *ripng, const char *ifname)
{
int index;
char *str;
index = ripng_enable_if_lookup(ifname);
index = ripng_enable_if_lookup(ripng, ifname);
if (index < 0)
return NB_ERR_INCONSISTENCY;
str = vector_slot(ripng_enable_if, index);
str = vector_slot(ripng->enable_if, index);
free(str);
vector_unset(ripng_enable_if, index);
vector_unset(ripng->enable_if, index);
ripng_enable_apply_all();
ripng_enable_apply_all(ripng);
return NB_OK;
}
@ -613,7 +652,7 @@ static int ripng_interface_wakeup(struct thread *t)
ri->t_wakeup = NULL;
/* Join to multicast group. */
if (ripng_multicast_join(ifp) < 0) {
if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"multicast join failed, interface %s not running",
ifp->name);
@ -631,6 +670,8 @@ static int ripng_interface_wakeup(struct thread *t)
static void ripng_connect_set(struct interface *ifp, int set)
{
struct ripng_interface *ri = ifp->info;
struct ripng *ripng = ri->ripng;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv6 address;
@ -650,19 +691,22 @@ static void ripng_connect_set(struct interface *ifp, int set)
if (set) {
/* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */
if ((ripng_enable_if_lookup(connected->ifp->name) >= 0)
if ((ripng_enable_if_lookup(ripng, connected->ifp->name)
>= 0)
|| (ripng_enable_network_lookup2(connected) >= 0))
ripng_redistribute_add(
ZEBRA_ROUTE_CONNECT,
ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
connected->ifp->ifindex, NULL, 0);
} else {
ripng_redistribute_delete(
ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
&address, connected->ifp->ifindex);
if (ripng_redistribute_check(ZEBRA_ROUTE_CONNECT))
ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE,
&address,
connected->ifp->ifindex);
if (ripng_redistribute_check(ripng,
ZEBRA_ROUTE_CONNECT))
ripng_redistribute_add(
ZEBRA_ROUTE_CONNECT,
ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_REDISTRIBUTE, &address,
connected->ifp->ifindex, NULL, 0);
}
@ -691,7 +735,7 @@ void ripng_enable_apply(struct interface *ifp)
ri->enable_network = 0;
/* Check interface name configuration. */
ret = ripng_enable_if_lookup(ifp->name);
ret = ripng_enable_if_lookup(ri->ripng, ifp->name);
if (ret >= 0)
ri->enable_interface = 1;
else
@ -729,49 +773,46 @@ void ripng_enable_apply(struct interface *ifp)
}
/* Set distribute list to all interfaces. */
static void ripng_enable_apply_all(void)
static void ripng_enable_apply_all(struct ripng *ripng)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
FOR_ALL_INTERFACES (ripng->vrf, ifp)
ripng_enable_apply(ifp);
}
/* Clear all network and neighbor configuration */
void ripng_clean_network(void)
void ripng_clean_network(struct ripng *ripng)
{
unsigned int i;
char *str;
struct agg_node *rn;
/* ripng_enable_network */
for (rn = agg_route_top(ripng_enable_network); rn;
/* ripng->enable_network */
for (rn = agg_route_top(ripng->enable_network); rn;
rn = agg_route_next(rn))
if (rn->info) {
rn->info = NULL;
agg_unlock_node(rn);
}
/* ripng_enable_if */
for (i = 0; i < vector_active(ripng_enable_if); i++)
if ((str = vector_slot(ripng_enable_if, i)) != NULL) {
/* ripng->enable_if */
for (i = 0; i < vector_active(ripng->enable_if); i++)
if ((str = vector_slot(ripng->enable_if, i)) != NULL) {
free(str);
vector_slot(ripng_enable_if, i) = NULL;
vector_slot(ripng->enable_if, i) = NULL;
}
}
/* Vector to store passive-interface name. */
vector Vripng_passive_interface;
/* Utility function for looking up passive interface settings. */
static int ripng_passive_interface_lookup(const char *ifname)
static int ripng_passive_interface_lookup(struct ripng *ripng,
const char *ifname)
{
unsigned int i;
char *str;
for (i = 0; i < vector_active(Vripng_passive_interface); i++)
if ((str = vector_slot(Vripng_passive_interface, i)) != NULL)
for (i = 0; i < vector_active(ripng->passive_interface); i++)
if ((str = vector_slot(ripng->passive_interface, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
@ -781,72 +822,75 @@ void ripng_passive_interface_apply(struct interface *ifp)
{
int ret;
struct ripng_interface *ri;
struct ripng *ripng;
ri = ifp->info;
ripng = ri->ripng;
if (!ripng)
return;
ret = ripng_passive_interface_lookup(ifp->name);
ret = ripng_passive_interface_lookup(ripng, ifp->name);
if (ret < 0)
ri->passive = 0;
else
ri->passive = 1;
}
static void ripng_passive_interface_apply_all(void)
static void ripng_passive_interface_apply_all(struct ripng *ripng)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
FOR_ALL_INTERFACES (ripng->vrf, ifp)
ripng_passive_interface_apply(ifp);
}
/* Passive interface. */
int ripng_passive_interface_set(const char *ifname)
int ripng_passive_interface_set(struct ripng *ripng, const char *ifname)
{
if (ripng_passive_interface_lookup(ifname) >= 0)
if (ripng_passive_interface_lookup(ripng, ifname) >= 0)
return NB_ERR_INCONSISTENCY;
vector_set(Vripng_passive_interface, strdup(ifname));
vector_set(ripng->passive_interface, strdup(ifname));
ripng_passive_interface_apply_all();
ripng_passive_interface_apply_all(ripng);
return NB_OK;
}
int ripng_passive_interface_unset(const char *ifname)
int ripng_passive_interface_unset(struct ripng *ripng, const char *ifname)
{
int i;
char *str;
i = ripng_passive_interface_lookup(ifname);
i = ripng_passive_interface_lookup(ripng, ifname);
if (i < 0)
return NB_ERR_INCONSISTENCY;
str = vector_slot(Vripng_passive_interface, i);
str = vector_slot(ripng->passive_interface, i);
free(str);
vector_unset(Vripng_passive_interface, i);
vector_unset(ripng->passive_interface, i);
ripng_passive_interface_apply_all();
ripng_passive_interface_apply_all(ripng);
return NB_OK;
}
/* Free all configured RIP passive-interface settings. */
void ripng_passive_interface_clean(void)
void ripng_passive_interface_clean(struct ripng *ripng)
{
unsigned int i;
char *str;
for (i = 0; i < vector_active(Vripng_passive_interface); i++)
if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) {
for (i = 0; i < vector_active(ripng->passive_interface); i++)
if ((str = vector_slot(ripng->passive_interface, i)) != NULL) {
free(str);
vector_slot(Vripng_passive_interface, i) = NULL;
vector_slot(ripng->passive_interface, i) = NULL;
}
ripng_passive_interface_apply_all();
ripng_passive_interface_apply_all(ripng);
}
/* Write RIPng enable network and interface to the vty. */
int ripng_network_write(struct vty *vty)
int ripng_network_write(struct vty *vty, struct ripng *ripng)
{
unsigned int i;
const char *ifname;
@ -854,7 +898,7 @@ int ripng_network_write(struct vty *vty)
char buf[BUFSIZ];
/* Write enable network. */
for (node = agg_route_top(ripng_enable_network); node;
for (node = agg_route_top(ripng->enable_network); node;
node = agg_route_next(node))
if (node->info) {
struct prefix *p = &node->p;
@ -864,8 +908,8 @@ int ripng_network_write(struct vty *vty)
}
/* Write enable interface. */
for (i = 0; i < vector_active(ripng_enable_if); i++)
if ((ifname = vector_slot(ripng_enable_if, i)) != NULL)
for (i = 0; i < vector_active(ripng->enable_if); i++)
if ((ifname = vector_slot(ripng->enable_if, i)) != NULL)
vty_out(vty, " %s\n", ifname);
return 0;
@ -874,6 +918,7 @@ int ripng_network_write(struct vty *vty)
static struct ripng_interface *ri_new(void)
{
struct ripng_interface *ri;
ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface));
/* Set default split-horizon behavior. If the interface is Frame
@ -886,9 +931,25 @@ static struct ripng_interface *ri_new(void)
return ri;
}
void ripng_interface_sync(struct interface *ifp)
{
struct vrf *vrf;
vrf = vrf_lookup_by_id(ifp->vrf_id);
if (vrf) {
struct ripng_interface *ri;
ri = ifp->info;
if (ri)
ri->ripng = vrf->info;
}
}
static int ripng_if_new_hook(struct interface *ifp)
{
ifp->info = ri_new();
ripng_interface_sync(ifp);
return 0;
}
@ -903,22 +964,25 @@ static int ripng_if_delete_hook(struct interface *ifp)
/* Configuration write function for ripngd. */
static int interface_config_write(struct vty *vty)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct vrf *vrf;
int write = 0;
FOR_ALL_INTERFACES (vrf, ifp) {
struct lyd_node *dnode;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
struct interface *ifp;
dnode = yang_dnode_get(
running_config->dnode,
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
ifp->name, vrf->name);
if (dnode == NULL)
continue;
FOR_ALL_INTERFACES (vrf, ifp) {
struct lyd_node *dnode;
write = 1;
nb_cli_show_dnode_cmds(vty, dnode, false);
dnode = yang_dnode_get(
running_config->dnode,
"/frr-interface:lib/interface[name='%s'][vrf='%s']",
ifp->name, vrf->name);
if (dnode == NULL)
continue;
write = 1;
nb_cli_show_dnode_cmds(vty, dnode, false);
}
}
return write;
@ -936,15 +1000,6 @@ void ripng_if_init(void)
hook_register_prio(if_add, 0, ripng_if_new_hook);
hook_register_prio(if_del, 0, ripng_if_delete_hook);
/* RIPng enable network init. */
ripng_enable_network = agg_table_init();
/* RIPng enable interface init. */
ripng_enable_if = vector_init(1);
/* RIPng passive interface. */
Vripng_passive_interface = vector_init(1);
/* Install interface node. */
install_node(&interface_node, interface_config_write);
if_cmd_init();

View File

@ -35,6 +35,7 @@
#include "privs.h"
#include "sigevent.h"
#include "vrf.h"
#include "if_rmap.h"
#include "libfrr.h"
#include "ripngd/ripngd.h"
@ -46,7 +47,7 @@
struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
/* ripngd privileges */
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
struct zebra_privs_t ripngd_privs = {
#if defined(FRR_USER)
@ -59,7 +60,7 @@ struct zebra_privs_t ripngd_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = 2,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
@ -82,8 +83,8 @@ static void sigint(void)
{
zlog_notice("Terminating on signal");
ripng_clean();
ripng_vrf_terminate();
if_rmap_terminate();
ripng_zebra_stop();
frr_fini();
exit(0);
@ -170,13 +171,12 @@ int main(int argc, char **argv)
master = frr_init();
/* Library inits. */
vrf_init(NULL, NULL, NULL, NULL, NULL);
ripng_vrf_init();
/* RIPngd inits. */
ripng_init();
ripng_cli_init();
zebra_init(master);
ripng_peer_init();
frr_config_fork();
frr_run(master);

View File

@ -27,6 +27,7 @@
DEFINE_MGROUP(RIPNGD, "ripngd")
DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure")
DEFINE_MTYPE(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name")
DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info")
DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer")

View File

@ -26,6 +26,7 @@
DECLARE_MGROUP(RIPNGD)
DECLARE_MTYPE(RIPNG)
DECLARE_MTYPE(RIPNG_VRF_NAME)
DECLARE_MTYPE(RIPNG_ROUTE)
DECLARE_MTYPE(RIPNG_AGGREGATE)
DECLARE_MTYPE(RIPNG_PEER)

View File

@ -114,7 +114,8 @@ void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
struct sockaddr_in6 *to)
{
struct ripng_interface *ri = ifp->info;
struct ripng *ripng = ri->ripng;
struct ripng_rte_data *data;
struct listnode *node, *nnode;

File diff suppressed because it is too large Load Diff

View File

@ -33,29 +33,29 @@
#include "ripngd/ripngd.h"
static struct list *ripng_offset_list_master;
#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
struct ripng_offset_list *ripng_offset_list_new(const char *ifname)
struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
const char *ifname)
{
struct ripng_offset_list *new;
new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
sizeof(struct ripng_offset_list));
new->ripng = ripng;
new->ifname = strdup(ifname);
listnode_add_sort(ripng_offset_list_master, new);
listnode_add_sort(ripng->offset_list_master, new);
return new;
}
void ripng_offset_list_del(struct ripng_offset_list *offset)
{
listnode_delete(ripng_offset_list_master, offset);
listnode_delete(offset->ripng->offset_list_master, offset);
if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_NAME(offset))
@ -64,12 +64,14 @@ void ripng_offset_list_del(struct ripng_offset_list *offset)
XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
}
struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
const char *ifname)
{
struct ripng_offset_list *offset;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
for (ALL_LIST_ELEMENTS(ripng->offset_list_master, node, nnode,
offset)) {
if (strcmp(offset->ifname, ifname) == 0)
return offset;
}
@ -77,14 +79,14 @@ struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
}
/* If metric is modifed return 1. */
int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
uint8_t *metric)
int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
struct interface *ifp, uint8_t *metric)
{
struct ripng_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
offset = ripng_offset_list_lookup(ifp->name);
offset = ripng_offset_list_lookup(ripng, ifp->name);
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
@ -98,7 +100,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
return 0;
}
/* Look up offset-list without interface name. */
offset = ripng_offset_list_lookup("*");
offset = ripng_offset_list_lookup(ripng, "*");
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
@ -115,14 +117,14 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
}
/* If metric is modifed return 1. */
int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
uint8_t *metric)
int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p,
struct interface *ifp, uint8_t *metric)
{
struct ripng_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
offset = ripng_offset_list_lookup(ifp->name);
offset = ripng_offset_list_lookup(ripng, ifp->name);
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
@ -137,7 +139,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
}
/* Look up offset-list without interface name. */
offset = ripng_offset_list_lookup("*");
offset = ripng_offset_list_lookup(ripng, "*");
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
@ -153,26 +155,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
return 0;
}
static int offset_list_cmp(struct ripng_offset_list *o1,
struct ripng_offset_list *o2)
int offset_list_cmp(struct ripng_offset_list *o1, struct ripng_offset_list *o2)
{
return strcmp(o1->ifname, o2->ifname);
}
void ripng_offset_init(void)
{
ripng_offset_list_master = list_new();
ripng_offset_list_master->cmp =
(int (*)(void *, void *))offset_list_cmp;
ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
}
void ripng_offset_clean(void)
{
list_delete(&ripng_offset_list_master);
ripng_offset_list_master = list_new();
ripng_offset_list_master->cmp =
(int (*)(void *, void *))offset_list_cmp;
ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
}

View File

@ -34,10 +34,6 @@
#include "ripngd/ripngd.h"
#include "ripngd/ripng_nexthop.h"
/* Linked list of RIPng peer. */
struct list *peer_list;
static struct ripng_peer *ripng_peer_new(void)
{
return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer));
@ -45,27 +41,29 @@ static struct ripng_peer *ripng_peer_new(void)
static void ripng_peer_free(struct ripng_peer *peer)
{
RIPNG_TIMER_OFF(peer->t_timeout);
XFREE(MTYPE_RIPNG_PEER, peer);
}
struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr)
struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
if (IPV6_ADDR_SAME(&peer->addr, addr))
return peer;
}
return NULL;
}
struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *addr)
struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
struct in6_addr *addr)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
if (addr6_cmp(&peer->addr, addr) > 0)
return peer;
}
@ -80,26 +78,28 @@ static int ripng_peer_timeout(struct thread *t)
struct ripng_peer *peer;
peer = THREAD_ARG(t);
listnode_delete(peer_list, peer);
listnode_delete(peer->ripng->peer_list, peer);
ripng_peer_free(peer);
return 0;
}
/* Get RIPng peer. At the same time update timeout thread. */
static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
static struct ripng_peer *ripng_peer_get(struct ripng *ripng,
struct in6_addr *addr)
{
struct ripng_peer *peer;
peer = ripng_peer_lookup(addr);
peer = ripng_peer_lookup(ripng, addr);
if (peer) {
if (peer->t_timeout)
thread_cancel(peer->t_timeout);
} else {
peer = ripng_peer_new();
peer->addr = *addr; /* XXX */
listnode_add_sort(peer_list, peer);
peer->ripng = ripng;
peer->addr = *addr;
listnode_add_sort(ripng->peer_list, peer);
}
/* Update timeout thread. */
@ -113,24 +113,25 @@ static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
return peer;
}
void ripng_peer_update(struct sockaddr_in6 *from, uint8_t version)
void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
uint8_t version)
{
struct ripng_peer *peer;
peer = ripng_peer_get(&from->sin6_addr);
peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->version = version;
}
void ripng_peer_bad_route(struct sockaddr_in6 *from)
void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from)
{
struct ripng_peer *peer;
peer = ripng_peer_get(&from->sin6_addr);
peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badroutes++;
}
void ripng_peer_bad_packet(struct sockaddr_in6 *from)
void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from)
{
struct ripng_peer *peer;
peer = ripng_peer_get(&from->sin6_addr);
peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badpackets++;
}
@ -163,14 +164,14 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
return buf;
}
void ripng_peer_display(struct vty *vty)
void ripng_peer_display(struct vty *vty, struct ripng *ripng)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
#define RIPNG_UPTIME_LEN 25
char timebuf[RIPNG_UPTIME_LEN];
for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
vty_out(vty, " %s \n%14s %10d %10d %10d %s\n",
inet6_ntoa(peer->addr), " ", peer->recv_badpackets,
peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT,
@ -178,13 +179,12 @@ void ripng_peer_display(struct vty *vty)
}
}
static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
{
return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr));
}
void ripng_peer_init(void)
void ripng_peer_list_del(void *arg)
{
peer_list = list_new();
peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
ripng_peer_free(arg);
}

View File

@ -86,7 +86,7 @@ void ripng_aggregate_decrement_list(struct agg_node *child, struct list *list)
}
/* RIPng routes treatment. */
int ripng_aggregate_add(struct prefix *p)
int ripng_aggregate_add(struct ripng *ripng, struct prefix *p)
{
struct agg_node *top;
struct agg_node *rp;
@ -124,7 +124,7 @@ int ripng_aggregate_add(struct prefix *p)
}
/* Delete RIPng static route. */
int ripng_aggregate_delete(struct prefix *p)
int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p)
{
struct agg_node *top;
struct agg_node *rp;

View File

@ -48,8 +48,8 @@ extern void ripng_aggregate_decrement(struct agg_node *rp,
struct ripng_info *rinfo);
extern void ripng_aggregate_decrement_list(struct agg_node *rp,
struct list *list);
extern int ripng_aggregate_add(struct prefix *p);
extern int ripng_aggregate_delete(struct prefix *p);
extern int ripng_aggregate_add(struct ripng *ripng, struct prefix *p);
extern int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p);
extern void ripng_aggregate_free(struct ripng_aggregate *aggregate);
#endif /* _ZEBRA_RIPNG_ROUTE_H */

View File

@ -37,7 +37,8 @@
struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */
static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
uint8_t cmd)
{
struct list *list = (struct list *)rp->info;
struct zapi_route api;
@ -47,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
int count = 0;
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.vrf_id = ripng->vrf->vrf_id;
api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST;
api.prefix = rp->p;
@ -57,7 +58,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
api_nh->vrf_id = VRF_DEFAULT;
api_nh->vrf_id = ripng->vrf->vrf_id;
api_nh->gate.ipv6 = rinfo->nexthop;
api_nh->ifindex = rinfo->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
@ -100,25 +101,30 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
}
/* Add/update ECMP routes to zebra. */
void ripng_zebra_ipv6_add(struct agg_node *rp)
void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp)
{
ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD);
}
/* Delete ECMP routes from zebra. */
void ripng_zebra_ipv6_delete(struct agg_node *rp)
void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp)
{
ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE);
}
/* Zebra route add and delete treatment. */
static int ripng_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct ripng *ripng;
struct zapi_route api;
struct in6_addr nexthop;
unsigned long ifindex;
ripng = ripng_lookup_by_vrf_id(vrf_id);
if (!ripng)
return 0;
if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
@ -133,69 +139,97 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
ifindex = api.nexthops[0].ifindex;
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
ripng_redistribute_add(ripng, api.type,
RIPNG_ROUTE_REDISTRIBUTE,
(struct prefix_ipv6 *)&api.prefix,
ifindex, &nexthop, api.tag);
else
ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
(struct prefix_ipv6 *)&api.prefix,
ifindex);
ripng_redistribute_delete(
ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
(struct prefix_ipv6 *)&api.prefix, ifindex);
return 0;
}
void ripng_redistribute_conf_update(int type)
void ripng_redistribute_conf_update(struct ripng *ripng, int type)
{
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
VRF_DEFAULT);
ripng->vrf->vrf_id);
}
void ripng_redistribute_conf_delete(int type)
void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
{
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
AFI_IP6, type, 0, VRF_DEFAULT);
AFI_IP6, type, 0, ripng->vrf->vrf_id);
ripng_redistribute_withdraw(type);
ripng_redistribute_withdraw(ripng, type);
}
int ripng_redistribute_check(int type)
int ripng_redistribute_check(struct ripng *ripng, int type)
{
return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
return ripng->redist[type].enabled;
}
void ripng_redistribute_clean(void)
void ripng_redistribute_enable(struct ripng *ripng)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
if (!ripng_redistribute_check(ripng, i))
continue;
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
zclient, AFI_IP6, i, 0,
VRF_DEFAULT);
vrf_bitmap_unset(zclient->redist[AFI_IP6][i], VRF_DEFAULT);
/* Remove the routes from RIP table. */
ripng_redistribute_withdraw(i);
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
AFI_IP6, i, 0, ripng->vrf->vrf_id);
}
}
void ripng_redistribute_write(struct vty *vty)
void ripng_redistribute_disable(struct ripng *ripng)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!ripng_redistribute_check(ripng, i))
continue;
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
AFI_IP6, i, 0, ripng->vrf->vrf_id);
}
}
void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
{
int i;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default
|| !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
VRF_DEFAULT))
|| !ripng_redistribute_check(ripng, i))
continue;
vty_out(vty, " %s", zebra_route_string(i));
}
}
void ripng_zebra_vrf_register(struct vrf *vrf)
{
if (vrf->vrf_id == VRF_DEFAULT)
return;
if (IS_RIPNG_DEBUG_EVENT)
zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
vrf->name, vrf->vrf_id);
zclient_send_reg_requests(zclient, vrf->vrf_id);
}
void ripng_zebra_vrf_deregister(struct vrf *vrf)
{
if (vrf->vrf_id == VRF_DEFAULT)
return;
if (IS_RIPNG_DEBUG_EVENT)
zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
vrf->name, vrf->vrf_id);
zclient_send_dereg_requests(zclient, vrf->vrf_id);
}
static void ripng_zebra_connected(struct zclient *zclient)
{
zclient_send_reg_requests(zclient, VRF_DEFAULT);
@ -215,6 +249,7 @@ void zebra_init(struct thread_master *master)
zclient->interface_delete = ripng_interface_delete;
zclient->interface_address_add = ripng_interface_address_add;
zclient->interface_address_delete = ripng_interface_address_delete;
zclient->interface_vrf_update = ripng_interface_vrf_update;
zclient->redistribute_route_add = ripng_zebra_read_route;
zclient->redistribute_route_del = ripng_zebra_read_route;
}

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
#include <zclient.h>
#include <vty.h>
#include <distribute.h>
#include <vector.h>
#include "ripng_memory.h"
@ -88,6 +89,17 @@
/* RIPng structure. */
struct ripng {
RB_ENTRY(ripng) entry;
/* VRF this routing instance is associated with. */
char *vrf_name;
/* VRF backpointer (might be NULL if the VRF doesn't exist). */
struct vrf *vrf;
/* Status of the routing instance. */
bool enabled;
/* RIPng socket. */
int sock;
@ -107,6 +119,21 @@ struct ripng {
/* RIPng routing information base. */
struct agg_table *table;
/* Linked list of RIPng peers. */
struct list *peer_list;
/* RIPng enabled interfaces. */
vector enable_if;
/* RIPng enabled networks. */
struct agg_table *enable_network;
/* Vector to store passive-interface name. */
vector passive_interface;
/* RIPng offset-lists. */
struct list *offset_list_master;
/* RIPng threads. */
struct thread *t_read;
struct thread *t_write;
@ -122,13 +149,16 @@ struct ripng {
/* RIPng ECMP flag */
bool ecmp;
/* For redistribute route map. */
/* RIPng redistribute configuration. */
struct {
char *name;
struct route_map *map;
bool enabled;
struct {
char *name;
struct route_map *map;
} route_map;
bool metric_config;
uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX];
} redist[ZEBRA_ROUTE_MAX];
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
@ -136,6 +166,8 @@ struct ripng {
/* For if_rmap container */
struct if_rmap_ctx *if_rmap_ctx;
};
RB_HEAD(ripng_instance_head, ripng);
RB_PROTOTYPE(ripng_instance_head, ripng, entry, ripng_instance_compare)
/* Routing table entry. */
struct rte {
@ -234,6 +266,9 @@ typedef enum {
/* RIPng specific interface configuration. */
struct ripng_interface {
/* Parent routing instance. */
struct ripng *ripng;
/* RIPng is enabled on this interface. */
int enable_network;
int enable_interface;
@ -280,6 +315,9 @@ struct ripng_interface {
/* RIPng peer information. */
struct ripng_peer {
/* Parent routing instance. */
struct ripng *ripng;
/* Peer address. */
struct in6_addr addr;
@ -325,6 +363,9 @@ enum ripng_event {
#define RIPNG_OFFSET_LIST_MAX 2
struct ripng_offset_list {
/* Parent routing instance. */
struct ripng *ripng;
char *ifname;
struct {
@ -335,72 +376,87 @@ struct ripng_offset_list {
};
/* Extern variables. */
extern struct ripng *ripng;
extern struct list *peer_list;
extern struct zebra_privs_t ripngd_privs;
extern struct thread_master *master;
extern struct ripng_instance_head ripng_instances;
/* Prototypes. */
extern void ripng_init(void);
extern void ripng_clean(void);
extern void ripng_clean_network(void);
extern void ripng_interface_clean(void);
extern int ripng_enable_network_add(struct prefix *p);
extern int ripng_enable_network_delete(struct prefix *p);
extern int ripng_enable_if_add(const char *ifname);
extern int ripng_enable_if_delete(const char *ifname);
extern int ripng_passive_interface_set(const char *ifname);
extern int ripng_passive_interface_unset(const char *ifname);
extern void ripng_passive_interface_clean(void);
extern void ripng_clean(struct ripng *ripng);
extern void ripng_clean_network(struct ripng *ripng);
extern void ripng_interface_clean(struct ripng *ripng);
extern int ripng_enable_network_add(struct ripng *ripng, struct prefix *p);
extern int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p);
extern int ripng_enable_if_add(struct ripng *ripng, const char *ifname);
extern int ripng_enable_if_delete(struct ripng *ripng, const char *ifname);
extern int ripng_passive_interface_set(struct ripng *ripng, const char *ifname);
extern int ripng_passive_interface_unset(struct ripng *ripng,
const char *ifname);
extern void ripng_passive_interface_clean(struct ripng *ripng);
extern void ripng_if_init(void);
extern void ripng_route_map_init(void);
extern void ripng_zebra_vrf_register(struct vrf *vrf);
extern void ripng_zebra_vrf_deregister(struct vrf *vrf);
extern void ripng_terminate(void);
/* zclient_init() is done by ripng_zebra.c:zebra_init() */
extern void zebra_init(struct thread_master *);
extern void ripng_zebra_stop(void);
extern void ripng_redistribute_conf_update(int type);
extern void ripng_redistribute_conf_delete(int type);
extern void ripng_redistribute_conf_update(struct ripng *ripng, int type);
extern void ripng_redistribute_conf_delete(struct ripng *ripng, int type);
extern void ripng_peer_init(void);
extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t);
extern void ripng_peer_bad_route(struct sockaddr_in6 *);
extern void ripng_peer_bad_packet(struct sockaddr_in6 *);
extern void ripng_peer_display(struct vty *);
extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *);
extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *);
extern void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
uint8_t version);
extern void ripng_peer_bad_route(struct ripng *ripng,
struct sockaddr_in6 *from);
extern void ripng_peer_bad_packet(struct ripng *ripng,
struct sockaddr_in6 *from);
extern void ripng_peer_display(struct vty *vty, struct ripng *ripng);
extern struct ripng_peer *ripng_peer_lookup(struct ripng *ripng,
struct in6_addr *addr);
extern struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
struct in6_addr *addr);
extern int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2);
extern void ripng_peer_list_del(void *arg);
extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname);
extern struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
const char *ifname);
extern void ripng_offset_list_del(struct ripng_offset_list *offset);
extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *,
uint8_t *);
extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *,
uint8_t *);
extern void ripng_offset_init(void);
extern void ripng_offset_clean(void);
extern struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
const char *ifname);
extern int ripng_offset_list_apply_in(struct ripng *ripng,
struct prefix_ipv6 *p,
struct interface *ifp, uint8_t *metric);
extern int ripng_offset_list_apply_out(struct ripng *ripng,
struct prefix_ipv6 *p,
struct interface *ifp, uint8_t *metric);
extern int offset_list_cmp(struct ripng_offset_list *o1,
struct ripng_offset_list *o2);
extern int ripng_route_rte(struct ripng_info *rinfo);
extern struct ripng_info *ripng_info_new(void);
extern void ripng_info_free(struct ripng_info *rinfo);
extern void ripng_event(enum ripng_event, int);
extern struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo);
extern void ripng_event(struct ripng *ripng, enum ripng_event event, int sock);
extern int ripng_request(struct interface *ifp);
extern void ripng_redistribute_add(int, int, struct prefix_ipv6 *, ifindex_t,
struct in6_addr *, route_tag_t);
extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *,
ifindex_t);
extern void ripng_redistribute_withdraw(int type);
extern void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
struct prefix_ipv6 *p, ifindex_t ifindex,
struct in6_addr *nexthop, route_tag_t tag);
extern void ripng_redistribute_delete(struct ripng *ripng, int type,
int sub_type, struct prefix_ipv6 *p,
ifindex_t ifindex);
extern void ripng_redistribute_withdraw(struct ripng *ripng, int type);
extern void ripng_ecmp_disable(void);
extern void ripng_ecmp_disable(struct ripng *ripng);
extern void ripng_distribute_update_interface(struct interface *);
extern void ripng_if_rmap_update_interface(struct interface *);
extern void ripng_zebra_ipv6_add(struct agg_node *node);
extern void ripng_zebra_ipv6_delete(struct agg_node *node);
extern void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *node);
extern void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *node);
extern void ripng_redistribute_clean(void);
extern int ripng_redistribute_check(int);
extern void ripng_redistribute_write(struct vty *);
extern void ripng_redistribute_enable(struct ripng *ripng);
extern void ripng_redistribute_disable(struct ripng *ripng);
extern int ripng_redistribute_check(struct ripng *ripng, int type);
extern void ripng_redistribute_write(struct vty *vty, struct ripng *ripng);
extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
struct in6_addr *nexthop, uint16_t tag,
@ -423,14 +479,26 @@ extern int ripng_interface_address_add(int command, struct zclient *,
zebra_size_t, vrf_id_t);
extern int ripng_interface_address_delete(int command, struct zclient *,
zebra_size_t, vrf_id_t);
extern int ripng_interface_vrf_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id);
extern void ripng_interface_sync(struct interface *ifp);
extern int ripng_create(int socket);
extern int ripng_make_socket(void);
extern int ripng_network_write(struct vty *);
extern struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id);
extern struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name);
extern struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf,
int socket);
extern int ripng_make_socket(struct vrf *vrf);
extern int ripng_network_write(struct vty *vty, struct ripng *ripng);
extern struct ripng_info *ripng_ecmp_add(struct ripng_info *);
extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *);
extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *);
extern struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
struct ripng_info *rinfo);
extern struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
struct ripng_info *rinfo);
extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
struct ripng_info *rinfo);
extern void ripng_vrf_init(void);
extern void ripng_vrf_terminate(void);
/* Northbound. */
extern void ripng_cli_init(void);

View File

@ -1521,15 +1521,15 @@ DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip",
ROUTER_STR "RIP\n")
DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
ROUTER_STR "RIP\n" VRF_CMD_HELP_STR)
{
vty->node = RIP_NODE;
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng",
ROUTER_STR "RIPng\n")
DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
{
vty->node = RIPNG_NODE;
return CMD_SUCCESS;

View File

@ -20,25 +20,28 @@
]
},
"frr-ripd:ripd": {
"instance": {
"allow-ecmp": "true",
"distance": {
"source": [
"instance": [
{
"vrf": "default",
"allow-ecmp": "true",
"distance": {
"source": [
{
"distance": "25",
"prefix": "172.16.1.0/24"
}
]
},
"redistribute": [
{
"prefix": "172.16.1.0/24",
"distance": "25"
"metric": "3",
"protocol": "ospf"
}
],
"static-route": [
"10.0.1.0/24"
]
},
"redistribute": [
{
"protocol": "ospf",
"metric": "3"
}
],
"static-route": [
"10.0.1.0/24"
]
}
}
]
}
}

View File

@ -18,6 +18,7 @@
</lib>
<ripd xmlns="http://frrouting.org/yang/ripd">
<instance>
<vrf>default</vrf>
<allow-ecmp>true</allow-ecmp>
<static-route>10.0.1.0/24</static-route>
<distance>

View File

@ -34,13 +34,18 @@ module frr-ripd {
container ripd {
/*
* Global configuration data
* Routing instance configuration.
*/
container instance {
presence "Present if the RIP protocol is enabled.";
list instance {
key "vrf";
description
"RIP routing instance.";
leaf vrf {
type string;
description
"VRF name.";
}
leaf allow-ecmp {
type boolean;
default "false";
@ -293,83 +298,83 @@ module frr-ripd {
'(./receive = "2" and ./send = "2") or ' +
'(./receive = "1-2" and ./send = "2")';
}
}
/*
* Operational data.
*/
container state {
config false;
description
"Operational data.";
container neighbors {
/*
* Operational data.
*/
container state {
config false;
description
"Neighbor information.";
list neighbor {
key "address";
"Operational data.";
container neighbors {
description
"A RIP neighbor.";
leaf address {
type inet:ipv4-address;
"Neighbor information.";
list neighbor {
key "address";
description
"IP address that a RIP neighbor is using as its
source address.";
}
leaf last-update {
type yang:date-and-time;
description
"The time when the most recent RIP update was
received from this neighbor.";
}
leaf bad-packets-rcvd {
type yang:counter32;
description
"The number of RIP invalid packets received from
this neighbor which were subsequently discarded
for any reason (e.g. a version 0 packet, or an
unknown command type).";
}
leaf bad-routes-rcvd {
type yang:counter32;
description
"The number of routes received from this neighbor,
in valid RIP packets, which were ignored for any
reason (e.g. unknown address family, or invalid
metric).";
"A RIP neighbor.";
leaf address {
type inet:ipv4-address;
description
"IP address that a RIP neighbor is using as its
source address.";
}
leaf last-update {
type yang:date-and-time;
description
"The time when the most recent RIP update was
received from this neighbor.";
}
leaf bad-packets-rcvd {
type yang:counter32;
description
"The number of RIP invalid packets received from
this neighbor which were subsequently discarded
for any reason (e.g. a version 0 packet, or an
unknown command type).";
}
leaf bad-routes-rcvd {
type yang:counter32;
description
"The number of routes received from this neighbor,
in valid RIP packets, which were ignored for any
reason (e.g. unknown address family, or invalid
metric).";
}
}
}
}
container routes {
description
"Route information.";
list route {
key "prefix";
container routes {
description
"A RIP IPv4 route.";
leaf prefix {
type inet:ipv4-prefix;
"Route information.";
list route {
key "prefix";
description
"IP address (in the form A.B.C.D) and prefix length,
separated by the slash (/) character. The range of
values for the prefix-length is 0 to 32.";
}
leaf next-hop {
type inet:ipv4-address;
description
"Next hop IPv4 address.";
}
leaf interface {
type string;
description
"The interface that the route uses.";
}
leaf metric {
type uint8 {
range "0..16";
"A RIP IPv4 route.";
leaf prefix {
type inet:ipv4-prefix;
description
"IP address (in the form A.B.C.D) and prefix length,
separated by the slash (/) character. The range of
values for the prefix-length is 0 to 32.";
}
leaf next-hop {
type inet:ipv4-address;
description
"Next hop IPv4 address.";
}
leaf interface {
type string;
description
"The interface that the route uses.";
}
leaf metric {
type uint8 {
range "0..16";
}
description
"Route metric.";
}
description
"Route metric.";
}
}
}
@ -547,6 +552,19 @@ module frr-ripd {
description
"Clears RIP routes from the IP routing table and routes
redistributed into the RIP protocol.";
input {
leaf vrf {
type string;
description
"VRF name identifying a specific RIP instance.
This leaf is optional for the rpc.
If it is specified, the rpc will clear all routes in the
specified RIP instance;
if it is not specified, the rpc will clear all routes in
all RIP instances.";
}
}
}
/*

View File

@ -33,13 +33,18 @@ module frr-ripngd {
container ripngd {
/*
* Global configuration data
* Routing instance configuration.
*/
container instance {
presence "Present if the RIPng protocol is enabled.";
list instance {
key "vrf";
description
"RIPng routing instance.";
leaf vrf {
type string;
description
"VRF name.";
}
leaf allow-ecmp {
type boolean;
default "false";
@ -194,82 +199,82 @@ module frr-ripngd {
"Interval at which RIPng updates are sent.";
}
}
}
/*
* Operational data.
*/
container state {
config false;
description
"Operational data.";
container neighbors {
/*
* Operational data.
*/
container state {
config false;
description
"Neighbor information.";
list neighbor {
key "address";
"Operational data.";
container neighbors {
description
"A RIPng neighbor.";
leaf address {
type inet:ipv6-address;
"Neighbor information.";
list neighbor {
key "address";
description
"IPv6 address that a RIPng neighbor is using as its
source address.";
}
leaf last-update {
type yang:date-and-time;
description
"The time when the most recent RIPng update was
received from this neighbor.";
}
leaf bad-packets-rcvd {
type yang:counter32;
description
"The number of RIPng invalid packets received from
this neighbor which were subsequently discarded
for any reason (e.g. a version 0 packet, or an
unknown command type).";
}
leaf bad-routes-rcvd {
type yang:counter32;
description
"The number of routes received from this neighbor,
in valid RIPng packets, which were ignored for any
reason (e.g. unknown address family, or invalid
metric).";
"A RIPng neighbor.";
leaf address {
type inet:ipv6-address;
description
"IPv6 address that a RIPng neighbor is using as its
source address.";
}
leaf last-update {
type yang:date-and-time;
description
"The time when the most recent RIPng update was
received from this neighbor.";
}
leaf bad-packets-rcvd {
type yang:counter32;
description
"The number of RIPng invalid packets received from
this neighbor which were subsequently discarded
for any reason (e.g. a version 0 packet, or an
unknown command type).";
}
leaf bad-routes-rcvd {
type yang:counter32;
description
"The number of routes received from this neighbor,
in valid RIPng packets, which were ignored for any
reason (e.g. unknown address family, or invalid
metric).";
}
}
}
}
container routes {
description
"Route information.";
list route {
key "prefix";
container routes {
description
"A RIPng IPv6 route.";
leaf prefix {
type inet:ipv6-prefix;
"Route information.";
list route {
key "prefix";
description
"IPv6 address and prefix length, in the format
specified in RFC6991.";
}
leaf next-hop {
type inet:ipv6-address;
description
"Next hop IPv6 address.";
}
leaf interface {
type string;
description
"The interface that the route uses.";
}
leaf metric {
type uint8 {
range "0..16";
"A RIPng IPv6 route.";
leaf prefix {
type inet:ipv6-prefix;
description
"IPv6 address and prefix length, in the format
specified in RFC6991.";
}
leaf next-hop {
type inet:ipv6-address;
description
"Next hop IPv6 address.";
}
leaf interface {
type string;
description
"The interface that the route uses.";
}
leaf metric {
type uint8 {
range "0..16";
}
description
"Route metric.";
}
description
"Route metric.";
}
}
}
@ -317,5 +322,18 @@ module frr-ripngd {
description
"Clears RIPng routes from the IPv6 routing table and routes
redistributed into the RIPng protocol.";
input {
leaf vrf {
type string;
description
"VRF name identifying a specific RIPng instance.
This leaf is optional for the rpc.
If it is specified, the rpc will clear all routes in the
specified RIPng instance;
if it is not specified, the rpc will clear all routes in
all RIPng instances.";
}
}
}
}

View File

@ -22,7 +22,7 @@
"mappings": [
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']",
"native": "/frr-ripd:ripd/instance"
"native": "/frr-ripd:ripd/instance[vrf='default']"
}
]
},
@ -32,31 +32,31 @@
"mappings": [
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/default-metric",
"native": "/frr-ripd:ripd/instance/default-metric"
"native": "/frr-ripd:ripd/instance[vrf='default']/default-metric"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/distance",
"native": "/frr-ripd:ripd/instance/distance/default"
"native": "/frr-ripd:ripd/instance[vrf='default']/distance/default"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/originate-default-route/enabled",
"native": "/frr-ripd:ripd/instance/default-information-originate"
"native": "/frr-ripd:ripd/instance[vrf='default']/default-information-originate"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/update-interval",
"native": "/frr-ripd:ripd/instance/timers/update-interval"
"native": "/frr-ripd:ripd/instance[vrf='default']/timers/update-interval"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/holddown-interval",
"native": "/frr-ripd:ripd/instance/timers/holddown-interval"
"native": "/frr-ripd:ripd/instance[vrf='default']/timers/holddown-interval"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/flush-interval",
"native": "/frr-ripd:ripd/instance/timers/flush-interval"
"native": "/frr-ripd:ripd/instance[vrf='default']/timers/flush-interval"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']",
"native": "/frr-ripd:ripd/instance/interface[.='KEY1']"
"native": "/frr-ripd:ripd/instance[vrf='default']/interface[.='KEY1']"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']/split-horizon",
@ -64,43 +64,43 @@
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']",
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/ipv4-address",
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/address"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/address"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/last-update",
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/last-update"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/last-update"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-packets-rcvd",
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-routes-rcvd",
"native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']",
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/ipv4-prefix",
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/prefix"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/prefix"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/next-hop",
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/next-hop"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/next-hop"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/interface",
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/interface"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/interface"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/metric",
"native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/metric"
"native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/metric"
},
{
"custom": "/ietf-rip:clear-rip-route",