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

View File

@ -1297,7 +1297,7 @@ DEFPY (show_yang_operational_data,
yang_dnode_free(dnode); yang_dnode_free(dnode);
return CMD_WARNING; 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. */ /* Display the data. */
if (lyd_print_mem(&strp, dnode, format, 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. */ /* Create a socket for the VRF. */
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
char *interfacename) const char *interfacename)
{ {
int ret, save_errno, ret2; int ret, save_errno, ret2;
@ -944,7 +944,7 @@ vrf_id_t vrf_get_default_id(void)
return VRF_DEFAULT_INTERNAL; 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; 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, int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
char *interfacename) const char *interfacename)
{ {
int ret, save_errno, ret2; int ret, save_errno, ret2;

View File

@ -220,12 +220,12 @@ extern void vrf_terminate(void);
/* Create a socket serving for the given VRF */ /* Create a socket serving for the given VRF */
extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, 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, 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 */ /* VRF ioctl operations */
extern int vrf_getaddrinfo(const char *node, const char *service, 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; 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) static void *ly_dup_cb(const void *priv)
{ {
/* Make a shallow copy of the priv pointer. */ /* 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); 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) * Create and set up a libyang context (for use by the translator)
*/ */

View File

@ -39,31 +39,46 @@
*/ */
DEFPY_NOSH (router_rip, DEFPY_NOSH (router_rip,
router_rip_cmd, router_rip_cmd,
"router rip", "router rip [vrf NAME]",
"Enable a routing process\n" "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; int ret;
nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_CREATE, /* Build RIP instance XPath. */
NULL); 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); ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS) if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(RIP_NODE, "/frr-ripd:ripd/instance"); VTY_PUSH_XPATH(RIP_NODE, xpath);
return ret; return ret;
} }
DEFPY (no_router_rip, DEFPY (no_router_rip,
no_router_rip_cmd, no_router_rip_cmd,
"no router rip", "no router rip [vrf NAME]",
NO_STR NO_STR
"Enable a routing process\n" "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, char xpath[XPATH_MAXLEN];
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_DESTROY, NULL);
return nb_cli_apply_changes(vty, 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, void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
bool show_defaults) bool show_defaults)
{ {
const char *vrf_name;
vrf_name = yang_dnode_get_string(dnode, "./vrf");
vty_out(vty, "!\n"); 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"
"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); NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip"); 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, DEFPY (clear_ip_rip,
clear_ip_rip_cmd, clear_ip_rip_cmd,
"clear ip rip", "clear ip rip [vrf WORD]",
CLEAR_STR CLEAR_STR
IP_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) 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_enable_apply(struct interface *);
static void rip_passive_interface_apply(struct interface *); static void rip_passive_interface_apply(struct interface *);
static int rip_if_down(struct interface *ifp); 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 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"}, const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_2, "2"}, {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"}, {RI_RIP_VERSION_NONE, "none"},
{0}}; {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. */ /* Join to the RIP version 2 multicast group. */
static int ipv4_multicast_join(int sock, struct in_addr group, static int ipv4_multicast_join(int sock, struct in_addr group,
struct in_addr ifa, ifindex_t ifindex) 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, /* If there is no version configuration in the interface,
use rip's version setting. */ 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); : ri->ri_send);
if (vsend & RIPv1) if (vsend & RIPv1)
rip_request_interface_send(ifp, 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 ? */ /* 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; struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) { FOR_ALL_INTERFACES (rip->vrf, ifp) {
struct listnode *cnode; struct listnode *cnode;
struct connected *connected; struct connected *connected;
@ -369,13 +359,14 @@ int rip_interface_down(int command, struct zclient *zclient,
if (ifp == NULL) if (ifp == NULL)
return 0; return 0;
rip_interface_sync(ifp);
rip_if_down(ifp); rip_if_down(ifp);
if (IS_RIP_DEBUG_ZEBRA) if (IS_RIP_DEBUG_ZEBRA)
zlog_debug( zlog_debug(
"interface %s index %d flags %llx metric %d mtu %d is down", "interface %s vrf %u index %d flags %llx metric %d mtu %d is down",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->name, ifp->vrf_id, ifp->ifindex,
ifp->metric, ifp->mtu); (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
return 0; return 0;
} }
@ -395,9 +386,11 @@ int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length,
if (IS_RIP_DEBUG_ZEBRA) if (IS_RIP_DEBUG_ZEBRA)
zlog_debug( zlog_debug(
"interface %s index %d flags %#llx metric %d mtu %d is up", "interface %s vrf %u index %d flags %#llx metric %d mtu %d is up",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->name, ifp->vrf_id, ifp->ifindex,
ifp->metric, ifp->mtu); (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
rip_interface_sync(ifp);
/* Check if this interface is RIP enabled or not.*/ /* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp); rip_enable_apply(ifp);
@ -418,12 +411,13 @@ int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length,
struct interface *ifp; struct interface *ifp;
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
rip_interface_sync(ifp);
if (IS_RIP_DEBUG_ZEBRA) if (IS_RIP_DEBUG_ZEBRA)
zlog_debug( zlog_debug(
"interface add %s index %d flags %#llx metric %d mtu %d", "interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->name, ifp->vrf_id, ifp->ifindex,
ifp->metric, ifp->mtu); (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
/* Check if this interface is RIP enabled or not.*/ /* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp); rip_enable_apply(ifp);
@ -456,13 +450,15 @@ int rip_interface_delete(int command, struct zclient *zclient,
if (ifp == NULL) if (ifp == NULL)
return 0; return 0;
rip_interface_sync(ifp);
if (if_is_up(ifp)) { if (if_is_up(ifp)) {
rip_if_down(ifp); rip_if_down(ifp);
} }
zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", zlog_info(
ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
ifp->metric, ifp->mtu); 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. */ /* To support pseudo interface do not free interface structure. */
/* if_delete(ifp); */ /* if_delete(ifp); */
@ -471,6 +467,28 @@ int rip_interface_delete(int command, struct zclient *zclient,
return 0; 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) static void rip_interface_clean(struct rip_interface *ri)
{ {
ri->enable_network = 0; 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; struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_interface_clean(ifp->info); 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) int rip_if_down(struct interface *ifp)
{ {
struct rip *rip;
struct route_node *rp; struct route_node *rp;
struct rip_info *rinfo; struct rip_info *rinfo;
struct rip_interface *ri = NULL; struct rip_interface *ri = NULL;
struct list *list = NULL; struct list *list = NULL;
struct listnode *listnode = NULL, *nextnode = NULL; struct listnode *listnode = NULL, *nextnode = NULL;
ri = ifp->info;
rip = ri->rip;
if (rip) { if (rip) {
for (rp = route_top(rip->table); rp; rp = route_next(rp)) for (rp = route_top(rip->table); rp; rp = route_next(rp))
if ((list = rp->info) != NULL) if ((list = rp->info) != NULL)
for (ALL_LIST_ELEMENTS(list, listnode, nextnode, for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo)) rinfo))
if (rinfo->nh.ifindex == ifp->ifindex) if (rinfo->nh.ifindex == ifp->ifindex)
rip_ecmp_delete(rinfo); rip_ecmp_delete(rip, rinfo);
ri = ifp->info;
if (ri->running) { if (ri->running) {
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
@ -560,18 +579,10 @@ int rip_if_down(struct interface *ifp)
return 0; 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) 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 prefix_ipv4 address;
struct nexthop nh; struct nexthop nh;
struct prefix *p; 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 /* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */ 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_enable_network_lookup2(ifc) >= 0))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
&address, &nh, 0, 0, 0); RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
0);
} }
int rip_interface_address_add(int command, struct zclient *zclient, 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) 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_ipv4 address;
struct prefix *p; struct prefix *p;
@ -651,7 +665,7 @@ static void rip_apply_address_del(struct connected *ifc)
address.prefixlen = p->prefixlen; address.prefixlen = p->prefixlen;
apply_mask_ipv4(&address); 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); &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. */ * is within the ripng_enable_network table. */
static int rip_enable_network_lookup_if(struct interface *ifp) 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 listnode *node, *nnode;
struct connected *connected; struct connected *connected;
struct prefix_ipv4 address; struct prefix_ipv4 address;
if (!rip)
return -1;
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
struct prefix *p; struct prefix *p;
struct route_node *n; struct route_node *n;
@ -704,7 +723,7 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
address.prefix = p->u.prefix4; address.prefix = p->u.prefix4;
address.prefixlen = IPV4_MAX_BITLEN; address.prefixlen = IPV4_MAX_BITLEN;
n = route_node_match(rip_enable_network, n = route_node_match(rip->enable_network,
(struct prefix *)&address); (struct prefix *)&address);
if (n) { if (n) {
route_unlock_node(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. */ /* 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_ipv4 address;
struct prefix *p; struct prefix *p;
@ -731,8 +752,8 @@ int rip_enable_network_lookup2(struct connected *connected)
address.prefixlen = IPV4_MAX_BITLEN; address.prefixlen = IPV4_MAX_BITLEN;
/* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
* rip_enable_network */ * rip->enable_network */
node = route_node_match(rip_enable_network, node = route_node_match(rip->enable_network,
(struct prefix *)&address); (struct prefix *)&address);
if (node) { if (node) {
@ -744,11 +765,11 @@ int rip_enable_network_lookup2(struct connected *connected)
return -1; return -1;
} }
/* Add RIP enable network. */ /* 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; struct route_node *node;
node = route_node_get(rip_enable_network, p); node = route_node_get(rip->enable_network, p);
if (node->info) { if (node->info) {
route_unlock_node(node); route_unlock_node(node);
@ -757,17 +778,17 @@ int rip_enable_network_add(struct prefix *p)
node->info = (void *)1; node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */ /* XXX: One should find a better solution than a generic one */
rip_enable_apply_all(); rip_enable_apply_all(rip);
return NB_OK; return NB_OK;
} }
/* Delete RIP enable network. */ /* 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; struct route_node *node;
node = route_node_lookup(rip_enable_network, p); node = route_node_lookup(rip->enable_network, p);
if (node) { if (node) {
node->info = NULL; node->info = NULL;
@ -778,7 +799,7 @@ int rip_enable_network_delete(struct prefix *p)
route_unlock_node(node); route_unlock_node(node);
/* XXX: One should find a better solution than a generic one */ /* XXX: One should find a better solution than a generic one */
rip_enable_apply_all(); rip_enable_apply_all(rip);
return NB_OK; return NB_OK;
} }
@ -787,50 +808,53 @@ int rip_enable_network_delete(struct prefix *p)
} }
/* Check interface is enabled by ifname statement. */ /* 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; unsigned int i;
char *str; char *str;
for (i = 0; i < vector_active(rip_enable_interface); i++) if (!rip)
if ((str = vector_slot(rip_enable_interface, i)) != NULL) 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) if (strcmp(str, ifname) == 0)
return i; return i;
return -1; return -1;
} }
/* Add interface to rip_enable_if. */ /* 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; int ret;
ret = rip_enable_if_lookup(ifname); ret = rip_enable_if_lookup(rip, ifname);
if (ret >= 0) if (ret >= 0)
return NB_ERR_INCONSISTENCY; return NB_ERR_INCONSISTENCY;
vector_set(rip_enable_interface, vector_set(rip->enable_interface,
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname)); XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
rip_enable_apply_all(); /* TODOVJ */ rip_enable_apply_all(rip); /* TODOVJ */
return NB_OK; return NB_OK;
} }
/* Delete interface from rip_enable_if. */ /* 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; int index;
char *str; char *str;
index = rip_enable_if_lookup(ifname); index = rip_enable_if_lookup(rip, ifname);
if (index < 0) if (index < 0)
return NB_ERR_INCONSISTENCY; return NB_ERR_INCONSISTENCY;
str = vector_slot(rip_enable_interface, index); str = vector_slot(rip->enable_interface, index);
XFREE(MTYPE_RIP_INTERFACE_STRING, str); 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; return NB_OK;
} }
@ -848,7 +872,7 @@ static int rip_interface_wakeup(struct thread *t)
ri->t_wakeup = NULL; ri->t_wakeup = NULL;
/* Join to multicast group. */ /* 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, flog_err_sys(EC_LIB_SOCKET,
"multicast join failed, interface %s not running", "multicast join failed, interface %s not running",
ifp->name); ifp->name);
@ -866,6 +890,8 @@ static int rip_interface_wakeup(struct thread *t)
static void rip_connect_set(struct interface *ifp, int set) 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 listnode *node, *nnode;
struct connected *connected; struct connected *connected;
struct prefix_ipv4 address; struct prefix_ipv4 address;
@ -890,17 +916,18 @@ static void rip_connect_set(struct interface *ifp, int set)
if (set) { if (set) {
/* Check once more wether this prefix is within a /* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */ * "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_enable_network_lookup2(connected) >= 0))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, RIP_ROUTE_INTERFACE,
&address, &nh, 0, 0, 0); &address, &nh, 0, 0, 0);
} else { } else {
rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, &address, RIP_ROUTE_INTERFACE, &address,
connected->ifp->ifindex); connected->ifp->ifindex);
if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT)) if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_REDISTRIBUTE, RIP_ROUTE_REDISTRIBUTE,
&address, &nh, 0, 0, 0); &address, &nh, 0, 0, 0);
} }
@ -929,7 +956,7 @@ void rip_enable_apply(struct interface *ifp)
ri->enable_network = 0; ri->enable_network = 0;
/* Check interface name configuration. */ /* Check interface name configuration. */
ret = rip_enable_if_lookup(ifp->name); ret = rip_enable_if_lookup(ri->rip, ifp->name);
if (ret >= 0) if (ret >= 0)
ri->enable_interface = 1; ri->enable_interface = 1;
else else
@ -962,17 +989,16 @@ void rip_enable_apply(struct interface *ifp)
} }
/* Apply network configuration to all interface. */ /* 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; struct interface *ifp;
/* Check each interface. */ /* Check each interface. */
FOR_ALL_INTERFACES (vrf, ifp) FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_enable_apply(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 prefix_ipv4 p;
struct route_node *node; struct route_node *node;
@ -991,7 +1017,7 @@ int rip_neighbor_lookup(struct sockaddr_in *from)
} }
/* Add new RIP neighbor to the neighbor tree. */ /* 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; struct route_node *node;
@ -1006,7 +1032,7 @@ int rip_neighbor_add(struct prefix_ipv4 *p)
} }
/* Delete RIP neighbor from the neighbor tree. */ /* 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; struct route_node *node;
@ -1027,50 +1053,51 @@ int rip_neighbor_delete(struct prefix_ipv4 *p)
} }
/* Clear all network and neighbor configuration. */ /* Clear all network and neighbor configuration. */
void rip_clean_network(void) void rip_clean_network(struct rip *rip)
{ {
unsigned int i; unsigned int i;
char *str; char *str;
struct route_node *rn; struct route_node *rn;
/* rip_enable_network. */ /* rip->enable_network. */
for (rn = route_top(rip_enable_network); rn; rn = route_next(rn)) for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
if (rn->info) { if (rn->info) {
rn->info = NULL; rn->info = NULL;
route_unlock_node(rn); route_unlock_node(rn);
} }
/* rip_enable_interface. */ /* rip->enable_interface. */
for (i = 0; i < vector_active(rip_enable_interface); i++) for (i = 0; i < vector_active(rip->enable_interface); i++)
if ((str = vector_slot(rip_enable_interface, i)) != NULL) { if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
XFREE(MTYPE_RIP_INTERFACE_STRING, str); 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. */ /* 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; unsigned int i;
char *str; char *str;
for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) for (i = 0; i < vector_active(rip->passive_nondefault); i++)
if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
if (strcmp(str, ifname) == 0) if (strcmp(str, ifname) == 0)
return i; return i;
return -1; 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; struct rip_interface *ri;
ri = ifp->info;
rip = ri->rip;
if (rip == NULL) if (rip == NULL)
return; return;
ri = ifp->info; ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0)
? rip->passive_default ? rip->passive_default
: !rip->passive_default); : !rip->passive_default);
@ -1079,39 +1106,38 @@ void rip_passive_interface_apply(struct interface *ifp)
ri->passive); 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; struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_passive_interface_apply(ifp); rip_passive_interface_apply(ifp);
} }
/* Passive interface. */ /* 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 * Don't return an error, this can happen after changing
* 'passive-default'. * 'passive-default'.
*/ */
return NB_OK; return NB_OK;
vector_set(Vrip_passive_nondefault, vector_set(rip->passive_nondefault,
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname)); XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
rip_passive_interface_apply_all(); rip_passive_interface_apply_all(rip);
return NB_OK; return NB_OK;
} }
int rip_passive_nondefault_unset(const char *ifname) int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
{ {
int i; int i;
char *str; char *str;
i = rip_passive_nondefault_lookup(ifname); i = rip_passive_nondefault_lookup(rip, ifname);
if (i < 0) if (i < 0)
/* /*
* Don't return an error, this can happen after changing * Don't return an error, this can happen after changing
@ -1119,36 +1145,38 @@ int rip_passive_nondefault_unset(const char *ifname)
*/ */
return NB_OK; return NB_OK;
str = vector_slot(Vrip_passive_nondefault, i); str = vector_slot(rip->passive_nondefault, i);
XFREE(MTYPE_RIP_INTERFACE_STRING, str); 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; return NB_OK;
} }
/* Free all configured RIP passive-interface settings. */ /* Free all configured RIP passive-interface settings. */
void rip_passive_nondefault_clean(void) void rip_passive_nondefault_clean(struct rip *rip)
{ {
unsigned int i; unsigned int i;
char *str; char *str;
for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) for (i = 0; i < vector_active(rip->passive_nondefault); i++)
if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) { if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
XFREE(MTYPE_RIP_INTERFACE_STRING, str); 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. */ /* Write rip configuration of each interface. */
static int rip_interface_config_write(struct vty *vty) static int rip_interface_config_write(struct vty *vty)
{ {
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct vrf *vrf;
struct interface *ifp;
int write = 0; int write = 0;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) { FOR_ALL_INTERFACES (vrf, ifp) {
struct lyd_node *dnode; struct lyd_node *dnode;
@ -1162,18 +1190,19 @@ static int rip_interface_config_write(struct vty *vty)
write = 1; write = 1;
nb_cli_show_dnode_cmds(vty, dnode, false); nb_cli_show_dnode_cmds(vty, dnode, false);
} }
}
return write; return write;
} }
int rip_show_network_config(struct vty *vty) int rip_show_network_config(struct vty *vty, struct rip *rip)
{ {
unsigned int i; unsigned int i;
char *ifname; char *ifname;
struct route_node *node; struct route_node *node;
/* Network type RIP enable interface statement. */ /* 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)) node = route_next(node))
if (node->info) if (node->info)
vty_out(vty, " %s/%u\n", vty_out(vty, " %s/%u\n",
@ -1181,8 +1210,8 @@ int rip_show_network_config(struct vty *vty)
node->p.prefixlen); node->p.prefixlen);
/* Interface name RIP enable statement. */ /* Interface name RIP enable statement. */
for (i = 0; i < vector_active(rip_enable_interface); i++) for (i = 0; i < vector_active(rip->enable_interface); i++)
if ((ifname = vector_slot(rip_enable_interface, i)) != NULL) if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
vty_out(vty, " %s\n", ifname); vty_out(vty, " %s\n", ifname);
/* RIP neighbors listing. */ /* RIP neighbors listing. */
@ -1197,10 +1226,26 @@ static struct cmd_node interface_node = {
INTERFACE_NODE, "%s(config-if)# ", 1, 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. */ /* Called when interface structure allocated. */
static int rip_interface_new_hook(struct interface *ifp) static int rip_interface_new_hook(struct interface *ifp)
{ {
ifp->info = rip_interface_new(); ifp->info = rip_interface_new();
rip_interface_sync(ifp);
return 0; 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_add, 0, rip_interface_new_hook);
hook_register_prio(if_del, 0, rip_interface_delete_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 interface node. */
install_node(&interface_node, rip_interface_config_write); install_node(&interface_node, rip_interface_config_write);
if_cmd_init(); if_cmd_init();

View File

@ -20,6 +20,8 @@
#ifndef _QUAGGA_RIP_INTERFACE_H #ifndef _QUAGGA_RIP_INTERFACE_H
#define _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_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_up(int, struct zclient *, zebra_size_t, vrf_id_t);
extern int rip_interface_add(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); vrf_id_t);
extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t, extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t,
vrf_id_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 */ #endif /* _QUAGGA_RIP_INTERFACE_H */

View File

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

View File

@ -27,6 +27,7 @@
DEFINE_MGROUP(RIPD, "ripd") DEFINE_MGROUP(RIPD, "ripd")
DEFINE_MTYPE(RIPD, RIP, "RIP structure") 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_INFO, "RIP route info")
DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface") DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface")
DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String") DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String")

View File

@ -26,6 +26,7 @@
DECLARE_MGROUP(RIPD) DECLARE_MGROUP(RIPD)
DECLARE_MTYPE(RIP) DECLARE_MTYPE(RIP)
DECLARE_MTYPE(RIP_VRF_NAME)
DECLARE_MTYPE(RIP_INFO) DECLARE_MTYPE(RIP_INFO)
DECLARE_MTYPE(RIP_INTERFACE) DECLARE_MTYPE(RIP_INTERFACE)
DECLARE_MTYPE(RIP_INTERFACE_STRING) 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" #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_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_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_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) #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; struct rip_offset_list *offset;
offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list));
offset->rip = rip;
offset->ifname = strdup(ifname); offset->ifname = strdup(ifname);
listnode_add_sort(rip_offset_list_master, offset); listnode_add_sort(rip->offset_list_master, offset);
return offset; return offset;
} }
void offset_list_del(struct rip_offset_list *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)) if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset)); free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_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); 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 rip_offset_list *offset;
struct listnode *node, *nnode; 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) if (strcmp(offset->ifname, ifname) == 0)
return offset; 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, int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric) uint32_t *metric)
{ {
struct rip_interface *ri = ifp->info;
struct rip_offset_list *offset; struct rip_offset_list *offset;
struct access_list *alist; struct access_list *alist;
/* Look up offset-list with interface name. */ /* 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)) { if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP, 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; return 0;
} }
/* Look up offset-list without interface name. */ /* 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)) { if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP, 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, int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric) uint32_t *metric)
{ {
struct rip_interface *ri = ifp->info;
struct rip_offset_list *offset; struct rip_offset_list *offset;
struct access_list *alist; struct access_list *alist;
/* Look up offset-list with interface name. */ /* 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)) { if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP, alist = access_list_lookup(AFI_IP,
OFFSET_LIST_OUT_NAME(offset)); 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. */ /* 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)) { if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP, alist = access_list_lookup(AFI_IP,
OFFSET_LIST_OUT_NAME(offset)); OFFSET_LIST_OUT_NAME(offset));
@ -146,24 +148,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
return 0; return 0;
} }
static int offset_list_cmp(struct rip_offset_list *o1, int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2)
struct rip_offset_list *o2)
{ {
return strcmp(o1->ifname, o2->ifname); 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" #include "ripd/ripd.h"
/* Linked list of RIP peer. */
struct list *peer_list;
static struct rip_peer *rip_peer_new(void) static struct rip_peer *rip_peer_new(void)
{ {
return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer)); 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) static void rip_peer_free(struct rip_peer *peer)
{ {
RIP_TIMER_OFF(peer->t_timeout);
XFREE(MTYPE_RIP_PEER, peer); 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 rip_peer *peer;
struct listnode *node, *nnode; 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)) if (IPV4_ADDR_SAME(&peer->addr, addr))
return peer; return peer;
} }
return NULL; 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 rip_peer *peer;
struct listnode *node, *nnode; 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)) if (htonl(peer->addr.s_addr) > htonl(addr->s_addr))
return peer; return peer;
} }
@ -72,26 +70,27 @@ static int rip_peer_timeout(struct thread *t)
struct rip_peer *peer; struct rip_peer *peer;
peer = THREAD_ARG(t); peer = THREAD_ARG(t);
listnode_delete(peer_list, peer); listnode_delete(peer->rip->peer_list, peer);
rip_peer_free(peer); rip_peer_free(peer);
return 0; return 0;
} }
/* Get RIP peer. At the same time update timeout thread. */ /* 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; struct rip_peer *peer;
peer = rip_peer_lookup(addr); peer = rip_peer_lookup(rip, addr);
if (peer) { if (peer) {
if (peer->t_timeout) if (peer->t_timeout)
thread_cancel(peer->t_timeout); thread_cancel(peer->t_timeout);
} else { } else {
peer = rip_peer_new(); peer = rip_peer_new();
peer->rip = rip;
peer->addr = *addr; peer->addr = *addr;
listnode_add_sort(peer_list, peer); listnode_add_sort(rip->peer_list, peer);
} }
/* Update timeout thread. */ /* Update timeout thread. */
@ -105,24 +104,24 @@ static struct rip_peer *rip_peer_get(struct in_addr *addr)
return peer; 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; struct rip_peer *peer;
peer = rip_peer_get(&from->sin_addr); peer = rip_peer_get(rip, &from->sin_addr);
peer->version = version; 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; struct rip_peer *peer;
peer = rip_peer_get(&from->sin_addr); peer = rip_peer_get(rip, &from->sin_addr);
peer->recv_badroutes++; 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; struct rip_peer *peer;
peer = rip_peer_get(&from->sin_addr); peer = rip_peer_get(rip, &from->sin_addr);
peer->recv_badpackets++; peer->recv_badpackets++;
} }
@ -155,14 +154,14 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
return buf; return buf;
} }
void rip_peer_display(struct vty *vty) void rip_peer_display(struct vty *vty, struct rip *rip)
{ {
struct rip_peer *peer; struct rip_peer *peer;
struct listnode *node, *nnode; struct listnode *node, *nnode;
#define RIP_UPTIME_LEN 25 #define RIP_UPTIME_LEN 25
char timebuf[RIP_UPTIME_LEN]; 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", vty_out(vty, " %-16s %9d %9d %9d %s\n",
inet_ntoa(peer->addr), peer->recv_badpackets, inet_ntoa(peer->addr), peer->recv_badpackets,
peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT, 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) if (p2->addr.s_addr == p1->addr.s_addr)
return 0; 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; 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(); rip_peer_free(arg);
peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
} }

View File

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

View File

@ -36,7 +36,8 @@
struct zclient *zclient = NULL; struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */ /* 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 list *list = (struct list *)rp->info;
struct zapi_route api; struct zapi_route api;
@ -46,7 +47,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
int count = 0; int count = 0;
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = rip->vrf->vrf_id;
api.type = ZEBRA_ROUTE_RIP; api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST; 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) if (count >= MULTIPATH_NUM)
break; break;
api_nh = &api.nexthops[count]; 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->gate = rinfo->nh.gate;
api_nh->type = NEXTHOP_TYPE_IPV4; api_nh->type = NEXTHOP_TYPE_IPV4;
if (cmd == ZEBRA_ROUTE_ADD) 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); inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
} }
rip_global_route_changes++; rip->counters.route_changes++;
} }
/* Add/update ECMP routes to zebra. */ /* 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. */ /* 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. */ /* Zebra route add and delete treatment. */
static int rip_zebra_read_route(int command, struct zclient *zclient, static int rip_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct rip *rip;
struct zapi_route api; struct zapi_route api;
struct nexthop nh; struct nexthop nh;
rip = rip_lookup_by_vrf_id(vrf_id);
if (!rip) if (!rip)
return 0; return 0;
@ -136,68 +139,95 @@ static int rip_zebra_read_route(int command, struct zclient *zclient,
/* Then fetch IPv4 prefixes. */ /* Then fetch IPv4 prefixes. */
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) 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, (struct prefix_ipv4 *)&api.prefix, &nh,
api.metric, api.distance, api.tag); api.metric, api.distance, api.tag);
else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) 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, (struct prefix_ipv4 *)&api.prefix,
nh.ifindex); nh.ifindex);
return 0; 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, 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) if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, 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. */ /* 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++) { 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; continue;
if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, i, 0, rip->vrf->vrf_id);
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);
} }
} }
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++) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default if (i == zclient->redist_default
|| !vrf_bitmap_check(zclient->redist[AFI_IP][i], || !rip_redistribute_check(rip, i))
VRF_DEFAULT))
continue; continue;
vty_out(vty, " %s", zebra_route_string(i)); 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) static void rip_zebra_connected(struct zclient *zclient)
{ {
zclient_send_reg_requests(zclient, VRF_DEFAULT); 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_address_delete = rip_interface_address_delete;
zclient->interface_up = rip_interface_up; zclient->interface_up = rip_interface_up;
zclient->interface_down = rip_interface_down; 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_add = rip_zebra_read_route;
zclient->redistribute_route_del = 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. */ /* RIP structure. */
struct rip { 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. */ /* RIP socket. */
int sock; int sock;
@ -112,9 +123,12 @@ struct rip {
/* RIP routing information base. */ /* RIP routing information base. */
struct route_table *table; struct route_table *table;
/* RIP neighbor. */ /* RIP static neighbors. */
struct route_table *neighbor; struct route_table *neighbor;
/* Linked list of RIP peers. */
struct list *peer_list;
/* RIP threads. */ /* RIP threads. */
struct thread *t_read; struct thread *t_read;
@ -144,20 +158,46 @@ struct rip {
/* Are we in passive-interface default mode? */ /* Are we in passive-interface default mode? */
bool passive_default; 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 {
bool enabled;
struct { struct {
char *name; char *name;
struct route_map *map; struct route_map *map;
} route_map;
bool metric_config; bool metric_config;
uint8_t metric; uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX]; } redist[ZEBRA_ROUTE_MAX];
/* For distribute-list container */ /* For distribute-list container */
struct distribute_ctx *distribute_ctx; struct distribute_ctx *distribute_ctx;
/* For if_rmap container */ /* For if_rmap container */
struct if_rmap_ctx *if_rmap_ctx; 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. */ /* RIP routing table entry which belong to rip_packet. */
struct rte { struct rte {
@ -225,11 +265,6 @@ struct rip_info {
struct route_node *rp; struct route_node *rp;
uint8_t distance; uint8_t distance;
#ifdef NEW_RIP_TABLE
struct rip_info *next;
struct rip_info *prev;
#endif /* NEW_RIP_TABLE */
}; };
typedef enum { typedef enum {
@ -240,6 +275,9 @@ typedef enum {
/* RIP specific interface configuration. */ /* RIP specific interface configuration. */
struct rip_interface { struct rip_interface {
/* Parent routing instance. */
struct rip *rip;
/* RIP is enabled on this interface. */ /* RIP is enabled on this interface. */
int enable_network; int enable_network;
int enable_interface; int enable_interface;
@ -297,6 +335,9 @@ struct rip_interface {
/* RIP peer information. */ /* RIP peer information. */
struct rip_peer { struct rip_peer {
/* Parent routing instance. */
struct rip *rip;
/* Peer address. */ /* Peer address. */
struct in_addr addr; struct in_addr addr;
@ -369,6 +410,9 @@ enum rip_event {
#define RIP_OFFSET_LIST_MAX 2 #define RIP_OFFSET_LIST_MAX 2
struct rip_offset_list { struct rip_offset_list {
/* Parent routing instance. */
struct rip *rip;
char *ifname; char *ifname;
struct { struct {
@ -380,104 +424,114 @@ struct rip_offset_list {
/* Prototypes. */ /* Prototypes. */
extern void rip_init(void); extern void rip_init(void);
extern void rip_clean(void); extern void rip_clean(struct rip *rip);
extern void rip_clean_network(void); extern void rip_clean_network(struct rip *rip);
extern void rip_interfaces_clean(void); extern void rip_interfaces_clean(struct rip *rip);
extern int rip_passive_nondefault_set(const char *ifname); extern int rip_passive_nondefault_set(struct rip *rip, const char *ifname);
extern int rip_passive_nondefault_unset(const char *ifname); extern int rip_passive_nondefault_unset(struct rip *rip, const char *ifname);
extern void rip_passive_nondefault_clean(void); extern void rip_passive_nondefault_clean(struct rip *rip);
extern void rip_if_init(void); extern void rip_if_init(void);
extern void rip_if_down_all(void);
extern void rip_route_map_init(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_init(struct thread_master *);
extern void rip_zclient_stop(void); extern void rip_zclient_stop(void);
extern int if_check_address(struct in_addr addr); extern int if_check_address(struct rip *rip, struct in_addr addr);
extern int rip_create(int socket); 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, extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
struct connected *); struct connected *);
extern int rip_neighbor_lookup(struct sockaddr_in *); extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from);
extern int rip_neighbor_add(struct prefix_ipv4 *p); extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p);
extern int rip_neighbor_delete(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_add(struct rip *rip, struct prefix *p);
extern int rip_enable_network_delete(struct prefix *p); extern int rip_enable_network_delete(struct rip *rip, struct prefix *p);
extern int rip_enable_if_add(const char *ifname); extern int rip_enable_if_add(struct rip *rip, const char *ifname);
extern int rip_enable_if_delete(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_event(struct rip *rip, enum rip_event event, int sock);
extern void rip_ecmp_disable(void); 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 int rip_redistribute_check(struct rip *rip, int type);
extern void rip_redistribute_conf_update(int type); extern void rip_redistribute_conf_update(struct rip *rip, int type);
extern void rip_redistribute_conf_delete(int type); extern void rip_redistribute_conf_delete(struct rip *rip, int type);
extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, extern void rip_redistribute_add(struct rip *rip, int type, int sub_type,
struct nexthop *nh, unsigned int metric, struct prefix_ipv4 *p, struct nexthop *nh,
unsigned char distance, route_tag_t tag); unsigned int metric, unsigned char distance,
extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t); route_tag_t tag);
extern void rip_redistribute_withdraw(int); extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
extern void rip_zebra_ipv4_add(struct route_node *); struct prefix_ipv4 *p, ifindex_t ifindex);
extern void rip_zebra_ipv4_delete(struct route_node *); 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_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *); extern void rip_distribute_update_interface(struct interface *);
extern void rip_if_rmap_update_interface(struct interface *ifp); 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 int rip_show_network_config(struct vty *vty, struct rip *rip);
extern void rip_peer_update(struct sockaddr_in *, uint8_t); extern void rip_show_redistribute_config(struct vty *vty, struct rip *rip);
extern void rip_peer_bad_route(struct sockaddr_in *);
extern void rip_peer_bad_packet(struct sockaddr_in *); extern void rip_peer_update(struct rip *rip, struct sockaddr_in *from,
extern void rip_peer_display(struct vty *); uint8_t version);
extern struct rip_peer *rip_peer_lookup(struct in_addr *); extern void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from);
extern struct rip_peer *rip_peer_lookup_next(struct in_addr *); 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 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 struct rip_distance *rip_distance_new(void);
extern void rip_distance_free(struct rip_distance *rdistance); extern void rip_distance_free(struct rip_distance *rdistance);
extern uint8_t rip_distance_apply(struct rip_info *); extern uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo);
extern void rip_redistribute_clean(void); 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 int rip_route_rte(struct rip_info *rinfo);
extern struct rip_info *rip_ecmp_add(struct rip_info *); extern struct rip_info *rip_ecmp_add(struct rip *rip,
extern struct rip_info *rip_ecmp_replace(struct rip_info *); struct rip_info *rinfo_new);
extern struct rip_info *rip_ecmp_delete(struct rip_info *); 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 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 *, extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *,
uint32_t *); uint32_t *);
extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *,
uint32_t *); uint32_t *);
extern void rip_offset_init(void); extern int offset_list_cmp(struct rip_offset_list *o1,
extern void rip_offset_clean(void); struct rip_offset_list *o2);
extern void rip_vrf_init(void);
extern void rip_vrf_terminate(void);
/* YANG notifications */ /* YANG notifications */
extern void ripd_notif_send_auth_type_failure(const char *ifname); extern void ripd_notif_send_auth_type_failure(const char *ifname);
extern void ripd_notif_send_auth_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 zebra_privs_t ripd_privs;
extern struct rip_instance_head rip_instances;
/* Master thread strucutre. */ /* Master thread strucutre. */
extern struct thread_master *master; 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_add, (struct connected * ifc), (ifc))
DECLARE_HOOK(rip_ifaddr_del, (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. */ /* Northbound. */
extern void rip_cli_init(void); extern void rip_cli_init(void);
extern const struct frr_yang_module_info frr_ripd_info; extern const struct frr_yang_module_info frr_ripd_info;

View File

@ -39,31 +39,46 @@
*/ */
DEFPY_NOSH (router_ripng, DEFPY_NOSH (router_ripng,
router_ripng_cmd, router_ripng_cmd,
"router ripng", "router ripng [vrf NAME]",
"Enable a routing process\n" "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; int ret;
nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE, /* Build RIPng instance XPath. */
NULL); 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); ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS) if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance"); VTY_PUSH_XPATH(RIPNG_NODE, xpath);
return ret; return ret;
} }
DEFPY (no_router_ripng, DEFPY (no_router_ripng,
no_router_ripng_cmd, no_router_ripng_cmd,
"no router ripng", "no router ripng [vrf NAME]",
NO_STR NO_STR
"Enable a routing process\n" "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, char xpath[XPATH_MAXLEN];
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_DESTROY, NULL);
return nb_cli_apply_changes(vty, 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, void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
bool show_defaults) bool show_defaults)
{ {
const char *vrf_name;
vrf_name = yang_dnode_get_string(dnode, "./vrf");
vty_out(vty, "!\n"); 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, DEFPY (clear_ipv6_rip,
clear_ipv6_rip_cmd, clear_ipv6_rip_cmd,
"clear ipv6 ripng", "clear ipv6 ripng [vrf WORD]",
CLEAR_STR CLEAR_STR
IPV6_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) void ripng_cli_init(void)

View File

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

View File

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

View File

@ -27,6 +27,7 @@
DEFINE_MGROUP(RIPNGD, "ripngd") DEFINE_MGROUP(RIPNGD, "ripngd")
DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure") 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_ROUTE, "RIPng route info")
DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate") DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer") DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer")

View File

@ -26,6 +26,7 @@
DECLARE_MGROUP(RIPNGD) DECLARE_MGROUP(RIPNGD)
DECLARE_MTYPE(RIPNG) DECLARE_MTYPE(RIPNG)
DECLARE_MTYPE(RIPNG_VRF_NAME)
DECLARE_MTYPE(RIPNG_ROUTE) DECLARE_MTYPE(RIPNG_ROUTE)
DECLARE_MTYPE(RIPNG_AGGREGATE) DECLARE_MTYPE(RIPNG_AGGREGATE)
DECLARE_MTYPE(RIPNG_PEER) 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, void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
struct sockaddr_in6 *to) struct sockaddr_in6 *to)
{ {
struct ripng_interface *ri = ifp->info;
struct ripng *ripng = ri->ripng;
struct ripng_rte_data *data; struct ripng_rte_data *data;
struct listnode *node, *nnode; struct listnode *node, *nnode;

View File

@ -32,6 +32,7 @@
#include "libfrr.h" #include "libfrr.h"
#include "ripngd/ripngd.h" #include "ripngd/ripngd.h"
#include "ripngd/ripng_debug.h"
#include "ripngd/ripng_route.h" #include "ripngd/ripng_route.h"
#include "ripngd/ripng_cli.h" #include "ripngd/ripng_cli.h"
@ -42,41 +43,98 @@ static int ripngd_instance_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
struct vrf *vrf;
const char *vrf_name;
int socket; int socket;
vrf_name = yang_dnode_get_string(dnode, "./vrf");
vrf = vrf_lookup_by_name(vrf_name);
/*
* Try to create a RIPng socket only if the VRF is enabled, otherwise
* create a disabled RIPng instance and wait for the VRF to be enabled.
*/
switch (event) { switch (event) {
case NB_EV_VALIDATE: case NB_EV_VALIDATE:
break; break;
case NB_EV_PREPARE: case NB_EV_PREPARE:
socket = ripng_make_socket(); if (!vrf || !vrf_is_enabled(vrf))
break;
socket = ripng_make_socket(vrf);
if (socket < 0) if (socket < 0)
return NB_ERR_RESOURCE; return NB_ERR_RESOURCE;
resource->fd = socket; resource->fd = socket;
break; break;
case NB_EV_ABORT: case NB_EV_ABORT:
if (!vrf || !vrf_is_enabled(vrf))
break;
socket = resource->fd; socket = resource->fd;
close(socket); close(socket);
break; break;
case NB_EV_APPLY: case NB_EV_APPLY:
if (vrf && vrf_is_enabled(vrf))
socket = resource->fd; socket = resource->fd;
ripng_create(socket); else
socket = -1;
ripng = ripng_create(vrf_name, vrf, socket);
yang_dnode_set_entry(dnode, ripng);
break; break;
} }
return NB_OK; return NB_OK;
} }
static int ripngd_instance_delete(enum nb_event event, static int ripngd_instance_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng_clean(); ripng = yang_dnode_get_entry(dnode, true);
ripng_clean(ripng);
return NB_OK; return NB_OK;
} }
static const void *ripngd_instance_get_next(const void *parent_list_entry,
const void *list_entry)
{
const struct ripng *ripng = list_entry;
if (list_entry == NULL)
ripng = RB_MIN(ripng_instance_head, &ripng_instances);
else
ripng = RB_NEXT(ripng_instance_head, (struct ripng *)ripng);
return ripng;
}
static int ripngd_instance_get_keys(const void *list_entry,
struct yang_list_keys *keys)
{
const struct ripng *ripng = list_entry;
keys->num = 1;
strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0]));
return NB_OK;
}
static const void *
ripngd_instance_lookup_entry(const void *parent_list_entry,
const struct yang_list_keys *keys)
{
const char *vrf_name = keys->key[0];
return ripng_lookup_by_vrf_name(vrf_name);
}
/* /*
* XPath: /frr-ripngd:ripngd/instance/allow-ecmp * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
*/ */
@ -84,12 +142,15 @@ static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ripng->ecmp = yang_dnode_get_bool(dnode, NULL); ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
if (!ripng->ecmp) if (!ripng->ecmp)
ripng_ecmp_disable(); ripng_ecmp_disable(ripng);
return NB_OK; return NB_OK;
} }
@ -101,19 +162,22 @@ static int ripngd_instance_default_information_originate_modify(
enum nb_event event, const struct lyd_node *dnode, enum nb_event event, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
bool default_information; bool default_information;
struct prefix_ipv6 p; struct prefix_ipv6 p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
default_information = yang_dnode_get_bool(dnode, NULL); default_information = yang_dnode_get_bool(dnode, NULL);
str2prefix_ipv6("::/0", &p); str2prefix_ipv6("::/0", &p);
if (default_information) { if (default_information) {
ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
&p, 0, NULL, 0); RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
} else { } else {
ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
RIPNG_ROUTE_DEFAULT, &p, 0); RIPNG_ROUTE_DEFAULT, &p, 0);
} }
@ -127,9 +191,12 @@ static int ripngd_instance_default_metric_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ripng->default_metric = yang_dnode_get_uint8(dnode, NULL); ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
return NB_OK; return NB_OK;
@ -142,29 +209,33 @@ static int ripngd_instance_network_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
struct prefix p; struct prefix p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL); yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6((struct prefix_ipv6 *)&p); apply_mask_ipv6((struct prefix_ipv6 *)&p);
return ripng_enable_network_add(&p); return ripng_enable_network_add(ripng, &p);
} }
static int ripngd_instance_network_delete(enum nb_event event, static int ripngd_instance_network_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
struct prefix p; struct prefix p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL); yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6((struct prefix_ipv6 *)&p); apply_mask_ipv6((struct prefix_ipv6 *)&p);
return ripng_enable_network_delete(&p); return ripng_enable_network_delete(ripng, &p);
} }
/* /*
@ -174,27 +245,31 @@ static int ripngd_instance_interface_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
const char *ifname; const char *ifname;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL); ifname = yang_dnode_get_string(dnode, NULL);
return ripng_enable_if_add(ifname); return ripng_enable_if_add(ripng, ifname);
} }
static int ripngd_instance_interface_delete(enum nb_event event, static int ripngd_instance_interface_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
const char *ifname; const char *ifname;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL); ifname = yang_dnode_get_string(dnode, NULL);
return ripng_enable_if_delete(ifname); return ripng_enable_if_delete(ripng, ifname);
} }
/* /*
@ -204,21 +279,23 @@ static int ripngd_instance_offset_list_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
const char *ifname; const char *ifname;
struct ripng_offset_list *offset; struct ripng_offset_list *offset;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, "./interface"); ifname = yang_dnode_get_string(dnode, "./interface");
offset = ripng_offset_list_new(ifname); offset = ripng_offset_list_new(ripng, ifname);
yang_dnode_set_entry(dnode, offset); yang_dnode_set_entry(dnode, offset);
return NB_OK; return NB_OK;
} }
static int ripngd_instance_offset_list_delete(enum nb_event event, static int ripngd_instance_offset_list_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
int direct; int direct;
@ -299,28 +376,32 @@ ripngd_instance_passive_interface_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
const char *ifname; const char *ifname;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL); ifname = yang_dnode_get_string(dnode, NULL);
return ripng_passive_interface_set(ifname); return ripng_passive_interface_set(ripng, ifname);
} }
static int static int
ripngd_instance_passive_interface_delete(enum nb_event event, ripngd_instance_passive_interface_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
const char *ifname; const char *ifname;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL); ifname = yang_dnode_get_string(dnode, NULL);
return ripng_passive_interface_unset(ifname); return ripng_passive_interface_unset(ripng, ifname);
} }
/* /*
@ -330,20 +411,43 @@ static int ripngd_instance_redistribute_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
return NB_OK; struct ripng *ripng;
}
static int ripngd_instance_redistribute_delete(enum nb_event event,
const struct lyd_node *dnode)
{
int type; int type;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol"); type = yang_dnode_get_enum(dnode, "./protocol");
ripng_redistribute_conf_delete(type); ripng->redist[type].enabled = true;
return NB_OK;
}
static int ripngd_instance_redistribute_destroy(enum nb_event event,
const struct lyd_node *dnode)
{
struct ripng *ripng;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol");
ripng->redist[type].enabled = false;
if (ripng->redist[type].route_map.name) {
free(ripng->redist[type].route_map.name);
ripng->redist[type].route_map.name = NULL;
ripng->redist[type].route_map.map = NULL;
}
ripng->redist[type].metric_config = false;
ripng->redist[type].metric = 0;
if (ripng->enabled)
ripng_redistribute_conf_delete(ripng, type);
return NB_OK; return NB_OK;
} }
@ -351,10 +455,14 @@ static int ripngd_instance_redistribute_delete(enum nb_event event,
static void static void
ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode) ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
{ {
struct ripng *ripng;
int type; int type;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol"); type = yang_dnode_get_enum(dnode, "./protocol");
ripng_redistribute_conf_update(type);
if (ripng->enabled)
ripng_redistribute_conf_update(ripng, type);
} }
/* /*
@ -365,37 +473,41 @@ ripngd_instance_redistribute_route_map_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
int type; int type;
const char *rmap_name; const char *rmap_name;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol"); type = yang_dnode_get_enum(dnode, "../protocol");
rmap_name = yang_dnode_get_string(dnode, NULL); rmap_name = yang_dnode_get_string(dnode, NULL);
if (ripng->route_map[type].name) if (ripng->redist[type].route_map.name)
free(ripng->route_map[type].name); free(ripng->redist[type].route_map.name);
ripng->route_map[type].name = strdup(rmap_name); ripng->redist[type].route_map.name = strdup(rmap_name);
ripng->route_map[type].map = route_map_lookup_by_name(rmap_name); ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
return NB_OK; return NB_OK;
} }
static int static int
ripngd_instance_redistribute_route_map_delete(enum nb_event event, ripngd_instance_redistribute_route_map_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
int type; int type;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol"); type = yang_dnode_get_enum(dnode, "../protocol");
free(ripng->route_map[type].name); free(ripng->redist[type].route_map.name);
ripng->route_map[type].name = NULL; ripng->redist[type].route_map.name = NULL;
ripng->route_map[type].map = NULL; ripng->redist[type].route_map.map = NULL;
return NB_OK; return NB_OK;
} }
@ -408,34 +520,38 @@ ripngd_instance_redistribute_metric_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
int type; int type;
uint8_t metric; uint8_t metric;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol"); type = yang_dnode_get_enum(dnode, "../protocol");
metric = yang_dnode_get_uint8(dnode, NULL); metric = yang_dnode_get_uint8(dnode, NULL);
ripng->route_map[type].metric_config = true; ripng->redist[type].metric_config = true;
ripng->route_map[type].metric = metric; ripng->redist[type].metric = metric;
return NB_OK; return NB_OK;
} }
static int static int
ripngd_instance_redistribute_metric_delete(enum nb_event event, ripngd_instance_redistribute_metric_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
int type; int type;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol"); type = yang_dnode_get_enum(dnode, "../protocol");
ripng->route_map[type].metric_config = false; ripng->redist[type].metric_config = false;
ripng->route_map[type].metric = 0; ripng->redist[type].metric = 0;
return NB_OK; return NB_OK;
} }
@ -447,32 +563,37 @@ static int ripngd_instance_static_route_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
struct prefix_ipv6 p; struct prefix_ipv6 p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL); yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p); apply_mask_ipv6(&p);
ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
NULL, 0); 0, NULL, 0);
return NB_OK; return NB_OK;
} }
static int ripngd_instance_static_route_delete(enum nb_event event, static int ripngd_instance_static_route_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
struct prefix_ipv6 p; struct prefix_ipv6 p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL); yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p); apply_mask_ipv6(&p);
ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
&p, 0);
return NB_OK; return NB_OK;
} }
@ -485,32 +606,36 @@ ripngd_instance_aggregate_address_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
struct prefix_ipv6 p; struct prefix_ipv6 p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL); yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p); apply_mask_ipv6(&p);
ripng_aggregate_add((struct prefix *)&p); ripng_aggregate_add(ripng, (struct prefix *)&p);
return NB_OK; return NB_OK;
} }
static int static int
ripngd_instance_aggregate_address_delete(enum nb_event event, ripngd_instance_aggregate_address_destroy(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
struct ripng *ripng;
struct prefix_ipv6 p; struct prefix_ipv6 p;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL); yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p); apply_mask_ipv6(&p);
ripng_aggregate_delete((struct prefix *)&p); ripng_aggregate_delete(ripng, (struct prefix *)&p);
return NB_OK; return NB_OK;
} }
@ -520,8 +645,12 @@ ripngd_instance_aggregate_address_delete(enum nb_event event,
*/ */
static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode) static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
{ {
struct ripng *ripng;
ripng = yang_dnode_get_entry(dnode, true);
/* Reset update timer thread. */ /* Reset update timer thread. */
ripng_event(RIPNG_UPDATE_EVENT, 0); ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
} }
/* /*
@ -532,9 +661,12 @@ ripngd_instance_timers_flush_interval_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL); ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK; return NB_OK;
@ -548,9 +680,12 @@ ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL); ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK; return NB_OK;
@ -564,32 +699,37 @@ ripngd_instance_timers_update_interval_modify(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
struct ripng *ripng;
if (event != NB_EV_APPLY) if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
ripng = yang_dnode_get_entry(dnode, true);
ripng->update_time = yang_dnode_get_uint16(dnode, NULL); ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK; return NB_OK;
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
*/ */
static const void * static const void *
ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry, ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
const void *list_entry) const void *list_entry)
{ {
const struct ripng *ripng = parent_list_entry;
struct listnode *node; struct listnode *node;
if (list_entry == NULL) if (list_entry == NULL)
node = listhead(peer_list); node = listhead(ripng->peer_list);
else else
node = listnextnode((struct listnode *)list_entry); node = listnextnode((struct listnode *)list_entry);
return node; return node;
} }
static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry, static int
ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
struct yang_list_keys *keys) struct yang_list_keys *keys)
{ {
const struct listnode *node = list_entry; const struct listnode *node = list_entry;
@ -602,17 +742,17 @@ static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
return NB_OK; return NB_OK;
} }
static const void * static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, const void *parent_list_entry, const struct yang_list_keys *keys)
const struct yang_list_keys *keys)
{ {
const struct ripng *ripng = parent_list_entry;
struct in6_addr address; struct in6_addr address;
struct ripng_peer *peer; struct ripng_peer *peer;
struct listnode *node; struct listnode *node;
yang_str2ipv6(keys->key[0], &address); yang_str2ipv6(keys->key[0], &address);
for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) { for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) {
if (IPV6_ADDR_SAME(&peer->addr, &address)) if (IPV6_ADDR_SAME(&peer->addr, &address))
return node; return node;
} }
@ -621,11 +761,11 @@ ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath, ripngd_instance_state_neighbors_neighbor_address_get_elem(
const void *list_entry) const char *xpath, const void *list_entry)
{ {
const struct listnode *node = list_entry; const struct listnode *node = list_entry;
const struct ripng_peer *peer = listgetdata(node); const struct ripng_peer *peer = listgetdata(node);
@ -634,21 +774,21 @@ ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath, ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
const void *list_entry) const char *xpath, const void *list_entry)
{ {
/* TODO: yang:date-and-time is tricky */ /* TODO: yang:date-and-time is tricky */
return NULL; return NULL;
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem( ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
const char *xpath, const void *list_entry) const char *xpath, const void *list_entry)
{ {
const struct listnode *node = list_entry; const struct listnode *node = list_entry;
@ -658,11 +798,11 @@ ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath, ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
const void *list_entry) const char *xpath, const void *list_entry)
{ {
const struct listnode *node = list_entry; const struct listnode *node = list_entry;
const struct ripng_peer *peer = listgetdata(node); const struct ripng_peer *peer = listgetdata(node);
@ -671,17 +811,15 @@ ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/routes/route * XPath: /frr-ripngd:ripngd/instance/state/routes/route
*/ */
static const void * static const void *
ripngd_state_routes_route_get_next(const void *parent_list_entry, ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
const void *list_entry) const void *list_entry)
{ {
const struct ripng *ripng = parent_list_entry;
struct agg_node *rn; struct agg_node *rn;
if (ripng == NULL)
return NULL;
if (list_entry == NULL) if (list_entry == NULL)
rn = agg_route_top(ripng->table); rn = agg_route_top(ripng->table);
else else
@ -692,7 +830,8 @@ ripngd_state_routes_route_get_next(const void *parent_list_entry,
return rn; return rn;
} }
static int ripngd_state_routes_route_get_keys(const void *list_entry, static int
ripngd_instance_state_routes_route_get_keys(const void *list_entry,
struct yang_list_keys *keys) struct yang_list_keys *keys)
{ {
const struct agg_node *rn = list_entry; const struct agg_node *rn = list_entry;
@ -703,10 +842,10 @@ static int ripngd_state_routes_route_get_keys(const void *list_entry,
return NB_OK; return NB_OK;
} }
static const void * static const void *ripngd_instance_state_routes_route_lookup_entry(
ripngd_state_routes_route_lookup_entry(const void *parent_list_entry, const void *parent_list_entry, const struct yang_list_keys *keys)
const struct yang_list_keys *keys)
{ {
const struct ripng *ripng = parent_list_entry;
struct prefix prefix; struct prefix prefix;
struct agg_node *rn; struct agg_node *rn;
@ -722,10 +861,10 @@ ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/routes/route/prefix * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_routes_route_prefix_get_elem(const char *xpath, ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
const void *list_entry) const void *list_entry)
{ {
const struct agg_node *rn = list_entry; const struct agg_node *rn = list_entry;
@ -735,10 +874,10 @@ ripngd_state_routes_route_prefix_get_elem(const char *xpath,
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/routes/route/next-hop * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_routes_route_next_hop_get_elem(const char *xpath, ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
const void *list_entry) const void *list_entry)
{ {
const struct agg_node *rn = list_entry; const struct agg_node *rn = list_entry;
@ -748,24 +887,25 @@ ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/routes/route/interface * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_routes_route_interface_get_elem(const char *xpath, ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
const void *list_entry) const void *list_entry)
{ {
const struct agg_node *rn = list_entry; const struct agg_node *rn = list_entry;
const struct ripng_info *rinfo = listnode_head(rn->info); const struct ripng_info *rinfo = listnode_head(rn->info);
const struct ripng *ripng = ripng_info_get_instance(rinfo);
return yang_data_new_string( return yang_data_new_string(
xpath, ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id));
} }
/* /*
* XPath: /frr-ripngd:ripngd/state/routes/route/metric * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric
*/ */
static struct yang_data * static struct yang_data *
ripngd_state_routes_route_metric_get_elem(const char *xpath, ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
const void *list_entry) const void *list_entry)
{ {
const struct agg_node *rn = list_entry; const struct agg_node *rn = list_entry;
@ -777,16 +917,20 @@ ripngd_state_routes_route_metric_get_elem(const char *xpath,
/* /*
* XPath: /frr-ripngd:clear-ripng-route * XPath: /frr-ripngd:clear-ripng-route
*/ */
static int clear_ripng_route_rpc(const char *xpath, const struct list *input, static void clear_ripng_route(struct ripng *ripng)
struct list *output)
{ {
struct agg_node *rp; struct agg_node *rp;
struct ripng_info *rinfo;
struct list *list; if (IS_RIPNG_DEBUG_EVENT)
struct listnode *listnode; zlog_debug("Clearing all RIPng routes (VRF %s)",
ripng->vrf_name);
/* Clear received RIPng routes */ /* Clear received RIPng routes */
for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
struct list *list;
struct listnode *listnode;
struct ripng_info *rinfo;
list = rp->info; list = rp->info;
if (list == NULL) if (list == NULL)
continue; continue;
@ -796,7 +940,7 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
continue; continue;
if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
ripng_zebra_ipv6_delete(rp); ripng_zebra_ipv6_delete(ripng, rp);
break; break;
} }
@ -813,6 +957,30 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
agg_unlock_node(rp); agg_unlock_node(rp);
} }
} }
}
static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
struct list *output)
{
struct ripng *ripng;
struct yang_data *yang_vrf;
yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf");
if (yang_vrf) {
ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
if (ripng)
clear_ripng_route(ripng);
} else {
struct vrf *vrf;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
ripng = vrf->info;
if (!ripng)
continue;
clear_ripng_route(ripng);
}
}
return NB_OK; return NB_OK;
} }
@ -845,7 +1013,10 @@ const struct frr_yang_module_info frr_ripngd_info = {
{ {
.xpath = "/frr-ripngd:ripngd/instance", .xpath = "/frr-ripngd:ripngd/instance",
.cbs.create = ripngd_instance_create, .cbs.create = ripngd_instance_create,
.cbs.destroy = ripngd_instance_delete, .cbs.destroy = ripngd_instance_destroy,
.cbs.get_next = ripngd_instance_get_next,
.cbs.get_keys = ripngd_instance_get_keys,
.cbs.lookup_entry = ripngd_instance_lookup_entry,
.cbs.cli_show = cli_show_router_ripng, .cbs.cli_show = cli_show_router_ripng,
}, },
{ {
@ -866,19 +1037,19 @@ const struct frr_yang_module_info frr_ripngd_info = {
{ {
.xpath = "/frr-ripngd:ripngd/instance/network", .xpath = "/frr-ripngd:ripngd/instance/network",
.cbs.create = ripngd_instance_network_create, .cbs.create = ripngd_instance_network_create,
.cbs.destroy = ripngd_instance_network_delete, .cbs.destroy = ripngd_instance_network_destroy,
.cbs.cli_show = cli_show_ripng_network_prefix, .cbs.cli_show = cli_show_ripng_network_prefix,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/interface", .xpath = "/frr-ripngd:ripngd/instance/interface",
.cbs.create = ripngd_instance_interface_create, .cbs.create = ripngd_instance_interface_create,
.cbs.destroy = ripngd_instance_interface_delete, .cbs.destroy = ripngd_instance_interface_destroy,
.cbs.cli_show = cli_show_ripng_network_interface, .cbs.cli_show = cli_show_ripng_network_interface,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/offset-list", .xpath = "/frr-ripngd:ripngd/instance/offset-list",
.cbs.create = ripngd_instance_offset_list_create, .cbs.create = ripngd_instance_offset_list_create,
.cbs.destroy = ripngd_instance_offset_list_delete, .cbs.destroy = ripngd_instance_offset_list_destroy,
.cbs.cli_show = cli_show_ripng_offset_list, .cbs.cli_show = cli_show_ripng_offset_list,
}, },
{ {
@ -892,36 +1063,36 @@ const struct frr_yang_module_info frr_ripngd_info = {
{ {
.xpath = "/frr-ripngd:ripngd/instance/passive-interface", .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
.cbs.create = ripngd_instance_passive_interface_create, .cbs.create = ripngd_instance_passive_interface_create,
.cbs.destroy = ripngd_instance_passive_interface_delete, .cbs.destroy = ripngd_instance_passive_interface_destroy,
.cbs.cli_show = cli_show_ripng_passive_interface, .cbs.cli_show = cli_show_ripng_passive_interface,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/redistribute", .xpath = "/frr-ripngd:ripngd/instance/redistribute",
.cbs.create = ripngd_instance_redistribute_create, .cbs.create = ripngd_instance_redistribute_create,
.cbs.destroy = ripngd_instance_redistribute_delete, .cbs.destroy = ripngd_instance_redistribute_destroy,
.cbs.apply_finish = ripngd_instance_redistribute_apply_finish, .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
.cbs.cli_show = cli_show_ripng_redistribute, .cbs.cli_show = cli_show_ripng_redistribute,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map", .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
.cbs.modify = ripngd_instance_redistribute_route_map_modify, .cbs.modify = ripngd_instance_redistribute_route_map_modify,
.cbs.destroy = ripngd_instance_redistribute_route_map_delete, .cbs.destroy = ripngd_instance_redistribute_route_map_destroy,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/redistribute/metric", .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
.cbs.modify = ripngd_instance_redistribute_metric_modify, .cbs.modify = ripngd_instance_redistribute_metric_modify,
.cbs.destroy = ripngd_instance_redistribute_metric_delete, .cbs.destroy = ripngd_instance_redistribute_metric_destroy,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/static-route", .xpath = "/frr-ripngd:ripngd/instance/static-route",
.cbs.create = ripngd_instance_static_route_create, .cbs.create = ripngd_instance_static_route_create,
.cbs.destroy = ripngd_instance_static_route_delete, .cbs.destroy = ripngd_instance_static_route_destroy,
.cbs.cli_show = cli_show_ripng_route, .cbs.cli_show = cli_show_ripng_route,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/instance/aggregate-address", .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
.cbs.create = ripngd_instance_aggregate_address_create, .cbs.create = ripngd_instance_aggregate_address_create,
.cbs.destroy = ripngd_instance_aggregate_address_delete, .cbs.destroy = ripngd_instance_aggregate_address_destroy,
.cbs.cli_show = cli_show_ripng_aggregate_address, .cbs.cli_show = cli_show_ripng_aggregate_address,
}, },
{ {
@ -942,48 +1113,48 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs.modify = ripngd_instance_timers_update_interval_modify, .cbs.modify = ripngd_instance_timers_update_interval_modify,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor", .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor",
.cbs.get_next = ripngd_state_neighbors_neighbor_get_next, .cbs.get_next = ripngd_instance_state_neighbors_neighbor_get_next,
.cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys, .cbs.get_keys = ripngd_instance_state_neighbors_neighbor_get_keys,
.cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry, .cbs.lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address", .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
.cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem, .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update", .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
.cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem, .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd", .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd",
.cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem, .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd", .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd",
.cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem, .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/routes/route", .xpath = "/frr-ripngd:ripngd/instance/state/routes/route",
.cbs.get_next = ripngd_state_routes_route_get_next, .cbs.get_next = ripngd_instance_state_routes_route_get_next,
.cbs.get_keys = ripngd_state_routes_route_get_keys, .cbs.get_keys = ripngd_instance_state_routes_route_get_keys,
.cbs.lookup_entry = ripngd_state_routes_route_lookup_entry, .cbs.lookup_entry = ripngd_instance_state_routes_route_lookup_entry,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/routes/route/prefix", .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
.cbs.get_elem = ripngd_state_routes_route_prefix_get_elem, .cbs.get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop", .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
.cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem, .cbs.get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/routes/route/interface", .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
.cbs.get_elem = ripngd_state_routes_route_interface_get_elem, .cbs.get_elem = ripngd_instance_state_routes_route_interface_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:ripngd/state/routes/route/metric", .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
.cbs.get_elem = ripngd_state_routes_route_metric_get_elem, .cbs.get_elem = ripngd_instance_state_routes_route_metric_get_elem,
}, },
{ {
.xpath = "/frr-ripngd:clear-ripng-route", .xpath = "/frr-ripngd:clear-ripng-route",

View File

@ -33,29 +33,29 @@
#include "ripngd/ripngd.h" #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_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_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_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric) #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; struct ripng_offset_list *new;
new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST, new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
sizeof(struct ripng_offset_list)); sizeof(struct ripng_offset_list));
new->ripng = ripng;
new->ifname = strdup(ifname); new->ifname = strdup(ifname);
listnode_add_sort(ripng_offset_list_master, new); listnode_add_sort(ripng->offset_list_master, new);
return new; return new;
} }
void ripng_offset_list_del(struct ripng_offset_list *offset) 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)) if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset)); free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_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); 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 ripng_offset_list *offset;
struct listnode *node, *nnode; 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) if (strcmp(offset->ifname, ifname) == 0)
return offset; return offset;
} }
@ -77,14 +79,14 @@ struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
} }
/* If metric is modifed return 1. */ /* If metric is modifed return 1. */
int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
uint8_t *metric) struct interface *ifp, uint8_t *metric)
{ {
struct ripng_offset_list *offset; struct ripng_offset_list *offset;
struct access_list *alist; struct access_list *alist;
/* Look up offset-list with interface name. */ /* 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)) { if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6, alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset)); OFFSET_LIST_IN_NAME(offset));
@ -98,7 +100,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
return 0; return 0;
} }
/* Look up offset-list without interface name. */ /* 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)) { if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6, alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset)); 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. */ /* If metric is modifed return 1. */
int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p,
uint8_t *metric) struct interface *ifp, uint8_t *metric)
{ {
struct ripng_offset_list *offset; struct ripng_offset_list *offset;
struct access_list *alist; struct access_list *alist;
/* Look up offset-list with interface name. */ /* 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)) { if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6, alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset)); 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. */ /* 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)) { if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6, alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset)); OFFSET_LIST_OUT_NAME(offset));
@ -153,26 +155,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
return 0; return 0;
} }
static int offset_list_cmp(struct ripng_offset_list *o1, int offset_list_cmp(struct ripng_offset_list *o1, struct ripng_offset_list *o2)
struct ripng_offset_list *o2)
{ {
return strcmp(o1->ifname, o2->ifname); 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/ripngd.h"
#include "ripngd/ripng_nexthop.h" #include "ripngd/ripng_nexthop.h"
/* Linked list of RIPng peer. */
struct list *peer_list;
static struct ripng_peer *ripng_peer_new(void) static struct ripng_peer *ripng_peer_new(void)
{ {
return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer)); 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) static void ripng_peer_free(struct ripng_peer *peer)
{ {
RIPNG_TIMER_OFF(peer->t_timeout);
XFREE(MTYPE_RIPNG_PEER, peer); 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 ripng_peer *peer;
struct listnode *node, *nnode; 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)) if (IPV6_ADDR_SAME(&peer->addr, addr))
return peer; return peer;
} }
return NULL; 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 ripng_peer *peer;
struct listnode *node, *nnode; 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) if (addr6_cmp(&peer->addr, addr) > 0)
return peer; return peer;
} }
@ -80,26 +78,28 @@ static int ripng_peer_timeout(struct thread *t)
struct ripng_peer *peer; struct ripng_peer *peer;
peer = THREAD_ARG(t); peer = THREAD_ARG(t);
listnode_delete(peer_list, peer); listnode_delete(peer->ripng->peer_list, peer);
ripng_peer_free(peer); ripng_peer_free(peer);
return 0; return 0;
} }
/* Get RIPng peer. At the same time update timeout thread. */ /* 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; struct ripng_peer *peer;
peer = ripng_peer_lookup(addr); peer = ripng_peer_lookup(ripng, addr);
if (peer) { if (peer) {
if (peer->t_timeout) if (peer->t_timeout)
thread_cancel(peer->t_timeout); thread_cancel(peer->t_timeout);
} else { } else {
peer = ripng_peer_new(); peer = ripng_peer_new();
peer->addr = *addr; /* XXX */ peer->ripng = ripng;
listnode_add_sort(peer_list, peer); peer->addr = *addr;
listnode_add_sort(ripng->peer_list, peer);
} }
/* Update timeout thread. */ /* Update timeout thread. */
@ -113,24 +113,25 @@ static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
return peer; 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; struct ripng_peer *peer;
peer = ripng_peer_get(&from->sin6_addr); peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->version = version; 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; struct ripng_peer *peer;
peer = ripng_peer_get(&from->sin6_addr); peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badroutes++; 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; struct ripng_peer *peer;
peer = ripng_peer_get(&from->sin6_addr); peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badpackets++; peer->recv_badpackets++;
} }
@ -163,14 +164,14 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
return buf; return buf;
} }
void ripng_peer_display(struct vty *vty) void ripng_peer_display(struct vty *vty, struct ripng *ripng)
{ {
struct ripng_peer *peer; struct ripng_peer *peer;
struct listnode *node, *nnode; struct listnode *node, *nnode;
#define RIPNG_UPTIME_LEN 25 #define RIPNG_UPTIME_LEN 25
char timebuf[RIPNG_UPTIME_LEN]; 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", vty_out(vty, " %s \n%14s %10d %10d %10d %s\n",
inet6_ntoa(peer->addr), " ", peer->recv_badpackets, inet6_ntoa(peer->addr), " ", peer->recv_badpackets,
peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT, 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)); 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(); ripng_peer_free(arg);
peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
} }

View File

@ -86,7 +86,7 @@ void ripng_aggregate_decrement_list(struct agg_node *child, struct list *list)
} }
/* RIPng routes treatment. */ /* 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 *top;
struct agg_node *rp; struct agg_node *rp;
@ -124,7 +124,7 @@ int ripng_aggregate_add(struct prefix *p)
} }
/* Delete RIPng static route. */ /* 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 *top;
struct agg_node *rp; struct agg_node *rp;

View File

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

View File

@ -37,7 +37,8 @@
struct zclient *zclient = NULL; struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */ /* 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 list *list = (struct list *)rp->info;
struct zapi_route api; struct zapi_route api;
@ -47,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
int count = 0; int count = 0;
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = ripng->vrf->vrf_id;
api.type = ZEBRA_ROUTE_RIPNG; api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = rp->p; 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) if (count >= MULTIPATH_NUM)
break; break;
api_nh = &api.nexthops[count]; 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->gate.ipv6 = rinfo->nexthop;
api_nh->ifindex = rinfo->ifindex; api_nh->ifindex = rinfo->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV6_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. */ /* 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. */ /* 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. */ /* Zebra route add and delete treatment. */
static int ripng_zebra_read_route(int command, struct zclient *zclient, static int ripng_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct ripng *ripng;
struct zapi_route api; struct zapi_route api;
struct in6_addr nexthop; struct in6_addr nexthop;
unsigned long ifindex; unsigned long ifindex;
ripng = ripng_lookup_by_vrf_id(vrf_id);
if (!ripng)
return 0;
if (zapi_route_decode(zclient->ibuf, &api) < 0) if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1; return -1;
@ -133,69 +139,97 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
ifindex = api.nexthops[0].ifindex; ifindex = api.nexthops[0].ifindex;
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) 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, (struct prefix_ipv6 *)&api.prefix,
ifindex, &nexthop, api.tag); ifindex, &nexthop, api.tag);
else else
ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE, ripng_redistribute_delete(
(struct prefix_ipv6 *)&api.prefix, ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
ifindex); (struct prefix_ipv6 *)&api.prefix, ifindex);
return 0; 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, 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) if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, 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++) { 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; continue;
if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, AFI_IP6, i, 0, ripng->vrf->vrf_id);
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);
} }
} }
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; int i;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default if (i == zclient->redist_default
|| !vrf_bitmap_check(zclient->redist[AFI_IP6][i], || !ripng_redistribute_check(ripng, i))
VRF_DEFAULT))
continue; continue;
vty_out(vty, " %s", zebra_route_string(i)); 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) static void ripng_zebra_connected(struct zclient *zclient)
{ {
zclient_send_reg_requests(zclient, VRF_DEFAULT); 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_delete = ripng_interface_delete;
zclient->interface_address_add = ripng_interface_address_add; zclient->interface_address_add = ripng_interface_address_add;
zclient->interface_address_delete = ripng_interface_address_delete; 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_add = ripng_zebra_read_route;
zclient->redistribute_route_del = 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 <zclient.h>
#include <vty.h> #include <vty.h>
#include <distribute.h> #include <distribute.h>
#include <vector.h>
#include "ripng_memory.h" #include "ripng_memory.h"
@ -88,6 +89,17 @@
/* RIPng structure. */ /* RIPng structure. */
struct ripng { 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. */ /* RIPng socket. */
int sock; int sock;
@ -107,6 +119,21 @@ struct ripng {
/* RIPng routing information base. */ /* RIPng routing information base. */
struct agg_table *table; 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. */ /* RIPng threads. */
struct thread *t_read; struct thread *t_read;
struct thread *t_write; struct thread *t_write;
@ -122,13 +149,16 @@ struct ripng {
/* RIPng ECMP flag */ /* RIPng ECMP flag */
bool ecmp; bool ecmp;
/* For redistribute route map. */ /* RIPng redistribute configuration. */
struct {
bool enabled;
struct { struct {
char *name; char *name;
struct route_map *map; struct route_map *map;
} route_map;
bool metric_config; bool metric_config;
uint8_t metric; uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX]; } redist[ZEBRA_ROUTE_MAX];
/* For distribute-list container */ /* For distribute-list container */
struct distribute_ctx *distribute_ctx; struct distribute_ctx *distribute_ctx;
@ -136,6 +166,8 @@ struct ripng {
/* For if_rmap container */ /* For if_rmap container */
struct if_rmap_ctx *if_rmap_ctx; 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. */ /* Routing table entry. */
struct rte { struct rte {
@ -234,6 +266,9 @@ typedef enum {
/* RIPng specific interface configuration. */ /* RIPng specific interface configuration. */
struct ripng_interface { struct ripng_interface {
/* Parent routing instance. */
struct ripng *ripng;
/* RIPng is enabled on this interface. */ /* RIPng is enabled on this interface. */
int enable_network; int enable_network;
int enable_interface; int enable_interface;
@ -280,6 +315,9 @@ struct ripng_interface {
/* RIPng peer information. */ /* RIPng peer information. */
struct ripng_peer { struct ripng_peer {
/* Parent routing instance. */
struct ripng *ripng;
/* Peer address. */ /* Peer address. */
struct in6_addr addr; struct in6_addr addr;
@ -325,6 +363,9 @@ enum ripng_event {
#define RIPNG_OFFSET_LIST_MAX 2 #define RIPNG_OFFSET_LIST_MAX 2
struct ripng_offset_list { struct ripng_offset_list {
/* Parent routing instance. */
struct ripng *ripng;
char *ifname; char *ifname;
struct { struct {
@ -335,72 +376,87 @@ struct ripng_offset_list {
}; };
/* Extern variables. */ /* Extern variables. */
extern struct ripng *ripng;
extern struct list *peer_list;
extern struct zebra_privs_t ripngd_privs; extern struct zebra_privs_t ripngd_privs;
extern struct thread_master *master; extern struct thread_master *master;
extern struct ripng_instance_head ripng_instances;
/* Prototypes. */ /* Prototypes. */
extern void ripng_init(void); extern void ripng_init(void);
extern void ripng_clean(void); extern void ripng_clean(struct ripng *ripng);
extern void ripng_clean_network(void); extern void ripng_clean_network(struct ripng *ripng);
extern void ripng_interface_clean(void); extern void ripng_interface_clean(struct ripng *ripng);
extern int ripng_enable_network_add(struct prefix *p); extern int ripng_enable_network_add(struct ripng *ripng, struct prefix *p);
extern int ripng_enable_network_delete(struct prefix *p); extern int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p);
extern int ripng_enable_if_add(const char *ifname); extern int ripng_enable_if_add(struct ripng *ripng, const char *ifname);
extern int ripng_enable_if_delete(const char *ifname); extern int ripng_enable_if_delete(struct ripng *ripng, const char *ifname);
extern int ripng_passive_interface_set(const char *ifname); extern int ripng_passive_interface_set(struct ripng *ripng, const char *ifname);
extern int ripng_passive_interface_unset(const char *ifname); extern int ripng_passive_interface_unset(struct ripng *ripng,
extern void ripng_passive_interface_clean(void); const char *ifname);
extern void ripng_passive_interface_clean(struct ripng *ripng);
extern void ripng_if_init(void); extern void ripng_if_init(void);
extern void ripng_route_map_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); extern void ripng_terminate(void);
/* zclient_init() is done by ripng_zebra.c:zebra_init() */ /* zclient_init() is done by ripng_zebra.c:zebra_init() */
extern void zebra_init(struct thread_master *); extern void zebra_init(struct thread_master *);
extern void ripng_zebra_stop(void); extern void ripng_zebra_stop(void);
extern void ripng_redistribute_conf_update(int type); extern void ripng_redistribute_conf_update(struct ripng *ripng, int type);
extern void ripng_redistribute_conf_delete(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 ripng *ripng, struct sockaddr_in6 *from,
extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t); uint8_t version);
extern void ripng_peer_bad_route(struct sockaddr_in6 *); extern void ripng_peer_bad_route(struct ripng *ripng,
extern void ripng_peer_bad_packet(struct sockaddr_in6 *); struct sockaddr_in6 *from);
extern void ripng_peer_display(struct vty *); extern void ripng_peer_bad_packet(struct ripng *ripng,
extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *); struct sockaddr_in6 *from);
extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *); 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 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(struct ripng *ripng,
extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname); const char *ifname);
extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *, extern int ripng_offset_list_apply_in(struct ripng *ripng,
uint8_t *); struct prefix_ipv6 *p,
extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *, struct interface *ifp, uint8_t *metric);
uint8_t *); extern int ripng_offset_list_apply_out(struct ripng *ripng,
extern void ripng_offset_init(void); struct prefix_ipv6 *p,
extern void ripng_offset_clean(void); 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 int ripng_route_rte(struct ripng_info *rinfo);
extern struct ripng_info *ripng_info_new(void); extern struct ripng_info *ripng_info_new(void);
extern void ripng_info_free(struct ripng_info *rinfo); 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 int ripng_request(struct interface *ifp);
extern void ripng_redistribute_add(int, int, struct prefix_ipv6 *, ifindex_t, extern void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
struct in6_addr *, route_tag_t); struct prefix_ipv6 *p, ifindex_t ifindex,
extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *, struct in6_addr *nexthop, route_tag_t tag);
ifindex_t); extern void ripng_redistribute_delete(struct ripng *ripng, int type,
extern void ripng_redistribute_withdraw(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_distribute_update_interface(struct interface *);
extern void ripng_if_rmap_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_add(struct ripng *ripng, struct agg_node *node);
extern void ripng_zebra_ipv6_delete(struct agg_node *node); extern void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *node);
extern void ripng_redistribute_clean(void); extern void ripng_redistribute_enable(struct ripng *ripng);
extern int ripng_redistribute_check(int); extern void ripng_redistribute_disable(struct ripng *ripng);
extern void ripng_redistribute_write(struct vty *); 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, extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
struct in6_addr *nexthop, uint16_t tag, 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); zebra_size_t, vrf_id_t);
extern int ripng_interface_address_delete(int command, struct zclient *, extern int ripng_interface_address_delete(int command, struct zclient *,
zebra_size_t, vrf_id_t); 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 struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id);
extern int ripng_make_socket(void); extern struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name);
extern int ripng_network_write(struct vty *); 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_add(struct ripng *ripng,
extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *); struct ripng_info *rinfo);
extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *); 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. */ /* Northbound. */
extern void ripng_cli_init(void); extern void ripng_cli_init(void);

View File

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

View File

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

View File

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

View File

@ -34,13 +34,18 @@ module frr-ripd {
container ripd { container ripd {
/* /*
* Global configuration data * Routing instance configuration.
*/ */
container instance { list instance {
presence "Present if the RIP protocol is enabled."; key "vrf";
description description
"RIP routing instance."; "RIP routing instance.";
leaf vrf {
type string;
description
"VRF name.";
}
leaf allow-ecmp { leaf allow-ecmp {
type boolean; type boolean;
default "false"; default "false";
@ -293,7 +298,6 @@ module frr-ripd {
'(./receive = "2" and ./send = "2") or ' + '(./receive = "2" and ./send = "2") or ' +
'(./receive = "1-2" and ./send = "2")'; '(./receive = "1-2" and ./send = "2")';
} }
}
/* /*
* Operational data. * Operational data.
@ -375,6 +379,7 @@ module frr-ripd {
} }
} }
} }
}
/* /*
* Per-interface configuration data * Per-interface configuration data
@ -547,6 +552,19 @@ module frr-ripd {
description description
"Clears RIP routes from the IP routing table and routes "Clears RIP routes from the IP routing table and routes
redistributed into the RIP protocol."; 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 { container ripngd {
/* /*
* Global configuration data * Routing instance configuration.
*/ */
container instance { list instance {
presence "Present if the RIPng protocol is enabled."; key "vrf";
description description
"RIPng routing instance."; "RIPng routing instance.";
leaf vrf {
type string;
description
"VRF name.";
}
leaf allow-ecmp { leaf allow-ecmp {
type boolean; type boolean;
default "false"; default "false";
@ -194,7 +199,6 @@ module frr-ripngd {
"Interval at which RIPng updates are sent."; "Interval at which RIPng updates are sent.";
} }
} }
}
/* /*
* Operational data. * Operational data.
@ -275,6 +279,7 @@ module frr-ripngd {
} }
} }
} }
}
/* /*
* Per-interface configuration data * Per-interface configuration data
@ -317,5 +322,18 @@ module frr-ripngd {
description description
"Clears RIPng routes from the IPv6 routing table and routes "Clears RIPng routes from the IPv6 routing table and routes
redistributed into the RIPng protocol."; 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": [ "mappings": [
{ {
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']", "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": [ "mappings": [
{ {
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/default-metric", "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", "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", "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", "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", "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", "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']", "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", "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']", "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", "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", "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", "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", "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']", "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", "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", "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", "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", "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", "custom": "/ietf-rip:clear-rip-route",