summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/if.c12
-rw-r--r--lib/northbound_cli.c2
-rw-r--r--lib/vrf.c6
-rw-r--r--lib/vrf.h6
-rw-r--r--lib/yang.c19
-rw-r--r--lib/yang.h15
-rw-r--r--ripd/rip_cli.c62
-rw-r--r--ripd/rip_interface.c310
-rw-r--r--ripd/rip_interface.h5
-rw-r--r--ripd/rip_main.c12
-rw-r--r--ripd/rip_memory.c1
-rw-r--r--ripd/rip_memory.h1
-rw-r--r--ripd/rip_northbound.c512
-rw-r--r--ripd/rip_offset.c43
-rw-r--r--ripd/rip_peer.c44
-rw-r--r--ripd/rip_snmp.c29
-rw-r--r--ripd/rip_zebra.c89
-rw-r--r--ripd/ripd.c894
-rw-r--r--ripd/ripd.h200
-rw-r--r--ripngd/ripng_cli.c60
-rw-r--r--ripngd/ripng_interface.c309
-rw-r--r--ripngd/ripng_main.c12
-rw-r--r--ripngd/ripng_memory.c1
-rw-r--r--ripngd/ripng_memory.h1
-rw-r--r--ripngd/ripng_nexthop.c3
-rw-r--r--ripngd/ripng_northbound.c449
-rw-r--r--ripngd/ripng_offset.c53
-rw-r--r--ripngd/ripng_peer.c50
-rw-r--r--ripngd/ripng_route.c4
-rw-r--r--ripngd/ripng_route.h4
-rw-r--r--ripngd/ripng_zebra.c95
-rw-r--r--ripngd/ripngd.c731
-rw-r--r--ripngd/ripngd.h182
-rw-r--r--vtysh/vtysh.c8
-rw-r--r--yang/example/ripd.json37
-rw-r--r--yang/example/ripd.xml1
-rw-r--r--yang/frr-ripd.yang160
-rw-r--r--yang/frr-ripngd.yang158
-rw-r--r--yang/ietf/frr-ietf-translator.json36
39 files changed, 2901 insertions, 1715 deletions
diff --git a/lib/if.c b/lib/if.c
index 5fdeb4540..8945159aa 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1310,8 +1310,8 @@ static int lib_interface_create(enum nb_event event,
return NB_OK;
}
-static int lib_interface_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int lib_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
struct interface *ifp;
@@ -1357,8 +1357,8 @@ static int lib_interface_description_modify(enum nb_event event,
return NB_OK;
}
-static int lib_interface_description_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int lib_interface_description_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
struct interface *ifp;
@@ -1378,13 +1378,13 @@ const struct frr_yang_module_info frr_interface_info = {
{
.xpath = "/frr-interface:lib/interface",
.cbs.create = lib_interface_create,
- .cbs.destroy = lib_interface_delete,
+ .cbs.destroy = lib_interface_destroy,
.cbs.cli_show = cli_show_interface,
},
{
.xpath = "/frr-interface:lib/interface/description",
.cbs.modify = lib_interface_description_modify,
- .cbs.destroy = lib_interface_description_delete,
+ .cbs.destroy = lib_interface_description_destroy,
.cbs.cli_show = cli_show_interface_desc,
},
{
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 33035de31..917b04810 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -1297,7 +1297,7 @@ DEFPY (show_yang_operational_data,
yang_dnode_free(dnode);
return CMD_WARNING;
}
- lyd_validate(&dnode, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, ly_ctx);
+ lyd_validate(&dnode, LYD_OPT_GET, ly_ctx);
/* Display the data. */
if (lyd_print_mem(&strp, dnode, format,
diff --git a/lib/vrf.c b/lib/vrf.c
index bc289be9c..e1898ead2 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -573,7 +573,7 @@ static int vrf_default_accepts_vrf(int type)
/* Create a socket for the VRF. */
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
- char *interfacename)
+ const char *interfacename)
{
int ret, save_errno, ret2;
@@ -944,7 +944,7 @@ vrf_id_t vrf_get_default_id(void)
return VRF_DEFAULT_INTERNAL;
}
-int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
+int vrf_bind(vrf_id_t vrf_id, int fd, const char *name)
{
int ret = 0;
@@ -1003,7 +1003,7 @@ int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
}
int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
- char *interfacename)
+ const char *interfacename)
{
int ret, save_errno, ret2;
diff --git a/lib/vrf.h b/lib/vrf.h
index d8fedf911..ca253e58a 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -220,12 +220,12 @@ extern void vrf_terminate(void);
/* Create a socket serving for the given VRF */
extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
- char *name);
+ const char *name);
extern int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
- char *name);
+ const char *name);
-extern int vrf_bind(vrf_id_t vrf_id, int fd, char *name);
+extern int vrf_bind(vrf_id_t vrf_id, int fd, const char *name);
/* VRF ioctl operations */
extern int vrf_getaddrinfo(const char *node, const char *service,
diff --git a/lib/yang.c b/lib/yang.c
index 1d8e82eb2..7982d14fd 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -610,6 +610,25 @@ struct list *yang_data_list_new(void)
return list;
}
+struct yang_data *yang_data_list_find(const struct list *list,
+ const char *xpath_fmt, ...)
+{
+ char xpath[XPATH_MAXLEN];
+ struct yang_data *data;
+ struct listnode *node;
+ va_list ap;
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ for (ALL_LIST_ELEMENTS_RO(list, node, data))
+ if (strmatch(data->xpath, xpath))
+ return data;
+
+ return NULL;
+}
+
static void *ly_dup_cb(const void *priv)
{
/* Make a shallow copy of the priv pointer. */
diff --git a/lib/yang.h b/lib/yang.h
index 885218272..15f0ec7ae 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -514,6 +514,21 @@ extern void yang_data_free(struct yang_data *data);
extern struct list *yang_data_list_new(void);
/*
+ * Find the yang_data structure corresponding to an XPath in a list.
+ *
+ * list
+ * list of yang_data structures to operate on.
+ *
+ * xpath_fmt
+ * XPath to search for (format string).
+ *
+ * Returns:
+ * Pointer to yang_data if found, NULL otherwise.
+ */
+extern struct yang_data *yang_data_list_find(const struct list *list,
+ const char *xpath_fmt, ...);
+
+/*
* Create and set up a libyang context (for use by the translator)
*/
extern struct ly_ctx *yang_ctx_new_setup(void);
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index 62aaad5d9..346e93b8e 100644
--- a/ripd/rip_cli.c
+++ b/ripd/rip_cli.c
@@ -39,31 +39,46 @@
*/
DEFPY_NOSH (router_rip,
router_rip_cmd,
- "router rip",
+ "router rip [vrf NAME]",
"Enable a routing process\n"
- "Routing Information Protocol (RIP)\n")
+ "Routing Information Protocol (RIP)\n"
+ VRF_CMD_HELP_STR)
{
+ char xpath[XPATH_MAXLEN];
int ret;
- nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_CREATE,
- NULL);
+ /* Build RIP instance XPath. */
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
+ snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
+ vrf);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS)
- VTY_PUSH_XPATH(RIP_NODE, "/frr-ripd:ripd/instance");
+ VTY_PUSH_XPATH(RIP_NODE, xpath);
return ret;
}
DEFPY (no_router_rip,
no_router_rip_cmd,
- "no router rip",
+ "no router rip [vrf NAME]",
NO_STR
"Enable a routing process\n"
- "Routing Information Protocol (RIP)\n")
+ "Routing Information Protocol (RIP)\n"
+ VRF_CMD_HELP_STR)
{
- nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_DESTROY,
- NULL);
+ char xpath[XPATH_MAXLEN];
+
+ /* Build RIP instance XPath. */
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
+ snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
+ vrf);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
@@ -71,8 +86,15 @@ DEFPY (no_router_rip,
void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
+ const char *vrf_name;
+
+ vrf_name = yang_dnode_get_string(dnode, "./vrf");
+
vty_out(vty, "!\n");
- vty_out(vty, "router rip\n");
+ vty_out(vty, "router rip");
+ if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
+ vty_out(vty, " vrf %s", vrf_name);
+ vty_out(vty, "\n");
}
/*
@@ -902,7 +924,7 @@ DEFPY (no_ip_rip_authentication_string,
"Authentication string\n"
"Authentication string\n")
{
- nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
+ nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
@@ -970,12 +992,24 @@ void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
*/
DEFPY (clear_ip_rip,
clear_ip_rip_cmd,
- "clear ip rip",
+ "clear ip rip [vrf WORD]",
CLEAR_STR
IP_STR
- "Clear IP RIP database\n")
+ "Clear IP RIP database\n"
+ VRF_CMD_HELP_STR)
{
- return nb_cli_rpc("/frr-ripd:clear-rip-route", NULL, NULL);
+ struct list *input;
+
+ input = list_new();
+ if (vrf) {
+ struct yang_data *yang_vrf;
+
+ yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf",
+ vrf);
+ listnode_add(input, yang_vrf);
+ }
+
+ return nb_cli_rpc("/frr-ripd:clear-rip-route", input, NULL);
}
void rip_cli_init(void)
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 8bad6b8b1..b909cbcb2 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -50,9 +50,9 @@ DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
static void rip_enable_apply(struct interface *);
static void rip_passive_interface_apply(struct interface *);
static int rip_if_down(struct interface *ifp);
-static int rip_enable_if_lookup(const char *ifname);
+static int rip_enable_if_lookup(struct rip *rip, const char *ifname);
static int rip_enable_network_lookup2(struct connected *connected);
-static void rip_enable_apply_all(void);
+static void rip_enable_apply_all(struct rip *rip);
const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_2, "2"},
@@ -60,15 +60,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
{RI_RIP_VERSION_NONE, "none"},
{0}};
-/* RIP enabled network vector. */
-vector rip_enable_interface;
-
-/* RIP enabled interface table. */
-struct route_table *rip_enable_network;
-
-/* Vector to store passive-interface name. */
-vector Vrip_passive_nondefault;
-
/* Join to the RIP version 2 multicast group. */
static int ipv4_multicast_join(int sock, struct in_addr group,
struct in_addr ifa, ifindex_t ifindex)
@@ -208,7 +199,7 @@ static void rip_request_interface(struct interface *ifp)
/* If there is no version configuration in the interface,
use rip's version setting. */
- vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send
+ vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send
: ri->ri_send);
if (vsend & RIPv1)
rip_request_interface_send(ifp, RIPv1);
@@ -329,12 +320,11 @@ static int rip_if_ipv4_address_check(struct interface *ifp)
/* Does this address belongs to me ? */
-int if_check_address(struct in_addr addr)
+int if_check_address(struct rip *rip, struct in_addr addr)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (rip->vrf, ifp) {
struct listnode *cnode;
struct connected *connected;
@@ -369,13 +359,14 @@ int rip_interface_down(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
+ rip_interface_sync(ifp);
rip_if_down(ifp);
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
- "interface %s index %d flags %llx metric %d mtu %d is down",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu);
+ "interface %s vrf %u index %d flags %llx metric %d mtu %d is down",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
return 0;
}
@@ -395,9 +386,11 @@ int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length,
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
- "interface %s index %d flags %#llx metric %d mtu %d is up",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu);
+ "interface %s vrf %u index %d flags %#llx metric %d mtu %d is up",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+
+ rip_interface_sync(ifp);
/* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp);
@@ -418,12 +411,13 @@ int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length,
struct interface *ifp;
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
+ rip_interface_sync(ifp);
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
- "interface add %s index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu);
+ "interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
/* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp);
@@ -456,13 +450,15 @@ int rip_interface_delete(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
+ rip_interface_sync(ifp);
if (if_is_up(ifp)) {
rip_if_down(ifp);
}
- zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu);
+ zlog_info(
+ "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
/* To support pseudo interface do not free interface structure. */
/* if_delete(ifp); */
@@ -471,6 +467,28 @@ int rip_interface_delete(int command, struct zclient *zclient,
return 0;
}
+/* VRF update for an interface. */
+int rip_interface_vrf_update(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct interface *ifp;
+ vrf_id_t new_vrf_id;
+
+ ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
+ &new_vrf_id);
+ if (!ifp)
+ return 0;
+
+ if (IS_RIP_DEBUG_ZEBRA)
+ zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
+ ifp->name, vrf_id, new_vrf_id);
+
+ if_update_to_new_vrf(ifp, new_vrf_id);
+ rip_interface_sync(ifp);
+
+ return 0;
+}
+
static void rip_interface_clean(struct rip_interface *ri)
{
ri->enable_network = 0;
@@ -483,12 +501,11 @@ static void rip_interface_clean(struct rip_interface *ri)
}
}
-void rip_interfaces_clean(void)
+void rip_interfaces_clean(struct rip *rip)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- FOR_ALL_INTERFACES (vrf, ifp)
+ FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_interface_clean(ifp->info);
}
@@ -531,20 +548,22 @@ static void rip_interface_reset(struct rip_interface *ri)
int rip_if_down(struct interface *ifp)
{
+ struct rip *rip;
struct route_node *rp;
struct rip_info *rinfo;
struct rip_interface *ri = NULL;
struct list *list = NULL;
struct listnode *listnode = NULL, *nextnode = NULL;
+
+ ri = ifp->info;
+ rip = ri->rip;
if (rip) {
for (rp = route_top(rip->table); rp; rp = route_next(rp))
if ((list = rp->info) != NULL)
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo))
if (rinfo->nh.ifindex == ifp->ifindex)
- rip_ecmp_delete(rinfo);
-
- ri = ifp->info;
+ rip_ecmp_delete(rip, rinfo);
if (ri->running) {
if (IS_RIP_DEBUG_EVENT)
@@ -560,18 +579,10 @@ int rip_if_down(struct interface *ifp)
return 0;
}
-/* Needed for stop RIP process. */
-void rip_if_down_all(void)
-{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp;
-
- FOR_ALL_INTERFACES (vrf, ifp)
- rip_if_down(ifp);
-}
-
static void rip_apply_address_add(struct connected *ifc)
{
+ struct rip_interface *ri = ifc->ifp->info;
+ struct rip *rip = ri->rip;
struct prefix_ipv4 address;
struct nexthop nh;
struct prefix *p;
@@ -597,10 +608,11 @@ static void rip_apply_address_add(struct connected *ifc)
/* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */
- if ((rip_enable_if_lookup(ifc->ifp->name) >= 0)
+ if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
|| (rip_enable_network_lookup2(ifc) >= 0))
- rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
- &address, &nh, 0, 0, 0);
+ rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
+ RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
+ 0);
}
int rip_interface_address_add(int command, struct zclient *zclient,
@@ -634,6 +646,8 @@ int rip_interface_address_add(int command, struct zclient *zclient,
static void rip_apply_address_del(struct connected *ifc)
{
+ struct rip_interface *ri = ifc->ifp->info;
+ struct rip *rip = ri->rip;
struct prefix_ipv4 address;
struct prefix *p;
@@ -651,7 +665,7 @@ static void rip_apply_address_del(struct connected *ifc)
address.prefixlen = p->prefixlen;
apply_mask_ipv4(&address);
- rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+ rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, ifc->ifp->ifindex);
}
@@ -689,10 +703,15 @@ int rip_interface_address_delete(int command, struct zclient *zclient,
* is within the ripng_enable_network table. */
static int rip_enable_network_lookup_if(struct interface *ifp)
{
+ struct rip_interface *ri = ifp->info;
+ struct rip *rip = ri->rip;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv4 address;
+ if (!rip)
+ return -1;
+
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
struct prefix *p;
struct route_node *n;
@@ -704,7 +723,7 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
address.prefix = p->u.prefix4;
address.prefixlen = IPV4_MAX_BITLEN;
- n = route_node_match(rip_enable_network,
+ n = route_node_match(rip->enable_network,
(struct prefix *)&address);
if (n) {
route_unlock_node(n);
@@ -716,8 +735,10 @@ static int rip_enable_network_lookup_if(struct interface *ifp)
}
/* Check wether connected is within the ripng_enable_network table. */
-int rip_enable_network_lookup2(struct connected *connected)
+static int rip_enable_network_lookup2(struct connected *connected)
{
+ struct rip_interface *ri = connected->ifp->info;
+ struct rip *rip = ri->rip;
struct prefix_ipv4 address;
struct prefix *p;
@@ -731,8 +752,8 @@ int rip_enable_network_lookup2(struct connected *connected)
address.prefixlen = IPV4_MAX_BITLEN;
/* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
- * rip_enable_network */
- node = route_node_match(rip_enable_network,
+ * rip->enable_network */
+ node = route_node_match(rip->enable_network,
(struct prefix *)&address);
if (node) {
@@ -744,11 +765,11 @@ int rip_enable_network_lookup2(struct connected *connected)
return -1;
}
/* Add RIP enable network. */
-int rip_enable_network_add(struct prefix *p)
+int rip_enable_network_add(struct rip *rip, struct prefix *p)
{
struct route_node *node;
- node = route_node_get(rip_enable_network, p);
+ node = route_node_get(rip->enable_network, p);
if (node->info) {
route_unlock_node(node);
@@ -757,17 +778,17 @@ int rip_enable_network_add(struct prefix *p)
node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */
- rip_enable_apply_all();
+ rip_enable_apply_all(rip);
return NB_OK;
}
/* Delete RIP enable network. */
-int rip_enable_network_delete(struct prefix *p)
+int rip_enable_network_delete(struct rip *rip, struct prefix *p)
{
struct route_node *node;
- node = route_node_lookup(rip_enable_network, p);
+ node = route_node_lookup(rip->enable_network, p);
if (node) {
node->info = NULL;
@@ -778,7 +799,7 @@ int rip_enable_network_delete(struct prefix *p)
route_unlock_node(node);
/* XXX: One should find a better solution than a generic one */
- rip_enable_apply_all();
+ rip_enable_apply_all(rip);
return NB_OK;
}
@@ -787,50 +808,53 @@ int rip_enable_network_delete(struct prefix *p)
}
/* Check interface is enabled by ifname statement. */
-static int rip_enable_if_lookup(const char *ifname)
+static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
{
unsigned int i;
char *str;
- for (i = 0; i < vector_active(rip_enable_interface); i++)
- if ((str = vector_slot(rip_enable_interface, i)) != NULL)
+ if (!rip)
+ return -1;
+
+ for (i = 0; i < vector_active(rip->enable_interface); i++)
+ if ((str = vector_slot(rip->enable_interface, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
}
/* Add interface to rip_enable_if. */
-int rip_enable_if_add(const char *ifname)
+int rip_enable_if_add(struct rip *rip, const char *ifname)
{
int ret;
- ret = rip_enable_if_lookup(ifname);
+ ret = rip_enable_if_lookup(rip, ifname);
if (ret >= 0)
return NB_ERR_INCONSISTENCY;
- vector_set(rip_enable_interface,
+ vector_set(rip->enable_interface,
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
- rip_enable_apply_all(); /* TODOVJ */
+ rip_enable_apply_all(rip); /* TODOVJ */
return NB_OK;
}
/* Delete interface from rip_enable_if. */
-int rip_enable_if_delete(const char *ifname)
+int rip_enable_if_delete(struct rip *rip, const char *ifname)
{
int index;
char *str;
- index = rip_enable_if_lookup(ifname);
+ index = rip_enable_if_lookup(rip, ifname);
if (index < 0)
return NB_ERR_INCONSISTENCY;
- str = vector_slot(rip_enable_interface, index);
+ str = vector_slot(rip->enable_interface, index);
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
- vector_unset(rip_enable_interface, index);
+ vector_unset(rip->enable_interface, index);
- rip_enable_apply_all(); /* TODOVJ */
+ rip_enable_apply_all(rip); /* TODOVJ */
return NB_OK;
}
@@ -848,7 +872,7 @@ static int rip_interface_wakeup(struct thread *t)
ri->t_wakeup = NULL;
/* Join to multicast group. */
- if (rip_multicast_join(ifp, rip->sock) < 0) {
+ if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"multicast join failed, interface %s not running",
ifp->name);
@@ -866,6 +890,8 @@ static int rip_interface_wakeup(struct thread *t)
static void rip_connect_set(struct interface *ifp, int set)
{
+ struct rip_interface *ri = ifp->info;
+ struct rip *rip = ri->rip;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv4 address;
@@ -890,17 +916,18 @@ static void rip_connect_set(struct interface *ifp, int set)
if (set) {
/* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */
- if ((rip_enable_if_lookup(connected->ifp->name) >= 0)
+ if ((rip_enable_if_lookup(rip, connected->ifp->name)
+ >= 0)
|| (rip_enable_network_lookup2(connected) >= 0))
- rip_redistribute_add(ZEBRA_ROUTE_CONNECT,
+ rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE,
&address, &nh, 0, 0, 0);
} else {
- rip_redistribute_delete(ZEBRA_ROUTE_CONNECT,
+ rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_INTERFACE, &address,
connected->ifp->ifindex);
- if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT))
- rip_redistribute_add(ZEBRA_ROUTE_CONNECT,
+ if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
+ rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
RIP_ROUTE_REDISTRIBUTE,
&address, &nh, 0, 0, 0);
}
@@ -929,7 +956,7 @@ void rip_enable_apply(struct interface *ifp)
ri->enable_network = 0;
/* Check interface name configuration. */
- ret = rip_enable_if_lookup(ifp->name);
+ ret = rip_enable_if_lookup(ri->rip, ifp->name);
if (ret >= 0)
ri->enable_interface = 1;
else
@@ -962,17 +989,16 @@ void rip_enable_apply(struct interface *ifp)
}
/* Apply network configuration to all interface. */
-void rip_enable_apply_all(void)
+static void rip_enable_apply_all(struct rip *rip)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
/* Check each interface. */
- FOR_ALL_INTERFACES (vrf, ifp)
+ FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_enable_apply(ifp);
}
-int rip_neighbor_lookup(struct sockaddr_in *from)
+int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
{
struct prefix_ipv4 p;
struct route_node *node;
@@ -991,7 +1017,7 @@ int rip_neighbor_lookup(struct sockaddr_in *from)
}
/* Add new RIP neighbor to the neighbor tree. */
-int rip_neighbor_add(struct prefix_ipv4 *p)
+int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
{
struct route_node *node;
@@ -1006,7 +1032,7 @@ int rip_neighbor_add(struct prefix_ipv4 *p)
}
/* Delete RIP neighbor from the neighbor tree. */
-int rip_neighbor_delete(struct prefix_ipv4 *p)
+int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
{
struct route_node *node;
@@ -1027,50 +1053,51 @@ int rip_neighbor_delete(struct prefix_ipv4 *p)
}
/* Clear all network and neighbor configuration. */
-void rip_clean_network(void)
+void rip_clean_network(struct rip *rip)
{
unsigned int i;
char *str;
struct route_node *rn;
- /* rip_enable_network. */
- for (rn = route_top(rip_enable_network); rn; rn = route_next(rn))
+ /* rip->enable_network. */
+ for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
if (rn->info) {
rn->info = NULL;
route_unlock_node(rn);
}
- /* rip_enable_interface. */
- for (i = 0; i < vector_active(rip_enable_interface); i++)
- if ((str = vector_slot(rip_enable_interface, i)) != NULL) {
+ /* rip->enable_interface. */
+ for (i = 0; i < vector_active(rip->enable_interface); i++)
+ if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
- vector_slot(rip_enable_interface, i) = NULL;
+ vector_slot(rip->enable_interface, i) = NULL;
}
}
/* Utility function for looking up passive interface settings. */
-static int rip_passive_nondefault_lookup(const char *ifname)
+static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
{
unsigned int i;
char *str;
- for (i = 0; i < vector_active(Vrip_passive_nondefault); i++)
- if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL)
+ for (i = 0; i < vector_active(rip->passive_nondefault); i++)
+ if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
}
-void rip_passive_interface_apply(struct interface *ifp)
+static void rip_passive_interface_apply(struct interface *ifp)
{
+ struct rip *rip;
struct rip_interface *ri;
+ ri = ifp->info;
+ rip = ri->rip;
if (rip == NULL)
return;
- ri = ifp->info;
-
- ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0)
+ ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
? rip->passive_default
: !rip->passive_default);
@@ -1079,39 +1106,38 @@ void rip_passive_interface_apply(struct interface *ifp)
ri->passive);
}
-static void rip_passive_interface_apply_all(void)
+static void rip_passive_interface_apply_all(struct rip *rip)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- FOR_ALL_INTERFACES (vrf, ifp)
+ FOR_ALL_INTERFACES (rip->vrf, ifp)
rip_passive_interface_apply(ifp);
}
/* Passive interface. */
-int rip_passive_nondefault_set(const char *ifname)
+int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
{
- if (rip_passive_nondefault_lookup(ifname) >= 0)
+ if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
/*
* Don't return an error, this can happen after changing
* 'passive-default'.
*/
return NB_OK;
- vector_set(Vrip_passive_nondefault,
+ vector_set(rip->passive_nondefault,
XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
- rip_passive_interface_apply_all();
+ rip_passive_interface_apply_all(rip);
return NB_OK;
}
-int rip_passive_nondefault_unset(const char *ifname)
+int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
{
int i;
char *str;
- i = rip_passive_nondefault_lookup(ifname);
+ i = rip_passive_nondefault_lookup(rip, ifname);
if (i < 0)
/*
* Don't return an error, this can happen after changing
@@ -1119,61 +1145,64 @@ int rip_passive_nondefault_unset(const char *ifname)
*/
return NB_OK;
- str = vector_slot(Vrip_passive_nondefault, i);
+ str = vector_slot(rip->passive_nondefault, i);
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
- vector_unset(Vrip_passive_nondefault, i);
+ vector_unset(rip->passive_nondefault, i);
- rip_passive_interface_apply_all();
+ rip_passive_interface_apply_all(rip);
return NB_OK;
}
/* Free all configured RIP passive-interface settings. */
-void rip_passive_nondefault_clean(void)
+void rip_passive_nondefault_clean(struct rip *rip)
{
unsigned int i;
char *str;
- for (i = 0; i < vector_active(Vrip_passive_nondefault); i++)
- if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) {
+ for (i = 0; i < vector_active(rip->passive_nondefault); i++)
+ if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
- vector_slot(Vrip_passive_nondefault, i) = NULL;
+ vector_slot(rip->passive_nondefault, i) = NULL;
}
- rip_passive_interface_apply_all();
+ rip_passive_interface_apply_all(rip);
}
/* Write rip configuration of each interface. */
static int rip_interface_config_write(struct vty *vty)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp;
+ struct vrf *vrf;
int write = 0;
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ struct interface *ifp;
- dnode = yang_dnode_get(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct lyd_node *dnode;
+
+ dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+ ifp->name, vrf->name);
+ if (dnode == NULL)
+ continue;
- write = 1;
- nb_cli_show_dnode_cmds(vty, dnode, false);
+ write = 1;
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+ }
}
return write;
}
-int rip_show_network_config(struct vty *vty)
+int rip_show_network_config(struct vty *vty, struct rip *rip)
{
unsigned int i;
char *ifname;
struct route_node *node;
/* Network type RIP enable interface statement. */
- for (node = route_top(rip_enable_network); node;
+ for (node = route_top(rip->enable_network); node;
node = route_next(node))
if (node->info)
vty_out(vty, " %s/%u\n",
@@ -1181,8 +1210,8 @@ int rip_show_network_config(struct vty *vty)
node->p.prefixlen);
/* Interface name RIP enable statement. */
- for (i = 0; i < vector_active(rip_enable_interface); i++)
- if ((ifname = vector_slot(rip_enable_interface, i)) != NULL)
+ for (i = 0; i < vector_active(rip->enable_interface); i++)
+ if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
vty_out(vty, " %s\n", ifname);
/* RIP neighbors listing. */
@@ -1197,10 +1226,26 @@ static struct cmd_node interface_node = {
INTERFACE_NODE, "%s(config-if)# ", 1,
};
+void rip_interface_sync(struct interface *ifp)
+{
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(ifp->vrf_id);
+ if (vrf) {
+ struct rip_interface *ri;
+
+ ri = ifp->info;
+ if (ri)
+ ri->rip = vrf->info;
+ }
+}
+
/* Called when interface structure allocated. */
static int rip_interface_new_hook(struct interface *ifp)
{
ifp->info = rip_interface_new();
+ rip_interface_sync(ifp);
+
return 0;
}
@@ -1220,13 +1265,6 @@ void rip_if_init(void)
hook_register_prio(if_add, 0, rip_interface_new_hook);
hook_register_prio(if_del, 0, rip_interface_delete_hook);
- /* RIP network init. */
- rip_enable_interface = vector_init(1);
- rip_enable_network = route_table_init();
-
- /* RIP passive interface. */
- Vrip_passive_nondefault = vector_init(1);
-
/* Install interface node. */
install_node(&interface_node, rip_interface_config_write);
if_cmd_init();
diff --git a/ripd/rip_interface.h b/ripd/rip_interface.h
index 8723388e7..303be0315 100644
--- a/ripd/rip_interface.h
+++ b/ripd/rip_interface.h
@@ -20,6 +20,8 @@
#ifndef _QUAGGA_RIP_INTERFACE_H
#define _QUAGGA_RIP_INTERFACE_H
+#include "zclient.h"
+
extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t);
extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t);
extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t);
@@ -28,5 +30,8 @@ extern int rip_interface_address_add(int, struct zclient *, zebra_size_t,
vrf_id_t);
extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t,
vrf_id_t);
+extern int rip_interface_vrf_update(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id);
+extern void rip_interface_sync(struct interface *ifp);
#endif /* _QUAGGA_RIP_INTERFACE_H */
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index 5db9c4b7e..65da51f83 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -34,6 +34,7 @@
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
+#include "if_rmap.h"
#include "libfrr.h"
#include "ripd/ripd.h"
@@ -46,7 +47,7 @@
static struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
/* ripd privileges */
-zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
+zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
struct zebra_privs_t ripd_privs = {
#if defined(FRR_USER)
@@ -59,7 +60,7 @@ struct zebra_privs_t ripd_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
- .cap_num_p = 2,
+ .cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
/* Master of threads. */
@@ -81,8 +82,8 @@ static void sigint(void)
{
zlog_notice("Terminating on signal");
- rip_clean();
-
+ rip_vrf_terminate();
+ if_rmap_terminate();
rip_zclient_stop();
frr_fini();
@@ -171,14 +172,13 @@ int main(int argc, char **argv)
/* Library initialization. */
rip_error_init();
keychain_init();
- vrf_init(NULL, NULL, NULL, NULL, NULL);
+ rip_vrf_init();
/* RIP related initialization. */
rip_init();
rip_if_init();
rip_cli_init();
rip_zclient_init(master);
- rip_peer_init();
frr_config_fork();
frr_run(master);
diff --git a/ripd/rip_memory.c b/ripd/rip_memory.c
index 185241074..7d703a86d 100644
--- a/ripd/rip_memory.c
+++ b/ripd/rip_memory.c
@@ -27,6 +27,7 @@
DEFINE_MGROUP(RIPD, "ripd")
DEFINE_MTYPE(RIPD, RIP, "RIP structure")
+DEFINE_MTYPE(RIPD, RIP_VRF_NAME, "RIP VRF name")
DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info")
DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface")
DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String")
diff --git a/ripd/rip_memory.h b/ripd/rip_memory.h
index 29013ecec..1f9d8f500 100644
--- a/ripd/rip_memory.h
+++ b/ripd/rip_memory.h
@@ -26,6 +26,7 @@
DECLARE_MGROUP(RIPD)
DECLARE_MTYPE(RIP)
+DECLARE_MTYPE(RIP_VRF_NAME)
DECLARE_MTYPE(RIP_INFO)
DECLARE_MTYPE(RIP_INTERFACE)
DECLARE_MTYPE(RIP_INTERFACE_STRING)
diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c
index f3b5dc2dc..c1ff678f2 100644
--- a/ripd/rip_northbound.c
+++ b/ripd/rip_northbound.c
@@ -31,6 +31,7 @@
#include "libfrr.h"
#include "ripd/ripd.h"
+#include "ripd/rip_debug.h"
#include "ripd/rip_cli.h"
/*
@@ -40,41 +41,97 @@ static int ripd_instance_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+ struct vrf *vrf;
+ const char *vrf_name;
int socket;
+ vrf_name = yang_dnode_get_string(dnode, "./vrf");
+ vrf = vrf_lookup_by_name(vrf_name);
+
+ /*
+ * Try to create a RIP socket only if the VRF is enabled, otherwise
+ * create a disabled RIP instance and wait for the VRF to be enabled.
+ */
switch (event) {
case NB_EV_VALIDATE:
break;
case NB_EV_PREPARE:
- socket = rip_create_socket();
+ if (!vrf || !vrf_is_enabled(vrf))
+ break;
+
+ socket = rip_create_socket(vrf);
if (socket < 0)
return NB_ERR_RESOURCE;
resource->fd = socket;
break;
case NB_EV_ABORT:
+ if (!vrf || !vrf_is_enabled(vrf))
+ break;
+
socket = resource->fd;
close(socket);
break;
case NB_EV_APPLY:
- socket = resource->fd;
- rip_create(socket);
+ if (vrf && vrf_is_enabled(vrf))
+ socket = resource->fd;
+ else
+ socket = -1;
+
+ rip = rip_create(vrf_name, vrf, socket);
+ yang_dnode_set_entry(dnode, rip);
break;
}
return NB_OK;
}
-static int ripd_instance_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
- rip_clean();
+ rip = yang_dnode_get_entry(dnode, true);
+ rip_clean(rip);
return NB_OK;
}
+static const void *ripd_instance_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ const struct rip *rip = list_entry;
+
+ if (list_entry == NULL)
+ rip = RB_MIN(rip_instance_head, &rip_instances);
+ else
+ rip = RB_NEXT(rip_instance_head, (struct rip *)rip);
+
+ return rip;
+}
+
+static int ripd_instance_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
+{
+ const struct rip *rip = list_entry;
+
+ keys->num = 1;
+ strlcpy(keys->key[0], rip->vrf_name, sizeof(keys->key[0]));
+
+ return NB_OK;
+}
+
+static const void *ripd_instance_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys)
+{
+ const char *vrf_name = keys->key[0];
+
+ return rip_lookup_by_vrf_name(vrf_name);
+}
+
/*
* XPath: /frr-ripd:ripd/instance/allow-ecmp
*/
@@ -82,12 +139,15 @@ static int ripd_instance_allow_ecmp_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->ecmp = yang_dnode_get_bool(dnode, NULL);
if (!rip->ecmp)
- rip_ecmp_disable();
+ rip_ecmp_disable(rip);
return NB_OK;
}
@@ -100,12 +160,14 @@ ripd_instance_default_information_originate_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
bool default_information;
struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
default_information = yang_dnode_get_bool(dnode, NULL);
memset(&p, 0, sizeof(struct prefix_ipv4));
@@ -115,11 +177,11 @@ ripd_instance_default_information_originate_modify(enum nb_event event,
memset(&nh, 0, sizeof(nh));
nh.type = NEXTHOP_TYPE_IPV4;
- rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
- &nh, 0, 0, 0);
+ rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT,
+ &p, &nh, 0, 0, 0);
} else {
- rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
- 0);
+ rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT,
+ &p, 0);
}
return NB_OK;
@@ -132,9 +194,12 @@ static int ripd_instance_default_metric_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->default_metric = yang_dnode_get_uint8(dnode, NULL);
/* rip_update_default_metric (); */
@@ -148,9 +213,12 @@ static int ripd_instance_distance_default_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->distance = yang_dnode_get_uint8(dnode, NULL);
return NB_OK;
@@ -163,6 +231,7 @@ static int ripd_instance_distance_source_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
struct prefix_ipv4 prefix;
struct route_node *rn;
@@ -173,15 +242,16 @@ static int ripd_instance_distance_source_create(enum nb_event event,
apply_mask_ipv4(&prefix);
/* Get RIP distance node. */
- rn = route_node_get(rip_distance_table, (struct prefix *)&prefix);
+ rip = yang_dnode_get_entry(dnode, true);
+ rn = route_node_get(rip->distance_table, (struct prefix *)&prefix);
rn->info = rip_distance_new();
yang_dnode_set_entry(dnode, rn);
return NB_OK;
}
-static int ripd_instance_distance_source_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_distance_source_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
struct route_node *rn;
struct rip_distance *rdistance;
@@ -191,10 +261,7 @@ static int ripd_instance_distance_source_delete(enum nb_event event,
rn = yang_dnode_get_entry(dnode, true);
rdistance = rn->info;
- if (rdistance->access_list)
- free(rdistance->access_list);
rip_distance_free(rdistance);
-
rn->info = NULL;
route_unlock_node(rn);
@@ -253,8 +320,8 @@ ripd_instance_distance_source_access_list_modify(enum nb_event event,
}
static int
-ripd_instance_distance_source_access_list_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripd_instance_distance_source_access_list_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
struct route_node *rn;
struct rip_distance *rdistance;
@@ -278,31 +345,35 @@ static int ripd_instance_explicit_neighbor_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
- return rip_neighbor_add(&p);
+ return rip_neighbor_add(rip, &p);
}
-static int ripd_instance_explicit_neighbor_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_explicit_neighbor_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
- return rip_neighbor_delete(&p);
+ return rip_neighbor_delete(rip, &p);
}
/*
@@ -312,29 +383,33 @@ static int ripd_instance_network_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
struct prefix p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv4p(&p, dnode, NULL);
apply_mask_ipv4((struct prefix_ipv4 *)&p);
- return rip_enable_network_add(&p);
+ return rip_enable_network_add(rip, &p);
}
-static int ripd_instance_network_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_network_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
struct prefix p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv4p(&p, dnode, NULL);
apply_mask_ipv4((struct prefix_ipv4 *)&p);
- return rip_enable_network_delete(&p);
+ return rip_enable_network_delete(rip, &p);
}
/*
@@ -344,27 +419,31 @@ static int ripd_instance_interface_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return rip_enable_if_add(ifname);
+ return rip_enable_if_add(rip, ifname);
}
-static int ripd_instance_interface_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return rip_enable_if_delete(ifname);
+ return rip_enable_if_delete(rip, ifname);
}
/*
@@ -374,22 +453,24 @@ static int ripd_instance_offset_list_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
const char *ifname;
struct rip_offset_list *offset;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, "./interface");
- offset = rip_offset_list_new(ifname);
+ offset = rip_offset_list_new(rip, ifname);
yang_dnode_set_entry(dnode, offset);
return NB_OK;
}
-static int ripd_instance_offset_list_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_offset_list_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
int direct;
struct rip_offset_list *offset;
@@ -467,11 +548,14 @@ static int ripd_instance_passive_default_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->passive_default = yang_dnode_get_bool(dnode, NULL);
- rip_passive_nondefault_clean();
+ rip_passive_nondefault_clean(rip);
return NB_OK;
}
@@ -483,27 +567,31 @@ static int ripd_instance_passive_interface_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return rip_passive_nondefault_set(ifname);
+ return rip_passive_nondefault_set(rip, ifname);
}
-static int ripd_instance_passive_interface_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_passive_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return rip_passive_nondefault_unset(ifname);
+ return rip_passive_nondefault_unset(rip, ifname);
}
/*
@@ -514,28 +602,32 @@ ripd_instance_non_passive_interface_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return rip_passive_nondefault_unset(ifname);
+ return rip_passive_nondefault_unset(rip, ifname);
}
static int
-ripd_instance_non_passive_interface_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripd_instance_non_passive_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return rip_passive_nondefault_set(ifname);
+ return rip_passive_nondefault_set(rip, ifname);
}
/*
@@ -545,20 +637,43 @@ static int ripd_instance_redistribute_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ rip = yang_dnode_get_entry(dnode, true);
+ type = yang_dnode_get_enum(dnode, "./protocol");
+
+ rip->redist[type].enabled = true;
+
return NB_OK;
}
-static int ripd_instance_redistribute_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_redistribute_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol");
- rip_redistribute_conf_delete(type);
+ rip->redist[type].enabled = false;
+ if (rip->redist[type].route_map.name) {
+ free(rip->redist[type].route_map.name);
+ rip->redist[type].route_map.name = NULL;
+ rip->redist[type].route_map.map = NULL;
+ }
+ rip->redist[type].metric_config = false;
+ rip->redist[type].metric = 0;
+
+ if (rip->enabled)
+ rip_redistribute_conf_delete(rip, type);
return NB_OK;
}
@@ -566,10 +681,14 @@ static int ripd_instance_redistribute_delete(enum nb_event event,
static void
ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
{
+ struct rip *rip;
int type;
+ rip = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol");
- rip_redistribute_conf_update(type);
+
+ if (rip->enabled)
+ rip_redistribute_conf_update(rip, type);
}
/*
@@ -580,37 +699,41 @@ ripd_instance_redistribute_route_map_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
int type;
const char *rmap_name;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
rmap_name = yang_dnode_get_string(dnode, NULL);
- if (rip->route_map[type].name)
- free(rip->route_map[type].name);
- rip->route_map[type].name = strdup(rmap_name);
- rip->route_map[type].map = route_map_lookup_by_name(rmap_name);
+ if (rip->redist[type].route_map.name)
+ free(rip->redist[type].route_map.name);
+ rip->redist[type].route_map.name = strdup(rmap_name);
+ rip->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
return NB_OK;
}
static int
-ripd_instance_redistribute_route_map_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripd_instance_redistribute_route_map_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
- free(rip->route_map[type].name);
- rip->route_map[type].name = NULL;
- rip->route_map[type].map = NULL;
+ free(rip->redist[type].route_map.name);
+ rip->redist[type].route_map.name = NULL;
+ rip->redist[type].route_map.map = NULL;
return NB_OK;
}
@@ -623,34 +746,38 @@ ripd_instance_redistribute_metric_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
int type;
uint8_t metric;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
metric = yang_dnode_get_uint8(dnode, NULL);
- rip->route_map[type].metric_config = true;
- rip->route_map[type].metric = metric;
+ rip->redist[type].metric_config = true;
+ rip->redist[type].metric = metric;
return NB_OK;
}
static int
-ripd_instance_redistribute_metric_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripd_instance_redistribute_metric_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
- rip->route_map[type].metric_config = false;
- rip->route_map[type].metric = 0;
+ rip->redist[type].metric_config = false;
+ rip->redist[type].metric = 0;
return NB_OK;
}
@@ -662,35 +789,39 @@ static int ripd_instance_static_route_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
struct nexthop nh;
struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv4p(&p, dnode, NULL);
apply_mask_ipv4(&p);
memset(&nh, 0, sizeof(nh));
nh.type = NEXTHOP_TYPE_IPV4;
- rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, 0,
- 0);
+ rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0,
+ 0, 0);
return NB_OK;
}
-static int ripd_instance_static_route_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripd_instance_static_route_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct rip *rip;
struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv4p(&p, dnode, NULL);
apply_mask_ipv4(&p);
- rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
+ rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
return NB_OK;
}
@@ -700,8 +831,12 @@ static int ripd_instance_static_route_delete(enum nb_event event,
*/
static void ripd_instance_timers_apply_finish(const struct lyd_node *dnode)
{
+ struct rip *rip;
+
+ rip = yang_dnode_get_entry(dnode, true);
+
/* Reset update timer thread. */
- rip_event(RIP_UPDATE_EVENT, 0);
+ rip_event(rip, RIP_UPDATE_EVENT, 0);
}
/*
@@ -712,9 +847,12 @@ ripd_instance_timers_flush_interval_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->garbage_time = yang_dnode_get_uint32(dnode, NULL);
return NB_OK;
@@ -728,9 +866,12 @@ ripd_instance_timers_holddown_interval_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->timeout_time = yang_dnode_get_uint32(dnode, NULL);
return NB_OK;
@@ -744,9 +885,12 @@ ripd_instance_timers_update_interval_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->update_time = yang_dnode_get_uint32(dnode, NULL);
return NB_OK;
@@ -759,9 +903,12 @@ static int ripd_instance_version_receive_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->version_recv = yang_dnode_get_enum(dnode, NULL);
return NB_OK;
@@ -774,9 +921,12 @@ static int ripd_instance_version_send_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ rip = yang_dnode_get_entry(dnode, true);
rip->version_send = yang_dnode_get_enum(dnode, NULL);
return NB_OK;
@@ -904,7 +1054,7 @@ static int lib_interface_rip_authentication_scheme_md5_auth_length_modify(
return NB_OK;
}
-static int lib_interface_rip_authentication_scheme_md5_auth_length_delete(
+static int lib_interface_rip_authentication_scheme_md5_auth_length_destroy(
enum nb_event event, const struct lyd_node *dnode)
{
struct interface *ifp;
@@ -945,8 +1095,8 @@ lib_interface_rip_authentication_password_modify(enum nb_event event,
}
static int
-lib_interface_rip_authentication_password_delete(enum nb_event event,
- const struct lyd_node *dnode)
+lib_interface_rip_authentication_password_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
struct interface *ifp;
struct rip_interface *ri;
@@ -985,8 +1135,8 @@ lib_interface_rip_authentication_key_chain_modify(enum nb_event event,
}
static int
-lib_interface_rip_authentication_key_chain_delete(enum nb_event event,
- const struct lyd_node *dnode)
+lib_interface_rip_authentication_key_chain_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
struct interface *ifp;
struct rip_interface *ri;
@@ -1002,24 +1152,26 @@ lib_interface_rip_authentication_key_chain_delete(enum nb_event event,
}
/*
- * XPath: /frr-ripd:ripd/state/neighbors/neighbor
+ * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor
*/
static const void *
-ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
- const void *list_entry)
+ripd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
+ const void *list_entry)
{
+ const struct rip *rip = parent_list_entry;
struct listnode *node;
if (list_entry == NULL)
- node = listhead(peer_list);
+ node = listhead(rip->peer_list);
else
node = listnextnode((struct listnode *)list_entry);
return node;
}
-static int ripd_state_neighbors_neighbor_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
+static int
+ripd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
{
const struct listnode *node = list_entry;
const struct rip_peer *peer = listgetdata(node);
@@ -1031,17 +1183,17 @@ static int ripd_state_neighbors_neighbor_get_keys(const void *list_entry,
return NB_OK;
}
-static const void *
-ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
- const struct yang_list_keys *keys)
+static const void *ripd_instance_state_neighbors_neighbor_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys)
{
+ const struct rip *rip = parent_list_entry;
struct in_addr address;
struct rip_peer *peer;
struct listnode *node;
yang_str2ipv4(keys->key[0], &address);
- for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) {
+ for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) {
if (IPV4_ADDR_SAME(&peer->addr, &address))
return node;
}
@@ -1050,11 +1202,11 @@ ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
}
/*
- * XPath: /frr-ripd:ripd/state/neighbors/neighbor/address
+ * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/address
*/
static struct yang_data *
-ripd_state_neighbors_neighbor_address_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_neighbors_neighbor_address_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct listnode *node = list_entry;
const struct rip_peer *peer = listgetdata(node);
@@ -1063,22 +1215,22 @@ ripd_state_neighbors_neighbor_address_get_elem(const char *xpath,
}
/*
- * XPath: /frr-ripd:ripd/state/neighbors/neighbor/last-update
+ * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/last-update
*/
static struct yang_data *
-ripd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_neighbors_neighbor_last_update_get_elem(
+ const char *xpath, const void *list_entry)
{
/* TODO: yang:date-and-time is tricky */
return NULL;
}
/*
- * XPath: /frr-ripd:ripd/state/neighbors/neighbor/bad-packets-rcvd
+ * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd
*/
static struct yang_data *
-ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
+ const char *xpath, const void *list_entry)
{
const struct listnode *node = list_entry;
const struct rip_peer *peer = listgetdata(node);
@@ -1087,11 +1239,11 @@ ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(const char *xpath,
}
/*
- * XPath: /frr-ripd:ripd/state/neighbors/neighbor/bad-routes-rcvd
+ * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd
*/
static struct yang_data *
-ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
+ const char *xpath, const void *list_entry)
{
const struct listnode *node = list_entry;
const struct rip_peer *peer = listgetdata(node);
@@ -1100,17 +1252,15 @@ ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
}
/*
- * XPath: /frr-ripd:ripd/state/routes/route
+ * XPath: /frr-ripd:ripd/instance/state/routes/route
*/
static const void *
-ripd_state_routes_route_get_next(const void *parent_list_entry,
- const void *list_entry)
+ripd_instance_state_routes_route_get_next(const void *parent_list_entry,
+ const void *list_entry)
{
+ const struct rip *rip = parent_list_entry;
struct route_node *rn;
- if (rip == NULL)
- return NULL;
-
if (list_entry == NULL)
rn = route_top(rip->table);
else
@@ -1121,8 +1271,9 @@ ripd_state_routes_route_get_next(const void *parent_list_entry,
return rn;
}
-static int ripd_state_routes_route_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
+static int
+ripd_instance_state_routes_route_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
{
const struct route_node *rn = list_entry;
@@ -1133,9 +1284,10 @@ static int ripd_state_routes_route_get_keys(const void *list_entry,
}
static const void *
-ripd_state_routes_route_lookup_entry(const void *parent_list_entry,
- const struct yang_list_keys *keys)
+ripd_instance_state_routes_route_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys)
{
+ const struct rip *rip = parent_list_entry;
struct prefix prefix;
struct route_node *rn;
@@ -1151,11 +1303,11 @@ ripd_state_routes_route_lookup_entry(const void *parent_list_entry,
}
/*
- * XPath: /frr-ripd:ripd/state/routes/route/prefix
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/prefix
*/
static struct yang_data *
-ripd_state_routes_route_prefix_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_routes_route_prefix_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct route_node *rn = list_entry;
const struct rip_info *rinfo = listnode_head(rn->info);
@@ -1164,11 +1316,11 @@ ripd_state_routes_route_prefix_get_elem(const char *xpath,
}
/*
- * XPath: /frr-ripd:ripd/state/routes/route/next-hop
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop
*/
static struct yang_data *
-ripd_state_routes_route_next_hop_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct route_node *rn = list_entry;
const struct rip_info *rinfo = listnode_head(rn->info);
@@ -1183,31 +1335,33 @@ ripd_state_routes_route_next_hop_get_elem(const char *xpath,
}
/*
- * XPath: /frr-ripd:ripd/state/routes/route/interface
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/interface
*/
static struct yang_data *
-ripd_state_routes_route_interface_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_routes_route_interface_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct route_node *rn = list_entry;
const struct rip_info *rinfo = listnode_head(rn->info);
+ const struct rip *rip = rip_info_get_instance(rinfo);
switch (rinfo->nh.type) {
case NEXTHOP_TYPE_IFINDEX:
case NEXTHOP_TYPE_IPV4_IFINDEX:
return yang_data_new_string(
- xpath, ifindex2ifname(rinfo->nh.ifindex, VRF_DEFAULT));
+ xpath,
+ ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id));
default:
return NULL;
}
}
/*
- * XPath: /frr-ripd:ripd/state/routes/route/metric
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/metric
*/
static struct yang_data *
-ripd_state_routes_route_metric_get_elem(const char *xpath,
- const void *list_entry)
+ripd_instance_state_routes_route_metric_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct route_node *rn = list_entry;
const struct rip_info *rinfo = listnode_head(rn->info);
@@ -1218,16 +1372,19 @@ ripd_state_routes_route_metric_get_elem(const char *xpath,
/*
* XPath: /frr-ripd:clear-rip-route
*/
-static int clear_rip_route_rpc(const char *xpath, const struct list *input,
- struct list *output)
+static void clear_rip_route(struct rip *rip)
{
struct route_node *rp;
- struct rip_info *rinfo;
- struct list *list;
- struct listnode *listnode;
+
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("Clearing all RIP routes (VRF %s)", rip->vrf_name);
/* Clear received RIP routes */
for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
+ struct list *list;
+ struct listnode *listnode;
+ struct rip_info *rinfo;
+
list = rp->info;
if (!list)
continue;
@@ -1237,7 +1394,7 @@ static int clear_rip_route_rpc(const char *xpath, const struct list *input,
continue;
if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
- rip_zebra_ipv4_delete(rp);
+ rip_zebra_ipv4_delete(rip, rp);
break;
}
@@ -1254,6 +1411,30 @@ static int clear_rip_route_rpc(const char *xpath, const struct list *input,
route_unlock_node(rp);
}
}
+}
+
+static int clear_rip_route_rpc(const char *xpath, const struct list *input,
+ struct list *output)
+{
+ struct rip *rip;
+ struct yang_data *yang_vrf;
+
+ yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf");
+ if (yang_vrf) {
+ rip = rip_lookup_by_vrf_name(yang_vrf->value);
+ if (rip)
+ clear_rip_route(rip);
+ } else {
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ rip = vrf->info;
+ if (!rip)
+ continue;
+
+ clear_rip_route(rip);
+ }
+ }
return NB_OK;
}
@@ -1303,7 +1484,10 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance",
.cbs.create = ripd_instance_create,
- .cbs.destroy = ripd_instance_delete,
+ .cbs.destroy = ripd_instance_destroy,
+ .cbs.get_next = ripd_instance_get_next,
+ .cbs.get_keys = ripd_instance_get_keys,
+ .cbs.lookup_entry = ripd_instance_lookup_entry,
.cbs.cli_show = cli_show_router_rip,
},
{
@@ -1329,7 +1513,7 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/distance/source",
.cbs.create = ripd_instance_distance_source_create,
- .cbs.destroy = ripd_instance_distance_source_delete,
+ .cbs.destroy = ripd_instance_distance_source_destroy,
.cbs.cli_show = cli_show_rip_distance_source,
},
{
@@ -1339,30 +1523,30 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/distance/source/access-list",
.cbs.modify = ripd_instance_distance_source_access_list_modify,
- .cbs.destroy = ripd_instance_distance_source_access_list_delete,
+ .cbs.destroy = ripd_instance_distance_source_access_list_destroy,
},
{
.xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
.cbs.create = ripd_instance_explicit_neighbor_create,
- .cbs.destroy = ripd_instance_explicit_neighbor_delete,
+ .cbs.destroy = ripd_instance_explicit_neighbor_destroy,
.cbs.cli_show = cli_show_rip_neighbor,
},
{
.xpath = "/frr-ripd:ripd/instance/network",
.cbs.create = ripd_instance_network_create,
- .cbs.destroy = ripd_instance_network_delete,
+ .cbs.destroy = ripd_instance_network_destroy,
.cbs.cli_show = cli_show_rip_network_prefix,
},
{
.xpath = "/frr-ripd:ripd/instance/interface",
.cbs.create = ripd_instance_interface_create,
- .cbs.destroy = ripd_instance_interface_delete,
+ .cbs.destroy = ripd_instance_interface_destroy,
.cbs.cli_show = cli_show_rip_network_interface,
},
{
.xpath = "/frr-ripd:ripd/instance/offset-list",
.cbs.create = ripd_instance_offset_list_create,
- .cbs.destroy = ripd_instance_offset_list_delete,
+ .cbs.destroy = ripd_instance_offset_list_destroy,
.cbs.cli_show = cli_show_rip_offset_list,
},
{
@@ -1381,36 +1565,36 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/passive-interface",
.cbs.create = ripd_instance_passive_interface_create,
- .cbs.destroy = ripd_instance_passive_interface_delete,
+ .cbs.destroy = ripd_instance_passive_interface_destroy,
.cbs.cli_show = cli_show_rip_passive_interface,
},
{
.xpath = "/frr-ripd:ripd/instance/non-passive-interface",
.cbs.create = ripd_instance_non_passive_interface_create,
- .cbs.destroy = ripd_instance_non_passive_interface_delete,
+ .cbs.destroy = ripd_instance_non_passive_interface_destroy,
.cbs.cli_show = cli_show_rip_non_passive_interface,
},
{
.xpath = "/frr-ripd:ripd/instance/redistribute",
.cbs.create = ripd_instance_redistribute_create,
- .cbs.destroy = ripd_instance_redistribute_delete,
+ .cbs.destroy = ripd_instance_redistribute_destroy,
.cbs.apply_finish = ripd_instance_redistribute_apply_finish,
.cbs.cli_show = cli_show_rip_redistribute,
},
{
.xpath = "/frr-ripd:ripd/instance/redistribute/route-map",
.cbs.modify = ripd_instance_redistribute_route_map_modify,
- .cbs.destroy = ripd_instance_redistribute_route_map_delete,
+ .cbs.destroy = ripd_instance_redistribute_route_map_destroy,
},
{
.xpath = "/frr-ripd:ripd/instance/redistribute/metric",
.cbs.modify = ripd_instance_redistribute_metric_modify,
- .cbs.destroy = ripd_instance_redistribute_metric_delete,
+ .cbs.destroy = ripd_instance_redistribute_metric_destroy,
},
{
.xpath = "/frr-ripd:ripd/instance/static-route",
.cbs.create = ripd_instance_static_route_create,
- .cbs.destroy = ripd_instance_static_route_delete,
+ .cbs.destroy = ripd_instance_static_route_destroy,
.cbs.cli_show = cli_show_rip_route,
},
{
@@ -1473,63 +1657,63 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length",
.cbs.modify = lib_interface_rip_authentication_scheme_md5_auth_length_modify,
- .cbs.destroy = lib_interface_rip_authentication_scheme_md5_auth_length_delete,
+ .cbs.destroy = lib_interface_rip_authentication_scheme_md5_auth_length_destroy,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password",
.cbs.modify = lib_interface_rip_authentication_password_modify,
- .cbs.destroy = lib_interface_rip_authentication_password_delete,
+ .cbs.destroy = lib_interface_rip_authentication_password_destroy,
.cbs.cli_show = cli_show_ip_rip_authentication_string,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain",
.cbs.modify = lib_interface_rip_authentication_key_chain_modify,
- .cbs.destroy = lib_interface_rip_authentication_key_chain_delete,
+ .cbs.destroy = lib_interface_rip_authentication_key_chain_destroy,
.cbs.cli_show = cli_show_ip_rip_authentication_key_chain,
},
{
- .xpath = "/frr-ripd:ripd/state/neighbors/neighbor",
- .cbs.get_next = ripd_state_neighbors_neighbor_get_next,
- .cbs.get_keys = ripd_state_neighbors_neighbor_get_keys,
- .cbs.lookup_entry = ripd_state_neighbors_neighbor_lookup_entry,
+ .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor",
+ .cbs.get_next = ripd_instance_state_neighbors_neighbor_get_next,
+ .cbs.get_keys = ripd_instance_state_neighbors_neighbor_get_keys,
+ .cbs.lookup_entry = ripd_instance_state_neighbors_neighbor_lookup_entry,
},
{
- .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/address",
- .cbs.get_elem = ripd_state_neighbors_neighbor_address_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/address",
+ .cbs.get_elem = ripd_instance_state_neighbors_neighbor_address_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/last-update",
- .cbs.get_elem = ripd_state_neighbors_neighbor_last_update_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/last-update",
+ .cbs.get_elem = ripd_instance_state_neighbors_neighbor_last_update_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/bad-packets-rcvd",
- .cbs.get_elem = ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd",
+ .cbs.get_elem = ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/bad-routes-rcvd",
- .cbs.get_elem = ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd",
+ .cbs.get_elem = ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/routes/route",
- .cbs.get_next = ripd_state_routes_route_get_next,
- .cbs.get_keys = ripd_state_routes_route_get_keys,
- .cbs.lookup_entry = ripd_state_routes_route_lookup_entry,
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route",
+ .cbs.get_next = ripd_instance_state_routes_route_get_next,
+ .cbs.get_keys = ripd_instance_state_routes_route_get_keys,
+ .cbs.lookup_entry = ripd_instance_state_routes_route_lookup_entry,
},
{
- .xpath = "/frr-ripd:ripd/state/routes/route/prefix",
- .cbs.get_elem = ripd_state_routes_route_prefix_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/prefix",
+ .cbs.get_elem = ripd_instance_state_routes_route_prefix_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/routes/route/next-hop",
- .cbs.get_elem = ripd_state_routes_route_next_hop_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/next-hop",
+ .cbs.get_elem = ripd_instance_state_routes_route_next_hop_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/routes/route/interface",
- .cbs.get_elem = ripd_state_routes_route_interface_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/interface",
+ .cbs.get_elem = ripd_instance_state_routes_route_interface_get_elem,
},
{
- .xpath = "/frr-ripd:ripd/state/routes/route/metric",
- .cbs.get_elem = ripd_state_routes_route_metric_get_elem,
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/metric",
+ .cbs.get_elem = ripd_instance_state_routes_route_metric_get_elem,
},
{
.xpath = "/frr-ripd:clear-rip-route",
diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c
index ca273c53b..b3f84fe50 100644
--- a/ripd/rip_offset.c
+++ b/ripd/rip_offset.c
@@ -29,28 +29,27 @@
#include "ripd/ripd.h"
-static struct list *rip_offset_list_master;
-
#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric)
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
-struct rip_offset_list *rip_offset_list_new(const char *ifname)
+struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname)
{
struct rip_offset_list *offset;
offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list));
+ offset->rip = rip;
offset->ifname = strdup(ifname);
- listnode_add_sort(rip_offset_list_master, offset);
+ listnode_add_sort(rip->offset_list_master, offset);
return offset;
}
void offset_list_del(struct rip_offset_list *offset)
{
- listnode_delete(rip_offset_list_master, offset);
+ listnode_delete(offset->rip->offset_list_master, offset);
if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_NAME(offset))
@@ -59,12 +58,13 @@ void offset_list_del(struct rip_offset_list *offset)
XFREE(MTYPE_RIP_OFFSET_LIST, offset);
}
-struct rip_offset_list *rip_offset_list_lookup(const char *ifname)
+struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
+ const char *ifname)
{
struct rip_offset_list *offset;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) {
+ for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) {
if (strcmp(offset->ifname, ifname) == 0)
return offset;
}
@@ -75,11 +75,12 @@ struct rip_offset_list *rip_offset_list_lookup(const char *ifname)
int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric)
{
+ struct rip_interface *ri = ifp->info;
struct rip_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
- offset = rip_offset_list_lookup(ifp->name);
+ offset = rip_offset_list_lookup(ri->rip, ifp->name);
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
@@ -92,7 +93,7 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
return 0;
}
/* Look up offset-list without interface name. */
- offset = rip_offset_list_lookup("*");
+ offset = rip_offset_list_lookup(ri->rip, "*");
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset));
@@ -111,11 +112,12 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric)
{
+ struct rip_interface *ri = ifp->info;
struct rip_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
- offset = rip_offset_list_lookup(ifp->name);
+ offset = rip_offset_list_lookup(ri->rip, ifp->name);
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP,
OFFSET_LIST_OUT_NAME(offset));
@@ -130,7 +132,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
}
/* Look up offset-list without interface name. */
- offset = rip_offset_list_lookup("*");
+ offset = rip_offset_list_lookup(ri->rip, "*");
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP,
OFFSET_LIST_OUT_NAME(offset));
@@ -146,24 +148,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
return 0;
}
-static int offset_list_cmp(struct rip_offset_list *o1,
- struct rip_offset_list *o2)
+int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2)
{
return strcmp(o1->ifname, o2->ifname);
}
-
-void rip_offset_init(void)
-{
- rip_offset_list_master = list_new();
- rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
- rip_offset_list_master->del = (void (*)(void *))offset_list_del;
-}
-
-void rip_offset_clean(void)
-{
- list_delete(&rip_offset_list_master);
-
- rip_offset_list_master = list_new();
- rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
- rip_offset_list_master->del = (void (*)(void *))offset_list_del;
-}
diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c
index 21317915d..08aa61257 100644
--- a/ripd/rip_peer.c
+++ b/ripd/rip_peer.c
@@ -29,9 +29,6 @@
#include "ripd/ripd.h"
-/* Linked list of RIP peer. */
-struct list *peer_list;
-
static struct rip_peer *rip_peer_new(void)
{
return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer));
@@ -39,27 +36,28 @@ static struct rip_peer *rip_peer_new(void)
static void rip_peer_free(struct rip_peer *peer)
{
+ RIP_TIMER_OFF(peer->t_timeout);
XFREE(MTYPE_RIP_PEER, peer);
}
-struct rip_peer *rip_peer_lookup(struct in_addr *addr)
+struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr)
{
struct rip_peer *peer;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
+ for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
if (IPV4_ADDR_SAME(&peer->addr, addr))
return peer;
}
return NULL;
}
-struct rip_peer *rip_peer_lookup_next(struct in_addr *addr)
+struct rip_peer *rip_peer_lookup_next(struct rip *rip, struct in_addr *addr)
{
struct rip_peer *peer;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
+ for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
if (htonl(peer->addr.s_addr) > htonl(addr->s_addr))
return peer;
}
@@ -72,26 +70,27 @@ static int rip_peer_timeout(struct thread *t)
struct rip_peer *peer;
peer = THREAD_ARG(t);
- listnode_delete(peer_list, peer);
+ listnode_delete(peer->rip->peer_list, peer);
rip_peer_free(peer);
return 0;
}
/* Get RIP peer. At the same time update timeout thread. */
-static struct rip_peer *rip_peer_get(struct in_addr *addr)
+static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr)
{
struct rip_peer *peer;
- peer = rip_peer_lookup(addr);
+ peer = rip_peer_lookup(rip, addr);
if (peer) {
if (peer->t_timeout)
thread_cancel(peer->t_timeout);
} else {
peer = rip_peer_new();
+ peer->rip = rip;
peer->addr = *addr;
- listnode_add_sort(peer_list, peer);
+ listnode_add_sort(rip->peer_list, peer);
}
/* Update timeout thread. */
@@ -105,24 +104,24 @@ static struct rip_peer *rip_peer_get(struct in_addr *addr)
return peer;
}
-void rip_peer_update(struct sockaddr_in *from, uint8_t version)
+void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version)
{
struct rip_peer *peer;
- peer = rip_peer_get(&from->sin_addr);
+ peer = rip_peer_get(rip, &from->sin_addr);
peer->version = version;
}
-void rip_peer_bad_route(struct sockaddr_in *from)
+void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from)
{
struct rip_peer *peer;
- peer = rip_peer_get(&from->sin_addr);
+ peer = rip_peer_get(rip, &from->sin_addr);
peer->recv_badroutes++;
}
-void rip_peer_bad_packet(struct sockaddr_in *from)
+void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from)
{
struct rip_peer *peer;
- peer = rip_peer_get(&from->sin_addr);
+ peer = rip_peer_get(rip, &from->sin_addr);
peer->recv_badpackets++;
}
@@ -155,14 +154,14 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
return buf;
}
-void rip_peer_display(struct vty *vty)
+void rip_peer_display(struct vty *vty, struct rip *rip)
{
struct rip_peer *peer;
struct listnode *node, *nnode;
#define RIP_UPTIME_LEN 25
char timebuf[RIP_UPTIME_LEN];
- for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
+ for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) {
vty_out(vty, " %-16s %9d %9d %9d %s\n",
inet_ntoa(peer->addr), peer->recv_badpackets,
peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT,
@@ -170,7 +169,7 @@ void rip_peer_display(struct vty *vty)
}
}
-static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
+int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
{
if (p2->addr.s_addr == p1->addr.s_addr)
return 0;
@@ -178,8 +177,7 @@ static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2)
return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1;
}
-void rip_peer_init(void)
+void rip_peer_list_del(void *arg)
{
- peer_list = list_new();
- peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
+ rip_peer_free(arg);
}
diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c
index 19367638c..5a6b71fba 100644
--- a/ripd/rip_snmp.c
+++ b/ripd/rip_snmp.c
@@ -156,17 +156,23 @@ static uint8_t *rip2Globals(struct variable *v, oid name[], size_t *length,
int exact, size_t *var_len,
WriteMethod **write_method)
{
+ struct rip *rip;
+
if (smux_header_generic(v, name, length, exact, var_len, write_method)
== MATCH_FAILED)
return NULL;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
+ if (!rip)
+ return NULL;
+
/* Retrun global counter. */
switch (v->magic) {
case RIP2GLOBALROUTECHANGES:
- return SNMP_INTEGER(rip_global_route_changes);
+ return SNMP_INTEGER(rip->counters.route_changes);
break;
case RIP2GLOBALQUERIES:
- return SNMP_INTEGER(rip_global_queries);
+ return SNMP_INTEGER(rip->counters.queries);
break;
default:
return NULL;
@@ -281,9 +287,14 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
size_t *length, struct in_addr *addr,
int exact)
{
+ struct rip *rip;
int len;
struct rip_peer *peer;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
+ if (!rip)
+ return NULL;
+
if (exact) {
/* Check the length. */
if (*length - v->namelen != sizeof(struct in_addr) + 1)
@@ -291,7 +302,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr);
- peer = rip_peer_lookup(addr);
+ peer = rip_peer_lookup(rip, addr);
if (peer->domain
== (int)name[v->namelen + sizeof(struct in_addr)])
@@ -306,7 +317,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
oid2in_addr(name + v->namelen, len, addr);
len = *length - v->namelen;
- peer = rip_peer_lookup(addr);
+ peer = rip_peer_lookup(rip, addr);
if (peer) {
if ((len < (int)sizeof(struct in_addr) + 1)
|| (peer->domain
@@ -321,7 +332,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
return peer;
}
}
- peer = rip_peer_lookup_next(addr);
+ peer = rip_peer_lookup_next(rip, addr);
if (!peer)
return NULL;
@@ -402,10 +413,10 @@ static long rip2IfConfSend(struct rip_interface *ri)
return ripVersion2;
else if (ri->ri_send & RIPv1)
return ripVersion1;
- else if (rip) {
- if (rip->version_send == RIPv2)
+ else if (ri->rip) {
+ if (ri->rip->version_send == RIPv2)
return ripVersion2;
- else if (rip->version_send == RIPv1)
+ else if (ri->rip->version_send == RIPv1)
return ripVersion1;
}
return doNotSend;
@@ -423,7 +434,7 @@ static long rip2IfConfReceive(struct rip_interface *ri)
if (!ri->running)
return doNotReceive;
- recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv
+ recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? ri->rip->version_recv
: ri->ri_receive;
if (recvv == RI_RIP_VERSION_1_AND_2)
return rip1OrRip2;
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index fff868177..4f0df1223 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -36,7 +36,8 @@
struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */
-static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
+static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp,
+ uint8_t cmd)
{
struct list *list = (struct list *)rp->info;
struct zapi_route api;
@@ -46,7 +47,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
int count = 0;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = rip->vrf->vrf_id;
api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST;
@@ -55,7 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
- api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->vrf_id = rip->vrf->vrf_id;
api_nh->gate = rinfo->nh.gate;
api_nh->type = NEXTHOP_TYPE_IPV4;
if (cmd == ZEBRA_ROUTE_ADD)
@@ -101,28 +102,30 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd)
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
}
- rip_global_route_changes++;
+ rip->counters.route_changes++;
}
/* Add/update ECMP routes to zebra. */
-void rip_zebra_ipv4_add(struct route_node *rp)
+void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp)
{
- rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
+ rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD);
}
/* Delete ECMP routes from zebra. */
-void rip_zebra_ipv4_delete(struct route_node *rp)
+void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp)
{
- rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
+ rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE);
}
/* Zebra route add and delete treatment. */
static int rip_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
+ struct rip *rip;
struct zapi_route api;
struct nexthop nh;
+ rip = rip_lookup_by_vrf_id(vrf_id);
if (!rip)
return 0;
@@ -136,68 +139,95 @@ static int rip_zebra_read_route(int command, struct zclient *zclient,
/* Then fetch IPv4 prefixes. */
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
- rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
+ rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix, &nh,
api.metric, api.distance, api.tag);
else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
- rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
+ rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix,
nh.ifindex);
return 0;
}
-void rip_redistribute_conf_update(int type)
+void rip_redistribute_conf_update(struct rip *rip, int type)
{
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
- 0, VRF_DEFAULT);
+ 0, rip->vrf->vrf_id);
}
-void rip_redistribute_conf_delete(int type)
+void rip_redistribute_conf_delete(struct rip *rip, int type)
{
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
- AFI_IP, type, 0, VRF_DEFAULT);
+ AFI_IP, type, 0, rip->vrf->vrf_id);
/* Remove the routes from RIP table. */
- rip_redistribute_withdraw(type);
+ rip_redistribute_withdraw(rip, type);
}
-int rip_redistribute_check(int type)
+int rip_redistribute_check(struct rip *rip, int type)
{
- return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT);
+ return rip->redist[type].enabled;
}
-void rip_redistribute_clean(void)
+void rip_redistribute_enable(struct rip *rip)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], VRF_DEFAULT))
+ if (!rip_redistribute_check(rip, i))
continue;
- if (zclient->sock > 0)
- zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
- zclient, AFI_IP, i, 0,
- VRF_DEFAULT);
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
+ i, 0, rip->vrf->vrf_id);
+ }
+}
- vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT);
+void rip_redistribute_disable(struct rip *rip)
+{
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ if (!rip_redistribute_check(rip, i))
+ continue;
- /* Remove the routes from RIP table. */
- rip_redistribute_withdraw(i);
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
+ AFI_IP, i, 0, rip->vrf->vrf_id);
}
}
-void rip_show_redistribute_config(struct vty *vty)
+void rip_show_redistribute_config(struct vty *vty, struct rip *rip)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default
- || !vrf_bitmap_check(zclient->redist[AFI_IP][i],
- VRF_DEFAULT))
+ || !rip_redistribute_check(rip, i))
continue;
vty_out(vty, " %s", zebra_route_string(i));
}
}
+void rip_zebra_vrf_register(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
+ vrf->name, vrf->vrf_id);
+
+ zclient_send_reg_requests(zclient, vrf->vrf_id);
+}
+
+void rip_zebra_vrf_deregister(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
+ vrf->name, vrf->vrf_id);
+
+ zclient_send_dereg_requests(zclient, vrf->vrf_id);
+}
+
static void rip_zebra_connected(struct zclient *zclient)
{
zclient_send_reg_requests(zclient, VRF_DEFAULT);
@@ -215,6 +245,7 @@ void rip_zclient_init(struct thread_master *master)
zclient->interface_address_delete = rip_interface_address_delete;
zclient->interface_up = rip_interface_up;
zclient->interface_down = rip_interface_down;
+ zclient->interface_vrf_update = rip_interface_vrf_update;
zclient->redistribute_route_add = rip_zebra_read_route;
zclient->redistribute_route_del = rip_zebra_read_route;
}
diff --git a/ripd/ripd.c b/ripd/ripd.c
index d2fc9eb30..9683e26b5 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -46,27 +46,20 @@
#include "ripd/ripd.h"
#include "ripd/rip_debug.h"
#include "ripd/rip_errors.h"
+#include "ripd/rip_interface.h"
/* UDP receive buffer size */
#define RIP_UDP_RCV_BUF 41600
-/* RIP Structure. */
-struct rip *rip = NULL;
-
-/* RIP neighbor address table. */
-struct route_table *rip_neighbor_table;
-
-/* RIP route changes. */
-long rip_global_route_changes = 0;
-
-/* RIP queries. */
-long rip_global_queries = 0;
-
/* Prototypes. */
static void rip_output_process(struct connected *, struct sockaddr_in *, int,
uint8_t);
static int rip_triggered_update(struct thread *);
static int rip_update_jitter(unsigned long);
+static void rip_distance_table_node_cleanup(struct route_table *table,
+ struct route_node *node);
+static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock);
+static void rip_instance_disable(struct rip *rip);
static void rip_distribute_update(struct distribute_ctx *ctx,
struct distribute *dist);
@@ -86,6 +79,15 @@ static const struct message rip_msg[] = {{RIP_REQUEST, "REQUEST"},
{RIP_POLL_ENTRY, "POLL ENTRY"},
{0}};
+/* Generate rb-tree of RIP instances. */
+static inline int rip_instance_compare(const struct rip *a, const struct rip *b)
+{
+ return strcmp(a->vrf_name, b->vrf_name);
+}
+RB_GENERATE(rip_instance_head, rip, entry, rip_instance_compare)
+
+struct rip_instance_head rip_instances = RB_INITIALIZER(&rip_instances);
+
/* Utility function to set boradcast option to the socket. */
static int sockopt_broadcast(int sock)
{
@@ -117,6 +119,11 @@ void rip_info_free(struct rip_info *rinfo)
XFREE(MTYPE_RIP_INFO, rinfo);
}
+struct rip *rip_info_get_instance(const struct rip_info *rinfo)
+{
+ return route_table_get_info(rinfo->rp->table);
+}
+
/* RIP route garbage collect timer. */
static int rip_garbage_collect(struct thread *t)
{
@@ -145,13 +152,13 @@ static int rip_garbage_collect(struct thread *t)
return 0;
}
-static void rip_timeout_update(struct rip_info *rinfo);
+static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo);
/* Add new route to the ECMP list.
* RETURN: the new entry added in the list, or NULL if it is not the first
* entry and ECMP is not allowed.
*/
-struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new)
+struct rip_info *rip_ecmp_add(struct rip *rip, struct rip_info *rinfo_new)
{
struct route_node *rp = rinfo_new->rp;
struct rip_info *rinfo = NULL;
@@ -171,8 +178,8 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new)
listnode_add(list, rinfo);
if (rip_route_rte(rinfo)) {
- rip_timeout_update(rinfo);
- rip_zebra_ipv4_add(rp);
+ rip_timeout_update(rip, rinfo);
+ rip_zebra_ipv4_add(rip, rp);
}
/* Set the route change flag on the first entry. */
@@ -180,7 +187,7 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new)
SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
/* Signal the output process to trigger an update (see section 2.5). */
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
return rinfo;
}
@@ -188,7 +195,7 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new)
/* Replace the ECMP list with the new route.
* RETURN: the new entry added in the list
*/
-struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new)
+struct rip_info *rip_ecmp_replace(struct rip *rip, struct rip_info *rinfo_new)
{
struct route_node *rp = rinfo_new->rp;
struct list *list = (struct list *)rp->info;
@@ -196,7 +203,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new)
struct listnode *node = NULL, *nextnode = NULL;
if (list == NULL || listcount(list) == 0)
- return rip_ecmp_add(rinfo_new);
+ return rip_ecmp_add(rip, rinfo_new);
/* Get the first entry */
rinfo = listgetdata(listhead(list));
@@ -204,7 +211,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new)
/* Learnt route replaced by a local one. Delete it from zebra. */
if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new))
if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
- rip_zebra_ipv4_delete(rp);
+ rip_zebra_ipv4_delete(rip, rp);
/* Re-use the first entry, and delete the others. */
for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo))
@@ -220,16 +227,16 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new)
memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
if (rip_route_rte(rinfo)) {
- rip_timeout_update(rinfo);
+ rip_timeout_update(rip, rinfo);
/* The ADD message implies an update. */
- rip_zebra_ipv4_add(rp);
+ rip_zebra_ipv4_add(rip, rp);
}
/* Set the route change flag. */
SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
/* Signal the output process to trigger an update (see section 2.5). */
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
return rinfo;
}
@@ -240,7 +247,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new)
* the entry - the entry is the last one in the list; its metric is set
* to INFINITY, and the garbage collector is started for it
*/
-struct rip_info *rip_ecmp_delete(struct rip_info *rinfo)
+struct rip_info *rip_ecmp_delete(struct rip *rip, struct rip_info *rinfo)
{
struct route_node *rp = rinfo->rp;
struct list *list = (struct list *)rp->info;
@@ -255,7 +262,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo)
if (rip_route_rte(rinfo)
&& CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
/* The ADD message implies the update. */
- rip_zebra_ipv4_add(rp);
+ rip_zebra_ipv4_add(rip, rp);
rip_info_free(rinfo);
rinfo = NULL;
} else {
@@ -271,7 +278,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo)
if (rip_route_rte(rinfo)
&& CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
- rip_zebra_ipv4_delete(rp);
+ rip_zebra_ipv4_delete(rip, rp);
}
/* Set the route change flag on the first entry. */
@@ -279,7 +286,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo)
SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
/* Signal the output process to trigger an update (see section 2.5). */
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
return rinfo;
}
@@ -287,15 +294,20 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo)
/* Timeout RIP routes. */
static int rip_timeout(struct thread *t)
{
- rip_ecmp_delete((struct rip_info *)THREAD_ARG(t));
+ struct rip_info *rinfo = THREAD_ARG(t);
+ struct rip *rip = rip_info_get_instance(rinfo);
+
+ rip_ecmp_delete(rip, rinfo);
+
return 0;
}
-static void rip_timeout_update(struct rip_info *rinfo)
+static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo)
{
if (rinfo->metric != RIP_METRIC_INFINITY) {
RIP_TIMER_OFF(rinfo->t_timeout);
- RIP_TIMER_ON(rinfo->t_timeout, rip_timeout, rip->timeout_time);
+ thread_add_timer(master, rip_timeout, rinfo, rip->timeout_time,
+ &rinfo->t_timeout);
}
}
@@ -334,7 +346,7 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p,
}
/* All interface filter check. */
- dist = distribute_lookup(rip->distribute_ctx, NULL);
+ dist = distribute_lookup(ri->rip->distribute_ctx, NULL);
if (dist) {
if (dist->list[distribute]) {
alist = access_list_lookup(AFI_IP,
@@ -373,9 +385,8 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p,
}
/* Check nexthop address validity. */
-static int rip_nexthop_check(struct in_addr *addr)
+static int rip_nexthop_check(struct rip *rip, struct in_addr *addr)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct listnode *cnode;
struct connected *ifc;
@@ -384,7 +395,7 @@ static int rip_nexthop_check(struct in_addr *addr)
/* If nexthop address matches local configured address then it is
invalid nexthop. */
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (rip->vrf, ifp) {
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
p = ifc->address;
@@ -400,6 +411,7 @@ static int rip_nexthop_check(struct in_addr *addr)
static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
struct interface *ifp)
{
+ struct rip *rip;
int ret;
struct prefix_ipv4 p;
struct route_node *rp;
@@ -420,9 +432,10 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
/* Make sure mask is applied. */
apply_mask_ipv4(&p);
- /* Apply input filters. */
ri = ifp->info;
+ rip = ri->rip;
+ /* Apply input filters. */
ret = rip_filter(RIP_FILTER_IN, &p, ri);
if (ret < 0)
return;
@@ -481,7 +494,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
nexthop = &rte->nexthop;
/* Check if nexthop address is myself, then do nothing. */
- if (rip_nexthop_check(nexthop) < 0) {
+ if (rip_nexthop_check(rip, nexthop) < 0) {
if (IS_RIP_DEBUG_PACKET)
zlog_debug("Nexthop address %s is myself",
inet_ntoa(*nexthop));
@@ -496,7 +509,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
newinfo.nh.type = NEXTHOP_TYPE_IPV4;
newinfo.metric = rte->metric;
newinfo.tag = ntohs(rte->tag);
- newinfo.distance = rip_distance_apply(&newinfo);
+ newinfo.distance = rip_distance_apply(rip, &newinfo);
new_dist = newinfo.distance ? newinfo.distance
: ZEBRA_RIP_DISTANCE_DEFAULT;
@@ -580,7 +593,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
mark it as a ghost */
if (new_dist <= old_dist
&& rte->metric != RIP_METRIC_INFINITY)
- rip_ecmp_replace(&newinfo);
+ rip_ecmp_replace(rip, &newinfo);
route_unlock_node(rp);
return;
@@ -597,7 +610,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
infinity (there is no point in adding a route which
unusable). */
if (rte->metric != RIP_METRIC_INFINITY)
- rip_ecmp_add(&newinfo);
+ rip_ecmp_add(rip, &newinfo);
} else {
/* Route is there but we are not sure the route is RIP or not.
*/
@@ -626,18 +639,18 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
|| ((old_dist != new_dist) && same)) {
if (listcount(list) == 1) {
if (newinfo.metric != RIP_METRIC_INFINITY)
- rip_ecmp_replace(&newinfo);
+ rip_ecmp_replace(rip, &newinfo);
else
- rip_ecmp_delete(rinfo);
+ rip_ecmp_delete(rip, rinfo);
} else {
if (newinfo.metric < rinfo->metric)
- rip_ecmp_replace(&newinfo);
+ rip_ecmp_replace(rip, &newinfo);
else if (newinfo.metric > rinfo->metric)
- rip_ecmp_delete(rinfo);
+ rip_ecmp_delete(rip, rinfo);
else if (new_dist < old_dist)
- rip_ecmp_replace(&newinfo);
+ rip_ecmp_replace(rip, &newinfo);
else if (new_dist > old_dist)
- rip_ecmp_delete(rinfo);
+ rip_ecmp_delete(rip, rinfo);
else {
int update = CHECK_FLAG(rinfo->flags,
RIP_RTF_FIB)
@@ -651,20 +664,20 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
RIP_TIMER_OFF(rinfo->t_garbage_collect);
memcpy(rinfo, &newinfo,
sizeof(struct rip_info));
- rip_timeout_update(rinfo);
+ rip_timeout_update(rip, rinfo);
if (update)
- rip_zebra_ipv4_add(rp);
+ rip_zebra_ipv4_add(rip, rp);
/* - Set the route change flag on the
* first entry. */
rinfo = listgetdata(listhead(list));
SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
}
}
} else /* same & no change */
- rip_timeout_update(rinfo);
+ rip_timeout_update(rip, rinfo);
/* Unlock tempolary lock of the route. */
route_unlock_node(rp);
@@ -1088,6 +1101,8 @@ static void rip_response_process(struct rip_packet *packet, int size,
struct sockaddr_in *from,
struct connected *ifc)
{
+ struct rip_interface *ri = ifc->ifp->info;
+ struct rip *rip = ri->rip;
caddr_t lim;
struct rte *rte;
struct prefix_ipv4 ifaddr;
@@ -1103,7 +1118,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
if (from->sin_port != htons(RIP_PORT_DEFAULT)) {
zlog_info("response doesn't come from RIP port: %d",
from->sin_port);
- rip_peer_bad_packet(from);
+ rip_peer_bad_packet(rip, from);
return;
}
@@ -1111,12 +1126,13 @@ static void rip_response_process(struct rip_packet *packet, int size,
whether the datagram is from a valid neighbor; the source of the
datagram must be on a directly connected network (RFC2453 - Sec.
3.9.2) */
- if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT)
+ if (if_lookup_address((void *)&from->sin_addr, AF_INET,
+ rip->vrf->vrf_id)
== NULL) {
zlog_info(
"This datagram doesn't came from a valid neighbor: %s",
inet_ntoa(from->sin_addr));
- rip_peer_bad_packet(from);
+ rip_peer_bad_packet(rip, from);
return;
}
@@ -1126,7 +1142,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
; /* Alredy done in rip_read () */
/* Update RIP peer. */
- rip_peer_update(from, packet->version);
+ rip_peer_update(rip, from, packet->version);
/* Set RTE pointer. */
rte = packet->rte;
@@ -1155,7 +1171,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
if (!rip_destination_check(rte->prefix)) {
zlog_info(
"Network is net 0 or net 127 or it is not unicast network");
- rip_peer_bad_route(from);
+ rip_peer_bad_route(rip, from);
continue;
}
@@ -1165,7 +1181,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
/* - is the metric valid (i.e., between 1 and 16, inclusive) */
if (!(rte->metric >= 1 && rte->metric <= 16)) {
zlog_info("Route's metric is not in the 1-16 range.");
- rip_peer_bad_route(from);
+ rip_peer_bad_route(rip, from);
continue;
}
@@ -1173,7 +1189,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) {
zlog_info("RIPv1 packet with nexthop value %s",
inet_ntoa(rte->nexthop));
- rip_peer_bad_route(from);
+ rip_peer_bad_route(rip, from);
continue;
}
@@ -1194,7 +1210,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
}
if (!if_lookup_address((void *)&rte->nexthop, AF_INET,
- VRF_DEFAULT)) {
+ rip->vrf->vrf_id)) {
struct route_node *rn;
struct rip_info *rinfo;
@@ -1305,7 +1321,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
zlog_warn(
"RIPv2 address %s is not mask /%d applied one",
inet_ntoa(rte->prefix), ip_masklen(rte->mask));
- rip_peer_bad_route(from);
+ rip_peer_bad_route(rip, from);
continue;
}
@@ -1324,11 +1340,12 @@ static void rip_response_process(struct rip_packet *packet, int size,
}
/* Make socket for RIP protocol. */
-int rip_create_socket(void)
+int rip_create_socket(struct vrf *vrf)
{
int ret;
int sock;
struct sockaddr_in addr;
+ const char *vrf_dev = NULL;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
@@ -1340,20 +1357,23 @@ int rip_create_socket(void)
addr.sin_port = htons(RIP_PORT_DEFAULT);
/* Make datagram socket. */
- sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (sock < 0) {
- flog_err_sys(EC_LIB_SOCKET, "Cannot create UDP socket: %s",
- safe_strerror(errno));
- exit(1);
+ if (vrf->vrf_id != VRF_DEFAULT)
+ vrf_dev = vrf->name;
+ frr_elevate_privs(&ripd_privs) {
+ sock = vrf_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, vrf->vrf_id,
+ vrf_dev);
+ if (sock < 0) {
+ flog_err_sys(EC_LIB_SOCKET,
+ "Cannot create UDP socket: %s",
+ safe_strerror(errno));
+ return -1;
+ }
}
sockopt_broadcast(sock);
sockopt_reuseaddr(sock);
sockopt_reuseport(sock);
setsockopt_ipv4_multicast_loop(sock, 0);
-#ifdef RIP_RECVMSG
- setsockopt_pktinfo(sock);
-#endif /* RIP_RECVMSG */
#ifdef IPTOS_PREC_INTERNETCONTROL
setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL);
#endif
@@ -1382,10 +1402,21 @@ int rip_create_socket(void)
static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
struct connected *ifc)
{
+ struct rip_interface *ri;
+ struct rip *rip;
int ret;
struct sockaddr_in sin;
+ struct msghdr msg;
+ struct iovec iov;
+#ifdef GNU_LINUX
+ struct cmsghdr *cmsgptr;
+ char adata[256] = {};
+ struct in_pktinfo *pkt;
+#endif /* GNU_LINUX */
assert(ifc != NULL);
+ ri = ifc->ifp->info;
+ rip = ri->rip;
if (IS_RIP_DEBUG_PACKET) {
#define ADDRESS_SIZE 20
@@ -1443,8 +1474,27 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
rip_interface_multicast_set(rip->sock, ifc);
}
- ret = sendto(rip->sock, buf, size, 0, (struct sockaddr *)&sin,
- sizeof(struct sockaddr_in));
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = (void *)&sin;
+ msg.msg_namelen = sizeof(struct sockaddr_in);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ iov.iov_base = buf;
+ iov.iov_len = size;
+
+#ifdef GNU_LINUX
+ msg.msg_control = (void *)adata;
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
+
+ cmsgptr = (struct cmsghdr *)adata;
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ cmsgptr->cmsg_level = IPPROTO_IP;
+ cmsgptr->cmsg_type = IP_PKTINFO;
+ pkt = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
+ pkt->ipi_ifindex = ifc->ifp->ifindex;
+#endif /* GNU_LINUX */
+
+ ret = sendmsg(rip->sock, &msg, 0);
if (IS_RIP_DEBUG_EVENT)
zlog_debug("SEND to %s.%d", inet_ntoa(sin.sin_addr),
@@ -1457,9 +1507,10 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
}
/* Add redistributed route to RIP table. */
-void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
- struct nexthop *nh, unsigned int metric,
- unsigned char distance, route_tag_t tag)
+void rip_redistribute_add(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, struct nexthop *nh,
+ unsigned int metric, unsigned char distance,
+ route_tag_t tag)
{
int ret;
struct route_node *rp = NULL;
@@ -1506,22 +1557,22 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
}
}
- (void)rip_ecmp_replace(&newinfo);
+ (void)rip_ecmp_replace(rip, &newinfo);
route_unlock_node(rp);
} else
- (void)rip_ecmp_add(&newinfo);
+ (void)rip_ecmp_add(rip, &newinfo);
if (IS_RIP_DEBUG_EVENT) {
zlog_debug("Redistribute new prefix %s/%d",
inet_ntoa(p->prefix), p->prefixlen);
}
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
}
/* Delete redistributed route from RIP table. */
-void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p,
- ifindex_t ifindex)
+void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, ifindex_t ifindex)
{
int ret;
struct route_node *rp;
@@ -1554,10 +1605,11 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p,
"infinity metric [delete]",
inet_ntoa(p->prefix),
p->prefixlen,
- ifindex2ifname(ifindex,
- VRF_DEFAULT));
+ ifindex2ifname(
+ ifindex,
+ rip->vrf->vrf_id));
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
}
}
route_unlock_node(rp);
@@ -1568,6 +1620,7 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p,
static void rip_request_process(struct rip_packet *packet, int size,
struct sockaddr_in *from, struct connected *ifc)
{
+ struct rip *rip;
caddr_t lim;
struct rte *rte;
struct prefix_ipv4 p;
@@ -1583,13 +1636,14 @@ static void rip_request_process(struct rip_packet *packet, int size,
ri = ifc->ifp->info;
if (!ri->running)
return;
+ rip = ri->rip;
/* When passive interface is specified, suppress responses */
if (ri->passive)
return;
/* RIP peer update. */
- rip_peer_update(from, packet->version);
+ rip_peer_update(rip, from, packet->version);
lim = ((caddr_t)packet) + size;
rte = packet->rte;
@@ -1639,87 +1693,13 @@ static void rip_request_process(struct rip_packet *packet, int size,
(void)rip_send_packet((uint8_t *)packet, size, from, ifc);
}
- rip_global_queries++;
-}
-
-#if RIP_RECVMSG
-/* Set IPv6 packet info to the socket. */
-static int setsockopt_pktinfo(int sock)
-{
- int ret;
- int val = 1;
-
- ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
- if (ret < 0)
- zlog_warn("Can't setsockopt IP_PKTINFO : %s",
- safe_strerror(errno));
- return ret;
-}
-
-/* Read RIP packet by recvmsg function. */
-int rip_recvmsg(int sock, uint8_t *buf, int size, struct sockaddr_in *from,
- ifindex_t *ifindex)
-{
- int ret;
- struct msghdr msg;
- struct iovec iov;
- struct cmsghdr *ptr;
- char adata[1024];
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = (void *)from;
- msg.msg_namelen = sizeof(struct sockaddr_in);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = (void *)adata;
- msg.msg_controllen = sizeof adata;
- iov.iov_base = buf;
- iov.iov_len = size;
-
- ret = recvmsg(sock, &msg, 0);
- if (ret < 0)
- return ret;
-
- for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL;
- ptr = CMSG_NXTHDR(&msg, ptr))
- if (ptr->cmsg_level == IPPROTO_IP
- && ptr->cmsg_type == IP_PKTINFO) {
- struct in_pktinfo *pktinfo;
- int i;
-
- pktinfo = (struct in_pktinfo *)CMSG_DATA(ptr);
- i = pktinfo->ipi_ifindex;
- }
- return ret;
-}
-
-/* RIP packet read function. */
-int rip_read_new(struct thread *t)
-{
- int ret;
- int sock;
- char buf[RIP_PACKET_MAXSIZ];
- struct sockaddr_in from;
- ifindex_t ifindex;
-
- /* Fetch socket then register myself. */
- sock = THREAD_FD(t);
- rip_event(RIP_READ, sock);
-
- /* Read RIP packet. */
- ret = rip_recvmsg(sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
- if (ret < 0) {
- zlog_warn("Can't read RIP packet: %s", safe_strerror(errno));
- return ret;
- }
-
- return ret;
+ rip->counters.queries++;
}
-#endif /* RIP_RECVMSG */
/* First entry point of RIP packet. */
static int rip_read(struct thread *t)
{
+ struct rip *rip = THREAD_ARG(t);
int sock;
int ret;
int rtenum;
@@ -1739,7 +1719,7 @@ static int rip_read(struct thread *t)
rip->t_read = NULL;
/* Add myself to tne next event */
- rip_event(RIP_READ, sock);
+ rip_event(rip, RIP_READ, sock);
/* RIPd manages only IPv4. */
memset(&from, 0, sizeof(struct sockaddr_in));
@@ -1748,33 +1728,37 @@ static int rip_read(struct thread *t)
len = recvfrom(sock, (char *)&rip_buf.buf, sizeof(rip_buf.buf), 0,
(struct sockaddr *)&from, &fromlen);
if (len < 0) {
- zlog_info("recvfrom failed: %s", safe_strerror(errno));
+ zlog_info("recvfrom failed (VRF %s): %s", rip->vrf_name,
+ safe_strerror(errno));
return len;
}
/* Check is this packet comming from myself? */
- if (if_check_address(from.sin_addr)) {
+ if (if_check_address(rip, from.sin_addr)) {
if (IS_RIP_DEBUG_PACKET)
- zlog_debug("ignore packet comes from myself");
+ zlog_debug("ignore packet comes from myself (VRF %s)",
+ rip->vrf_name);
return -1;
}
/* Which interface is this packet comes from. */
- ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, VRF_DEFAULT);
+ ifc = if_lookup_address((void *)&from.sin_addr, AF_INET,
+ rip->vrf->vrf_id);
if (ifc)
ifp = ifc->ifp;
/* RIP packet received */
if (IS_RIP_DEBUG_EVENT)
- zlog_debug("RECV packet from %s port %d on %s",
+ zlog_debug("RECV packet from %s port %d on %s (VRF %s)",
inet_ntoa(from.sin_addr), ntohs(from.sin_port),
- ifp ? ifp->name : "unknown");
+ ifp ? ifp->name : "unknown", rip->vrf_name);
/* If this packet come from unknown interface, ignore it. */
if (ifp == NULL) {
zlog_info(
- "rip_read: cannot find interface for packet from %s port %d",
- inet_ntoa(from.sin_addr), ntohs(from.sin_port));
+ "rip_read: cannot find interface for packet from %s port %d (VRF %s)",
+ inet_ntoa(from.sin_addr), ntohs(from.sin_port),
+ rip->vrf_name);
return -1;
}
@@ -1787,9 +1771,9 @@ static int rip_read(struct thread *t)
if (ifc == NULL) {
zlog_info(
"rip_read: cannot find connected address for packet from %s "
- "port %d on interface %s",
+ "port %d on interface %s (VRF %s)",
inet_ntoa(from.sin_addr), ntohs(from.sin_port),
- ifp->name);
+ ifp->name, rip->vrf_name);
return -1;
}
@@ -1797,13 +1781,13 @@ static int rip_read(struct thread *t)
if (len < RIP_PACKET_MINSIZ) {
zlog_warn("packet size %d is smaller than minimum size %d", len,
RIP_PACKET_MINSIZ);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return len;
}
if (len > RIP_PACKET_MAXSIZ) {
zlog_warn("packet size %d is larger than max size %d", len,
RIP_PACKET_MAXSIZ);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return len;
}
@@ -1811,7 +1795,7 @@ static int rip_read(struct thread *t)
if ((len - RIP_PACKET_MINSIZ) % 20) {
zlog_warn("packet size %d is wrong for RIP packet alignment",
len);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return len;
}
@@ -1825,7 +1809,7 @@ static int rip_read(struct thread *t)
if (packet->version == 0) {
zlog_info("version 0 with command %d received.",
packet->command);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
@@ -1842,11 +1826,11 @@ static int rip_read(struct thread *t)
/* Is RIP running or is this RIP neighbor ?*/
ri = ifp->info;
- if (!ri->running && !rip_neighbor_lookup(&from)) {
+ if (!ri->running && !rip_neighbor_lookup(rip, &from)) {
if (IS_RIP_DEBUG_EVENT)
zlog_debug("RIP is not enabled on interface %s.",
ifp->name);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
@@ -1860,7 +1844,7 @@ static int rip_read(struct thread *t)
zlog_debug(
" packet's v%d doesn't fit to if version spec",
packet->version);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
@@ -1875,7 +1859,7 @@ static int rip_read(struct thread *t)
"packet RIPv%d is dropped because authentication disabled",
packet->version);
ripd_notif_send_auth_type_failure(ifp->name);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
@@ -1912,7 +1896,7 @@ static int rip_read(struct thread *t)
"RIPv1"
" dropped because authentication enabled");
ripd_notif_send_auth_type_failure(ifp->name);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
} else if (ri->auth_type != RIP_NO_AUTH) {
@@ -1925,7 +1909,7 @@ static int rip_read(struct thread *t)
zlog_debug(
"RIPv2 authentication failed: no auth RTE in packet");
ripd_notif_send_auth_type_failure(ifp->name);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
@@ -1936,7 +1920,7 @@ static int rip_read(struct thread *t)
"RIPv2"
" dropped because authentication enabled");
ripd_notif_send_auth_type_failure(ifp->name);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
@@ -1972,7 +1956,7 @@ static int rip_read(struct thread *t)
zlog_debug("RIPv2 %s authentication failure",
auth_desc);
ripd_notif_send_auth_failure(ifp->name);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
return -1;
}
}
@@ -1991,16 +1975,16 @@ static int rip_read(struct thread *t)
zlog_info(
"Obsolete command %s received, please sent it to routed",
lookup_msg(rip_msg, packet->command, NULL));
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
break;
case RIP_POLL_ENTRY:
zlog_info("Obsolete command %s received",
lookup_msg(rip_msg, packet->command, NULL));
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
break;
default:
zlog_info("Unknown RIP command %d received", packet->command);
- rip_peer_bad_packet(&from);
+ rip_peer_bad_packet(rip, &from);
break;
}
@@ -2040,6 +2024,7 @@ static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p,
void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
int route_type, uint8_t version)
{
+ struct rip *rip;
int ret;
struct stream *s;
struct route_node *rp;
@@ -2069,6 +2054,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
ifc->ifp->name, ifc->ifp->ifindex);
}
+ /* Get RIP interface. */
+ ri = ifc->ifp->info;
+ rip = ri->rip;
+
/* Set output stream. */
s = rip->obuf;
@@ -2076,9 +2065,6 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
stream_reset(s);
rtemax = RIP_MAX_RTE;
- /* Get RIP interface. */
- ri = ifc->ifp->info;
-
/* If output interface is in simple password authentication mode, we
need space for authentication data. */
if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
@@ -2252,10 +2238,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
}
/* Apply redistribute route map - continue, if deny */
- if (rip->route_map[rinfo->type].name
+ if (rip->redist[rinfo->type].route_map.name
&& rinfo->sub_type != RIP_ROUTE_INTERFACE) {
ret = route_map_apply(
- rip->route_map[rinfo->type].map,
+ rip->redist[rinfo->type].route_map.map,
(struct prefix *)p, RMAP_RIP, rinfo);
if (ret == RMAP_DENYMATCH) {
@@ -2271,11 +2257,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
/* When route-map does not set metric. */
if (!rinfo->metric_set) {
/* If redistribute metric is set. */
- if (rip->route_map[rinfo->type].metric_config
+ if (rip->redist[rinfo->type].metric_config
&& rinfo->metric != RIP_METRIC_INFINITY) {
rinfo->metric_out =
- rip->route_map[rinfo->type]
- .metric;
+ rip->redist[rinfo->type].metric;
} else {
/* If the route is not connected or
localy generated
@@ -2450,9 +2435,8 @@ static void rip_update_interface(struct connected *ifc, uint8_t version,
}
/* Update send to all interface and neighbor. */
-static void rip_update_process(int route_type)
+static void rip_update_process(struct rip *rip, int route_type)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct listnode *ifnode, *ifnnode;
struct connected *connected;
struct interface *ifp;
@@ -2462,7 +2446,7 @@ static void rip_update_process(int route_type)
struct prefix *p;
/* Send RIP update to each interface. */
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (rip->vrf, ifp) {
if (if_is_loopback(ifp))
continue;
@@ -2515,7 +2499,7 @@ static void rip_update_process(int route_type)
p = &rp->p;
connected = if_lookup_address(&p->u.prefix4, AF_INET,
- VRF_DEFAULT);
+ rip->vrf->vrf_id);
if (!connected) {
zlog_warn(
"Neighbor %s doesn't have connected interface!",
@@ -2537,6 +2521,8 @@ static void rip_update_process(int route_type)
/* RIP's periodical timer. */
static int rip_update(struct thread *t)
{
+ struct rip *rip = THREAD_ARG(t);
+
/* Clear timer pointer. */
rip->t_update = NULL;
@@ -2544,7 +2530,7 @@ static int rip_update(struct thread *t)
zlog_debug("update timer fire!");
/* Process update output. */
- rip_update_process(rip_all_route);
+ rip_update_process(rip, rip_all_route);
/* Triggered updates may be suppressed if a regular update is due by
the time the triggered update would be sent. */
@@ -2552,13 +2538,13 @@ static int rip_update(struct thread *t)
rip->trigger = 0;
/* Register myself. */
- rip_event(RIP_UPDATE_EVENT, 0);
+ rip_event(rip, RIP_UPDATE_EVENT, 0);
return 0;
}
/* Walk down the RIP routing table then clear changed flag. */
-static void rip_clear_changed_flag(void)
+static void rip_clear_changed_flag(struct rip *rip)
{
struct route_node *rp;
struct rip_info *rinfo = NULL;
@@ -2578,7 +2564,7 @@ static void rip_clear_changed_flag(void)
/* Triggered update interval timer. */
static int rip_triggered_interval(struct thread *t)
{
- int rip_triggered_update(struct thread *);
+ struct rip *rip = THREAD_ARG(t);
rip->t_triggered_interval = NULL;
@@ -2592,6 +2578,7 @@ static int rip_triggered_interval(struct thread *t)
/* Execute triggered update. */
static int rip_triggered_update(struct thread *t)
{
+ struct rip *rip = THREAD_ARG(t);
int interval;
/* Clear thred pointer. */
@@ -2607,11 +2594,11 @@ static int rip_triggered_update(struct thread *t)
/* Split Horizon processing is done when generating triggered
updates as well as normal updates (see section 2.6). */
- rip_update_process(rip_changed_route);
+ rip_update_process(rip, rip_changed_route);
/* Once all of the triggered updates have been generated, the route
change flags should be cleared. */
- rip_clear_changed_flag();
+ rip_clear_changed_flag(rip);
/* After a triggered update is sent, a timer should be set for a
random interval between 1 and 5 seconds. If other changes that
@@ -2620,22 +2607,19 @@ static int rip_triggered_update(struct thread *t)
interval = (random() % 5) + 1;
rip->t_triggered_interval = NULL;
- thread_add_timer(master, rip_triggered_interval, NULL, interval,
+ thread_add_timer(master, rip_triggered_interval, rip, interval,
&rip->t_triggered_interval);
return 0;
}
/* Withdraw redistributed route. */
-void rip_redistribute_withdraw(int type)
+void rip_redistribute_withdraw(struct rip *rip, int type)
{
struct route_node *rp;
struct rip_info *rinfo = NULL;
struct list *list = NULL;
- if (!rip)
- return;
-
for (rp = route_top(rip->table); rp; rp = route_next(rp))
if ((list = rp->info) != NULL) {
rinfo = listgetdata(listhead(list));
@@ -2659,18 +2643,41 @@ void rip_redistribute_withdraw(int type)
p->prefixlen,
ifindex2ifname(
rinfo->nh.ifindex,
- VRF_DEFAULT));
+ rip->vrf->vrf_id));
}
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
}
}
}
+struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id)
+{
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
+ return vrf->info;
+}
+
+struct rip *rip_lookup_by_vrf_name(const char *vrf_name)
+{
+ struct rip rip;
+
+ rip.vrf_name = (char *)vrf_name;
+
+ return RB_FIND(rip_instance_head, &rip_instances, &rip);
+}
+
/* Create new RIP instance and set it to global variable. */
-int rip_create(int socket)
+struct rip *rip_create(const char *vrf_name, struct vrf *vrf, int socket)
{
+ struct rip *rip;
+
rip = XCALLOC(MTYPE_RIP, sizeof(struct rip));
+ rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf_name);
/* Set initial value. */
rip->ecmp = yang_get_default_bool("%s/allow-ecmp", RIP_INSTANCE);
@@ -2691,33 +2698,46 @@ int rip_create(int socket)
rip->version_recv =
yang_get_default_enum("%s/version/receive", RIP_INSTANCE);
- /* Initialize RIP routig table. */
+ /* Initialize RIP data structures. */
rip->table = route_table_init();
+ route_table_set_info(rip->table, rip);
rip->neighbor = route_table_init();
+ rip->peer_list = list_new();
+ rip->peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
+ rip->peer_list->del = rip_peer_list_del;
+ rip->distance_table = route_table_init();
+ rip->distance_table->cleanup = rip_distance_table_node_cleanup;
+ rip->enable_interface = vector_init(1);
+ rip->enable_network = route_table_init();
+ rip->passive_nondefault = vector_init(1);
+ 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;
- /* Make output stream. */
- rip->obuf = stream_new(1500);
-
- /* Set socket. */
- rip->sock = socket;
-
- /* Create read and timer thread. */
- rip_event(RIP_READ, rip->sock);
- rip_event(RIP_UPDATE_EVENT, 1);
/* Distribute list install. */
- rip->distribute_ctx = distribute_list_ctx_create(
- vrf_lookup_by_id(VRF_DEFAULT));
- distribute_list_add_hook(rip->distribute_ctx,
- rip_distribute_update);
- distribute_list_delete_hook(rip->distribute_ctx,
- rip_distribute_update);
+ rip->distribute_ctx = distribute_list_ctx_create(vrf);
+ distribute_list_add_hook(rip->distribute_ctx, rip_distribute_update);
+ distribute_list_delete_hook(rip->distribute_ctx, rip_distribute_update);
/* if rmap install. */
- rip->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ rip->if_rmap_ctx = if_rmap_ctx_create(vrf_name);
if_rmap_hook_add(rip->if_rmap_ctx, rip_if_rmap_update);
if_rmap_hook_delete(rip->if_rmap_ctx, rip_if_rmap_update);
- return 0;
+ /* Make output stream. */
+ rip->obuf = stream_new(1500);
+
+ /* Enable the routing instance if possible. */
+ if (vrf && vrf_is_enabled(vrf))
+ rip_instance_enable(rip, vrf, socket);
+ else {
+ rip->vrf = NULL;
+ rip->sock = -1;
+ }
+
+ RB_INSERT(rip_instance_head, &rip_instances, rip);
+
+ return rip;
}
/* Sned RIP request to the destination. */
@@ -2786,19 +2806,19 @@ static int rip_update_jitter(unsigned long time)
return jitter / JITTER_BOUND;
}
-void rip_event(enum rip_event event, int sock)
+void rip_event(struct rip *rip, enum rip_event event, int sock)
{
int jitter = 0;
switch (event) {
case RIP_READ:
rip->t_read = NULL;
- thread_add_read(master, rip_read, NULL, sock, &rip->t_read);
+ thread_add_read(master, rip_read, rip, sock, &rip->t_read);
break;
case RIP_UPDATE_EVENT:
RIP_TIMER_OFF(rip->t_update);
jitter = rip_update_jitter(rip->update_time);
- thread_add_timer(master, rip_update, NULL,
+ thread_add_timer(master, rip_update, rip,
sock ? 2 : rip->update_time + jitter,
&rip->t_update);
break;
@@ -2806,7 +2826,7 @@ void rip_event(enum rip_event event, int sock)
if (rip->t_triggered_interval)
rip->trigger = 1;
else
- thread_add_event(master, rip_triggered_update, NULL, 0,
+ thread_add_event(master, rip_triggered_update, rip, 0,
&rip->t_triggered_update);
break;
default:
@@ -2831,9 +2851,6 @@ rip_update_default_metric (void)
}
#endif
-
-struct route_table *rip_distance_table;
-
struct rip_distance *rip_distance_new(void)
{
return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance));
@@ -2841,42 +2858,36 @@ struct rip_distance *rip_distance_new(void)
void rip_distance_free(struct rip_distance *rdistance)
{
+ if (rdistance->access_list)
+ free(rdistance->access_list);
XFREE(MTYPE_RIP_DISTANCE, rdistance);
}
-static void rip_distance_reset(void)
+static void rip_distance_table_node_cleanup(struct route_table *table,
+ struct route_node *node)
{
- struct route_node *rn;
struct rip_distance *rdistance;
- for (rn = route_top(rip_distance_table); rn; rn = route_next(rn))
- if ((rdistance = rn->info) != NULL) {
- if (rdistance->access_list)
- free(rdistance->access_list);
- rip_distance_free(rdistance);
- rn->info = NULL;
- route_unlock_node(rn);
- }
+ rdistance = node->info;
+ if (rdistance)
+ rip_distance_free(rdistance);
}
/* Apply RIP information to distance method. */
-uint8_t rip_distance_apply(struct rip_info *rinfo)
+uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo)
{
struct route_node *rn;
struct prefix_ipv4 p;
struct rip_distance *rdistance;
struct access_list *alist;
- if (!rip)
- return 0;
-
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
p.prefix = rinfo->from;
p.prefixlen = IPV4_MAX_BITLEN;
/* Check source address. */
- rn = route_node_match(rip_distance_table, (struct prefix *)&p);
+ rn = route_node_match(rip->distance_table, (struct prefix *)&p);
if (rn) {
rdistance = rn->info;
route_unlock_node(rn);
@@ -2901,7 +2912,7 @@ uint8_t rip_distance_apply(struct rip_info *rinfo)
return 0;
}
-static void rip_distance_show(struct vty *vty)
+static void rip_distance_show(struct vty *vty, struct rip *rip)
{
struct route_node *rn;
struct rip_distance *rdistance;
@@ -2911,7 +2922,7 @@ static void rip_distance_show(struct vty *vty)
vty_out(vty, " Distance: (default is %u)\n",
rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT);
- for (rn = route_top(rip_distance_table); rn; rn = route_next(rn))
+ for (rn = route_top(rip->distance_table); rn; rn = route_next(rn))
if ((rdistance = rn->info) != NULL) {
if (header) {
vty_out(vty,
@@ -2928,16 +2939,13 @@ static void rip_distance_show(struct vty *vty)
}
/* Update ECMP routes to zebra when ECMP is disabled. */
-void rip_ecmp_disable(void)
+void rip_ecmp_disable(struct rip *rip)
{
struct route_node *rp;
struct rip_info *rinfo, *tmp_rinfo;
struct list *list;
struct listnode *node, *nextnode;
- if (!rip)
- return;
-
for (rp = route_top(rip->table); rp; rp = route_next(rp))
if ((list = rp->info) != NULL && listcount(list) > 1) {
rinfo = listgetdata(listhead(list));
@@ -2955,13 +2963,13 @@ void rip_ecmp_disable(void)
}
/* Update zebra. */
- rip_zebra_ipv4_add(rp);
+ rip_zebra_ipv4_add(rip, rp);
/* Set the route change flag. */
SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
}
}
@@ -3007,18 +3015,34 @@ static const char *rip_route_type_print(int sub_type)
DEFUN (show_ip_rip,
show_ip_rip_cmd,
- "show ip rip",
+ "show ip rip [vrf NAME]",
SHOW_STR
IP_STR
- "Show RIP routes\n")
+ "Show RIP routes\n"
+ VRF_CMD_HELP_STR)
{
+ struct rip *rip;
struct route_node *np;
struct rip_info *rinfo = NULL;
struct list *list = NULL;
struct listnode *listnode = NULL;
+ const char *vrf_name;
+ int idx = 0;
- if (!rip)
+ if (argv_find(argv, argc, "vrf", &idx))
+ vrf_name = argv[idx + 1]->arg;
+ else
+ vrf_name = VRF_DEFAULT_NAME;
+
+ rip = rip_lookup_by_vrf_name(vrf_name);
+ if (!rip) {
+ vty_out(vty, "%% RIP instance not found\n");
return CMD_SUCCESS;
+ }
+ if (!rip->enabled) {
+ vty_out(vty, "%% RIP instance is disabled\n");
+ return CMD_SUCCESS;
+ }
vty_out(vty,
"Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n"
@@ -3110,21 +3134,36 @@ DEFUN (show_ip_rip,
/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
DEFUN (show_ip_rip_status,
show_ip_rip_status_cmd,
- "show ip rip status",
+ "show ip rip [vrf NAME] status",
SHOW_STR
IP_STR
"Show RIP routes\n"
+ VRF_CMD_HELP_STR
"IP routing protocol process parameters and statistics\n")
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct rip *rip;
struct interface *ifp;
struct rip_interface *ri;
extern const struct message ri_version_msg[];
const char *send_version;
const char *receive_version;
+ const char *vrf_name;
+ int idx = 0;
- if (!rip)
+ if (argv_find(argv, argc, "vrf", &idx))
+ vrf_name = argv[idx + 1]->arg;
+ else
+ vrf_name = VRF_DEFAULT_NAME;
+
+ rip = rip_lookup_by_vrf_name(vrf_name);
+ if (!rip) {
+ vty_out(vty, "%% RIP instance not found\n");
+ return CMD_SUCCESS;
+ }
+ if (!rip->enabled) {
+ vty_out(vty, "%% RIP instance is disabled\n");
return CMD_SUCCESS;
+ }
vty_out(vty, "Routing Protocol is \"rip\"\n");
vty_out(vty, " Sending updates every %u seconds with +/-50%%,",
@@ -3143,7 +3182,7 @@ DEFUN (show_ip_rip_status,
/* Redistribute information. */
vty_out(vty, " Redistributing:");
- rip_show_redistribute_config(vty);
+ rip_show_redistribute_config(vty, rip);
vty_out(vty, "\n");
vty_out(vty, " Default version control: send version %s,",
@@ -3156,7 +3195,7 @@ DEFUN (show_ip_rip_status,
vty_out(vty, " Interface Send Recv Key-chain\n");
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (rip->vrf, ifp) {
ri = ifp->info;
if (!ri->running)
@@ -3186,11 +3225,11 @@ DEFUN (show_ip_rip_status,
}
vty_out(vty, " Routing for Networks:\n");
- rip_show_network_config(vty);
+ rip_show_network_config(vty, rip);
{
int found_passive = 0;
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (rip->vrf, ifp) {
ri = ifp->info;
if ((ri->enable_network || ri->enable_interface)
@@ -3208,9 +3247,9 @@ DEFUN (show_ip_rip_status,
vty_out(vty, " Routing Information Sources:\n");
vty_out(vty,
" Gateway BadPackets BadRoutes Distance Last Update\n");
- rip_peer_display(vty);
+ rip_peer_display(vty, rip);
- rip_distance_show(vty);
+ rip_distance_show(vty, rip);
return CMD_SUCCESS;
}
@@ -3218,23 +3257,30 @@ DEFUN (show_ip_rip_status,
/* RIP configuration write function. */
static int config_write_rip(struct vty *vty)
{
+ struct rip *rip;
int write = 0;
- struct lyd_node *dnode;
- dnode = yang_dnode_get(running_config->dnode,
- "/frr-ripd:ripd/instance");
- if (dnode) {
- write++;
+ RB_FOREACH(rip, rip_instance_head, &rip_instances) {
+ char xpath[XPATH_MAXLEN];
+ struct lyd_node *dnode;
+
+ snprintf(xpath, sizeof(xpath),
+ "/frr-ripd:ripd/instance[vrf='%s']", rip->vrf_name);
+
+ dnode = yang_dnode_get(running_config->dnode, xpath);
+ assert(dnode);
nb_cli_show_dnode_cmds(vty, dnode, false);
/* Distribute configuration. */
- write += config_write_distribute(vty,
- rip->distribute_ctx);
+ config_write_distribute(vty, rip->distribute_ctx);
/* Interface routemap configuration */
- write += config_write_if_rmap(vty, rip->if_rmap_ctx);
+ config_write_if_rmap(vty, rip->if_rmap_ctx);
+
+ write = 1;
}
+
return write;
}
@@ -3250,10 +3296,10 @@ static void rip_distribute_update(struct distribute_ctx *ctx,
struct access_list *alist;
struct prefix_list *plist;
- if (!dist->ifname)
+ if (!ctx->vrf || !dist->ifname)
return;
- ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT);
+ ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id);
if (ifp == NULL)
return;
@@ -3302,6 +3348,8 @@ static void rip_distribute_update(struct distribute_ctx *ctx,
void rip_distribute_update_interface(struct interface *ifp)
{
+ struct rip_interface *ri = ifp->info;
+ struct rip *rip = ri->rip;
struct distribute *dist;
if (!rip)
@@ -3328,77 +3376,35 @@ static void rip_distribute_update_all_wrapper(struct access_list *notused)
}
/* Delete all added rip route. */
-void rip_clean(void)
+void rip_clean(struct rip *rip)
{
- int i;
- struct route_node *rp;
- struct rip_info *rinfo = NULL;
- struct list *list = NULL;
- struct listnode *listnode = NULL;
-
- if (rip) {
- /* Clear RIP routes */
- for (rp = route_top(rip->table); rp; rp = route_next(rp))
- if ((list = rp->info) != NULL) {
- rinfo = listgetdata(listhead(list));
- if (rip_route_rte(rinfo))
- rip_zebra_ipv4_delete(rp);
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode,
- rinfo)) {
- RIP_TIMER_OFF(rinfo->t_timeout);
- RIP_TIMER_OFF(rinfo->t_garbage_collect);
- rip_info_free(rinfo);
- }
- list_delete(&list);
- rp->info = NULL;
- route_unlock_node(rp);
- }
-
- /* Cancel RIP related timers. */
- RIP_TIMER_OFF(rip->t_update);
- RIP_TIMER_OFF(rip->t_triggered_update);
- RIP_TIMER_OFF(rip->t_triggered_interval);
-
- /* Cancel read thread. */
- THREAD_READ_OFF(rip->t_read);
-
- /* Close RIP socket. */
- if (rip->sock >= 0) {
- close(rip->sock);
- rip->sock = -1;
- }
-
- stream_free(rip->obuf);
-
- /* RIP neighbor configuration. */
- for (rp = route_top(rip->neighbor); rp; rp = route_next(rp))
- if (rp->info) {
- rp->info = NULL;
- route_unlock_node(rp);
- }
+ if (rip->enabled)
+ rip_instance_disable(rip);
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (rip->route_map[i].name)
- free(rip->route_map[i].name);
+ stream_free(rip->obuf);
- route_table_finish(rip->table);
- route_table_finish(rip->neighbor);
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (rip->redist[i].route_map.name)
+ free(rip->redist[i].route_map.name);
- distribute_list_delete(&rip->distribute_ctx);
+ route_table_finish(rip->table);
+ route_table_finish(rip->neighbor);
+ list_delete(&rip->peer_list);
+ distribute_list_delete(&rip->distribute_ctx);
+ if_rmap_ctx_delete(rip->if_rmap_ctx);
- if_rmap_ctx_delete(rip->if_rmap_ctx);
+ rip_clean_network(rip);
+ rip_passive_nondefault_clean(rip);
+ vector_free(rip->enable_interface);
+ route_table_finish(rip->enable_network);
+ vector_free(rip->passive_nondefault);
+ list_delete(&rip->offset_list_master);
+ rip_interfaces_clean(rip);
+ route_table_finish(rip->distance_table);
- XFREE(MTYPE_RIP, rip);
- rip = NULL;
- }
- rip_clean_network();
- rip_passive_nondefault_clean();
- rip_offset_clean();
- rip_interfaces_clean();
- rip_distance_reset();
- rip_redistribute_clean();
- if_rmap_terminate();
+ RB_REMOVE(rip_instance_head, &rip_instances, rip);
+ XFREE(MTYPE_RIP_VRF_NAME, rip->vrf_name);
+ XFREE(MTYPE_RIP, rip);
}
static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
@@ -3438,13 +3444,13 @@ static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
void rip_if_rmap_update_interface(struct interface *ifp)
{
+ struct rip_interface *ri = ifp->info;
+ struct rip *rip = ri->rip;
struct if_rmap *if_rmap;
struct if_rmap_ctx *ctx;
if (!rip)
return;
- if (ifp->vrf_id != VRF_DEFAULT)
- return;
ctx = rip->if_rmap_ctx;
if (!ctx)
return;
@@ -3453,19 +3459,14 @@ void rip_if_rmap_update_interface(struct interface *ifp)
rip_if_rmap_update(ctx, if_rmap);
}
-static void rip_routemap_update_redistribute(void)
+static void rip_routemap_update_redistribute(struct rip *rip)
{
- int i;
-
- if (rip) {
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (rip->route_map[i].name) {
- rip->route_map[i].map =
- route_map_lookup_by_name(
- rip->route_map[i].name);
- route_map_counter_increment(
- rip->route_map[i].map);
- }
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ if (rip->redist[i].route_map.name) {
+ rip->redist[i].route_map.map = route_map_lookup_by_name(
+ rip->redist[i].route_map.name);
+ route_map_counter_increment(
+ rip->redist[i].route_map.map);
}
}
}
@@ -3474,12 +3475,183 @@ static void rip_routemap_update_redistribute(void)
static void rip_routemap_update(const char *notused)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct rip *rip;
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
rip_if_rmap_update_interface(ifp);
- rip_routemap_update_redistribute();
+ rip = vrf->info;
+ if (rip)
+ rip_routemap_update_redistribute(rip);
+}
+
+/* Link RIP instance to VRF. */
+static void rip_vrf_link(struct rip *rip, struct vrf *vrf)
+{
+ struct interface *ifp;
+
+ rip->vrf = vrf;
+ rip->distribute_ctx->vrf = vrf;
+ vrf->info = rip;
+
+ FOR_ALL_INTERFACES (vrf, ifp)
+ rip_interface_sync(ifp);
+}
+
+/* Unlink RIP instance from VRF. */
+static void rip_vrf_unlink(struct rip *rip, struct vrf *vrf)
+{
+ struct interface *ifp;
+
+ rip->vrf = NULL;
+ rip->distribute_ctx->vrf = NULL;
+ vrf->info = NULL;
+
+ FOR_ALL_INTERFACES (vrf, ifp)
+ rip_interface_sync(ifp);
+}
+
+static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock)
+{
+ rip->sock = sock;
+
+ rip_vrf_link(rip, vrf);
+ rip->enabled = true;
+
+ /* Resend all redistribute requests. */
+ rip_redistribute_enable(rip);
+
+ /* Create read and timer thread. */
+ rip_event(rip, RIP_READ, rip->sock);
+ rip_event(rip, RIP_UPDATE_EVENT, 1);
+
+ rip_zebra_vrf_register(vrf);
+}
+
+static void rip_instance_disable(struct rip *rip)
+{
+ struct vrf *vrf = rip->vrf;
+ struct route_node *rp;
+
+ /* Clear RIP routes */
+ for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
+ struct rip_info *rinfo;
+ struct list *list;
+ struct listnode *listnode;
+
+ if ((list = rp->info) == NULL)
+ continue;
+
+ rinfo = listgetdata(listhead(list));
+ if (rip_route_rte(rinfo))
+ rip_zebra_ipv4_delete(rip, rp);
+
+ for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+ RIP_TIMER_OFF(rinfo->t_timeout);
+ RIP_TIMER_OFF(rinfo->t_garbage_collect);
+ rip_info_free(rinfo);
+ }
+ list_delete(&list);
+ rp->info = NULL;
+ route_unlock_node(rp);
+ }
+
+ /* Flush all redistribute requests. */
+ rip_redistribute_disable(rip);
+
+ /* Cancel RIP related timers. */
+ RIP_TIMER_OFF(rip->t_update);
+ RIP_TIMER_OFF(rip->t_triggered_update);
+ RIP_TIMER_OFF(rip->t_triggered_interval);
+
+ /* Cancel read thread. */
+ THREAD_READ_OFF(rip->t_read);
+
+ /* Close RIP socket. */
+ close(rip->sock);
+ rip->sock = -1;
+
+ /* Clear existing peers. */
+ list_delete_all_node(rip->peer_list);
+
+ rip_zebra_vrf_deregister(vrf);
+
+ rip_vrf_unlink(rip, vrf);
+ rip->enabled = false;
+}
+
+static int rip_vrf_new(struct vrf *vrf)
+{
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name,
+ vrf->vrf_id);
+
+ return 0;
+}
+
+static int rip_vrf_delete(struct vrf *vrf)
+{
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name,
+ vrf->vrf_id);
+
+ return 0;
+}
+
+static int rip_vrf_enable(struct vrf *vrf)
+{
+ struct rip *rip;
+ int socket;
+
+ rip = rip_lookup_by_vrf_name(vrf->name);
+ if (!rip || rip->enabled)
+ return 0;
+
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name,
+ vrf->vrf_id);
+
+ /* Activate the VRF RIP instance. */
+ if (!rip->enabled) {
+ socket = rip_create_socket(vrf);
+ if (socket < 0)
+ return -1;
+
+ rip_instance_enable(rip, vrf, socket);
+ }
+
+ return 0;
+}
+
+static int rip_vrf_disable(struct vrf *vrf)
+{
+ struct rip *rip;
+
+ rip = rip_lookup_by_vrf_name(vrf->name);
+ if (!rip || !rip->enabled)
+ return 0;
+
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name,
+ vrf->vrf_id);
+
+ /* Deactivate the VRF RIP instance. */
+ if (rip->enabled)
+ rip_instance_disable(rip);
+
+ return 0;
+}
+
+void rip_vrf_init(void)
+{
+ vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete,
+ NULL);
+}
+
+void rip_vrf_terminate(void)
+{
+ vrf_terminate();
}
/* Allocate new rip structure and set default value. */
@@ -3512,13 +3684,9 @@ void rip_init(void)
/* Route-map */
rip_route_map_init();
- rip_offset_init();
route_map_add_hook(rip_routemap_update);
route_map_delete_hook(rip_routemap_update);
if_rmap_init(RIP_NODE);
-
- /* Distance control. */
- rip_distance_table = route_table_init();
}
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 383df3707..7b196a16b 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -99,6 +99,17 @@
/* RIP structure. */
struct rip {
+ RB_ENTRY(rip) entry;
+
+ /* VRF this routing instance is associated with. */
+ char *vrf_name;
+
+ /* VRF backpointer (might be NULL if the VRF doesn't exist). */
+ struct vrf *vrf;
+
+ /* Status of the routing instance. */
+ bool enabled;
+
/* RIP socket. */
int sock;
@@ -112,9 +123,12 @@ struct rip {
/* RIP routing information base. */
struct route_table *table;
- /* RIP neighbor. */
+ /* RIP static neighbors. */
struct route_table *neighbor;
+ /* Linked list of RIP peers. */
+ struct list *peer_list;
+
/* RIP threads. */
struct thread *t_read;
@@ -144,20 +158,46 @@ struct rip {
/* Are we in passive-interface default mode? */
bool passive_default;
- /* For redistribute route map. */
+ /* RIP enabled interfaces. */
+ vector enable_interface;
+
+ /* RIP enabled networks. */
+ struct route_table *enable_network;
+
+ /* Vector to store passive-interface name. */
+ vector passive_nondefault;
+
+ /* RIP offset-lists. */
+ struct list *offset_list_master;
+
+ /* RIP redistribute configuration. */
struct {
- char *name;
- struct route_map *map;
+ bool enabled;
+ struct {
+ char *name;
+ struct route_map *map;
+ } route_map;
bool metric_config;
uint8_t metric;
- } route_map[ZEBRA_ROUTE_MAX];
+ } redist[ZEBRA_ROUTE_MAX];
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
/* For if_rmap container */
struct if_rmap_ctx *if_rmap_ctx;
+
+ /* Counters for SNMP. */
+ struct {
+ /* RIP route changes. */
+ long route_changes;
+
+ /* RIP queries. */
+ long queries;
+ } counters;
};
+RB_HEAD(rip_instance_head, rip);
+RB_PROTOTYPE(rip_instance_head, rip, entry, rip_instance_compare)
/* RIP routing table entry which belong to rip_packet. */
struct rte {
@@ -225,11 +265,6 @@ struct rip_info {
struct route_node *rp;
uint8_t distance;
-
-#ifdef NEW_RIP_TABLE
- struct rip_info *next;
- struct rip_info *prev;
-#endif /* NEW_RIP_TABLE */
};
typedef enum {
@@ -240,6 +275,9 @@ typedef enum {
/* RIP specific interface configuration. */
struct rip_interface {
+ /* Parent routing instance. */
+ struct rip *rip;
+
/* RIP is enabled on this interface. */
int enable_network;
int enable_interface;
@@ -297,6 +335,9 @@ struct rip_interface {
/* RIP peer information. */
struct rip_peer {
+ /* Parent routing instance. */
+ struct rip *rip;
+
/* Peer address. */
struct in_addr addr;
@@ -369,6 +410,9 @@ enum rip_event {
#define RIP_OFFSET_LIST_MAX 2
struct rip_offset_list {
+ /* Parent routing instance. */
+ struct rip *rip;
+
char *ifname;
struct {
@@ -380,104 +424,114 @@ struct rip_offset_list {
/* Prototypes. */
extern void rip_init(void);
-extern void rip_clean(void);
-extern void rip_clean_network(void);
-extern void rip_interfaces_clean(void);
-extern int rip_passive_nondefault_set(const char *ifname);
-extern int rip_passive_nondefault_unset(const char *ifname);
-extern void rip_passive_nondefault_clean(void);
+extern void rip_clean(struct rip *rip);
+extern void rip_clean_network(struct rip *rip);
+extern void rip_interfaces_clean(struct rip *rip);
+extern int rip_passive_nondefault_set(struct rip *rip, const char *ifname);
+extern int rip_passive_nondefault_unset(struct rip *rip, const char *ifname);
+extern void rip_passive_nondefault_clean(struct rip *rip);
extern void rip_if_init(void);
-extern void rip_if_down_all(void);
extern void rip_route_map_init(void);
+extern void rip_zebra_vrf_register(struct vrf *vrf);
+extern void rip_zebra_vrf_deregister(struct vrf *vrf);
extern void rip_zclient_init(struct thread_master *);
extern void rip_zclient_stop(void);
-extern int if_check_address(struct in_addr addr);
-extern int rip_create(int socket);
+extern int if_check_address(struct rip *rip, struct in_addr addr);
+extern struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id);
+extern struct rip *rip_lookup_by_vrf_name(const char *vrf_name);
+extern struct rip *rip_create(const char *vrf_name, struct vrf *vrf,
+ int socket);
extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
struct connected *);
-extern int rip_neighbor_lookup(struct sockaddr_in *);
-extern int rip_neighbor_add(struct prefix_ipv4 *p);
-extern int rip_neighbor_delete(struct prefix_ipv4 *p);
-
-extern int rip_enable_network_add(struct prefix *p);
-extern int rip_enable_network_delete(struct prefix *p);
-extern int rip_enable_if_add(const char *ifname);
-extern int rip_enable_if_delete(const char *ifname);
-
-extern void rip_event(enum rip_event, int);
-extern void rip_ecmp_disable(void);
-
-extern int rip_create_socket(void);
-
-extern int rip_redistribute_check(int);
-extern void rip_redistribute_conf_update(int type);
-extern void rip_redistribute_conf_delete(int type);
-extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
- struct nexthop *nh, unsigned int metric,
- unsigned char distance, route_tag_t tag);
-extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t);
-extern void rip_redistribute_withdraw(int);
-extern void rip_zebra_ipv4_add(struct route_node *);
-extern void rip_zebra_ipv4_delete(struct route_node *);
+extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from);
+extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p);
+extern int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p);
+
+extern int rip_enable_network_add(struct rip *rip, struct prefix *p);
+extern int rip_enable_network_delete(struct rip *rip, struct prefix *p);
+extern int rip_enable_if_add(struct rip *rip, const char *ifname);
+extern int rip_enable_if_delete(struct rip *rip, const char *ifname);
+
+extern void rip_event(struct rip *rip, enum rip_event event, int sock);
+extern void rip_ecmp_disable(struct rip *rip);
+
+extern int rip_create_socket(struct vrf *vrf);
+
+extern int rip_redistribute_check(struct rip *rip, int type);
+extern void rip_redistribute_conf_update(struct rip *rip, int type);
+extern void rip_redistribute_conf_delete(struct rip *rip, int type);
+extern void rip_redistribute_add(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, struct nexthop *nh,
+ unsigned int metric, unsigned char distance,
+ route_tag_t tag);
+extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, ifindex_t ifindex);
+extern void rip_redistribute_withdraw(struct rip *rip, int type);
+extern void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp);
+extern void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp);
extern void rip_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *);
extern void rip_if_rmap_update_interface(struct interface *ifp);
-extern int rip_show_network_config(struct vty *);
-extern void rip_show_redistribute_config(struct vty *);
-extern void rip_peer_init(void);
-extern void rip_peer_update(struct sockaddr_in *, uint8_t);
-extern void rip_peer_bad_route(struct sockaddr_in *);
-extern void rip_peer_bad_packet(struct sockaddr_in *);
-extern void rip_peer_display(struct vty *);
-extern struct rip_peer *rip_peer_lookup(struct in_addr *);
-extern struct rip_peer *rip_peer_lookup_next(struct in_addr *);
+extern int rip_show_network_config(struct vty *vty, struct rip *rip);
+extern void rip_show_redistribute_config(struct vty *vty, struct rip *rip);
+
+extern void rip_peer_update(struct rip *rip, struct sockaddr_in *from,
+ uint8_t version);
+extern void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from);
+extern void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from);
+extern void rip_peer_display(struct vty *vty, struct rip *rip);
+extern struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr);
+extern struct rip_peer *rip_peer_lookup_next(struct rip *rip,
+ struct in_addr *addr);
+extern int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2);
+extern void rip_peer_list_del(void *arg);
extern void rip_info_free(struct rip_info *);
+extern struct rip *rip_info_get_instance(const struct rip_info *rinfo);
extern struct rip_distance *rip_distance_new(void);
extern void rip_distance_free(struct rip_distance *rdistance);
-extern uint8_t rip_distance_apply(struct rip_info *);
-extern void rip_redistribute_clean(void);
+extern uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo);
+extern void rip_redistribute_enable(struct rip *rip);
+extern void rip_redistribute_disable(struct rip *rip);
extern int rip_route_rte(struct rip_info *rinfo);
-extern struct rip_info *rip_ecmp_add(struct rip_info *);
-extern struct rip_info *rip_ecmp_replace(struct rip_info *);
-extern struct rip_info *rip_ecmp_delete(struct rip_info *);
-
-extern struct rip_offset_list *rip_offset_list_new(const char *ifname);
+extern struct rip_info *rip_ecmp_add(struct rip *rip,
+ struct rip_info *rinfo_new);
+extern struct rip_info *rip_ecmp_replace(struct rip *rip,
+ struct rip_info *rinfo_new);
+extern struct rip_info *rip_ecmp_delete(struct rip *rip,
+ struct rip_info *rinfo);
+
+extern struct rip_offset_list *rip_offset_list_new(struct rip *rip,
+ const char *ifname);
extern void offset_list_del(struct rip_offset_list *offset);
-extern struct rip_offset_list *rip_offset_list_lookup(const char *ifname);
+extern struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
+ const char *ifname);
extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *,
uint32_t *);
extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *,
uint32_t *);
-extern void rip_offset_init(void);
-extern void rip_offset_clean(void);
+extern int offset_list_cmp(struct rip_offset_list *o1,
+ struct rip_offset_list *o2);
+
+extern void rip_vrf_init(void);
+extern void rip_vrf_terminate(void);
/* YANG notifications */
extern void ripd_notif_send_auth_type_failure(const char *ifname);
extern void ripd_notif_send_auth_failure(const char *ifname);
-/* There is only one rip strucutre. */
-extern struct rip *rip;
-
extern struct zebra_privs_t ripd_privs;
+extern struct rip_instance_head rip_instances;
/* Master thread strucutre. */
extern struct thread_master *master;
-/* RIP statistics for SNMP. */
-extern long rip_global_route_changes;
-extern long rip_global_queries;
-
DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc))
DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
-extern struct list *peer_list;
-extern struct route_table *rip_distance_table;
-extern vector Vrip_passive_nondefault;
-
/* Northbound. */
extern void rip_cli_init(void);
extern const struct frr_yang_module_info frr_ripd_info;
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index 23a480317..e95c0e95d 100644
--- a/ripngd/ripng_cli.c
+++ b/ripngd/ripng_cli.c
@@ -39,31 +39,46 @@
*/
DEFPY_NOSH (router_ripng,
router_ripng_cmd,
- "router ripng",
+ "router ripng [vrf NAME]",
"Enable a routing process\n"
- "Make RIPng instance command\n")
+ "Make RIPng instance command\n"
+ VRF_CMD_HELP_STR)
{
+ char xpath[XPATH_MAXLEN];
int ret;
- nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE,
- NULL);
+ /* Build RIPng instance XPath. */
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
+ snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
+ vrf);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS)
- VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance");
+ VTY_PUSH_XPATH(RIPNG_NODE, xpath);
return ret;
}
DEFPY (no_router_ripng,
no_router_ripng_cmd,
- "no router ripng",
+ "no router ripng [vrf NAME]",
NO_STR
"Enable a routing process\n"
- "Make RIPng instance command\n")
+ "Make RIPng instance command\n"
+ VRF_CMD_HELP_STR)
{
- nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DESTROY,
- NULL);
+ char xpath[XPATH_MAXLEN];
+
+ /* Build RIPng instance XPath. */
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
+ snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
+ vrf);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
@@ -71,8 +86,15 @@ DEFPY (no_router_ripng,
void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
+ const char *vrf_name;
+
+ vrf_name = yang_dnode_get_string(dnode, "./vrf");
+
vty_out(vty, "!\n");
- vty_out(vty, "router ripng\n");
+ vty_out(vty, "router ripng");
+ if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
+ vty_out(vty, " vrf %s", vrf_name);
+ vty_out(vty, "\n");
}
/*
@@ -456,12 +478,24 @@ void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
*/
DEFPY (clear_ipv6_rip,
clear_ipv6_rip_cmd,
- "clear ipv6 ripng",
+ "clear ipv6 ripng [vrf WORD]",
CLEAR_STR
IPV6_STR
- "Clear IPv6 RIP database\n")
+ "Clear IPv6 RIP database\n"
+ VRF_CMD_HELP_STR)
{
- return nb_cli_rpc("/frr-ripngd:clear-ripng-route", NULL, NULL);
+ struct list *input;
+
+ input = list_new();
+ if (vrf) {
+ struct yang_data *yang_vrf;
+
+ yang_vrf = yang_data_new(
+ "/frr-ripngd:clear-ripng-route/input/vrf", vrf);
+ listnode_add(input, yang_vrf);
+ }
+
+ return nb_cli_rpc("/frr-ripngd:clear-ripng-route", input, NULL);
}
void ripng_cli_init(void)
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index ea32b622a..e35652b1a 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -52,12 +52,12 @@
/* Static utility function. */
static void ripng_enable_apply(struct interface *);
static void ripng_passive_interface_apply(struct interface *);
-static int ripng_enable_if_lookup(const char *);
+static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname);
static int ripng_enable_network_lookup2(struct connected *);
-static void ripng_enable_apply_all(void);
+static void ripng_enable_apply_all(struct ripng *ripng);
/* Join to the all rip routers multicast group. */
-static int ripng_multicast_join(struct interface *ifp)
+static int ripng_multicast_join(struct interface *ifp, int sock)
{
int ret;
struct ipv6_mreq mreq;
@@ -75,8 +75,7 @@ static int ripng_multicast_join(struct interface *ifp)
*/
frr_elevate_privs(&ripngd_privs) {
- ret = setsockopt(ripng->sock, IPPROTO_IPV6,
- IPV6_JOIN_GROUP,
+ ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char *)&mreq, sizeof(mreq));
save_errno = errno;
@@ -111,7 +110,7 @@ static int ripng_multicast_join(struct interface *ifp)
}
/* Leave from the all rip routers multicast group. */
-static int ripng_multicast_leave(struct interface *ifp)
+static int ripng_multicast_leave(struct interface *ifp, int sock)
{
int ret;
struct ipv6_mreq mreq;
@@ -121,7 +120,7 @@ static int ripng_multicast_leave(struct interface *ifp)
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = ifp->ifindex;
- ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
(char *)&mreq, sizeof(mreq));
if (ret < 0)
zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s",
@@ -163,9 +162,13 @@ static int ripng_if_down(struct interface *ifp)
struct agg_node *rp;
struct ripng_info *rinfo;
struct ripng_interface *ri;
+ struct ripng *ripng;
struct list *list = NULL;
struct listnode *listnode = NULL, *nextnode = NULL;
+ ri = ifp->info;
+ ripng = ri->ripng;
+
if (ripng)
for (rp = agg_route_top(ripng->table); rp;
rp = agg_route_next(rp))
@@ -173,16 +176,15 @@ static int ripng_if_down(struct interface *ifp)
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo))
if (rinfo->ifindex == ifp->ifindex)
- ripng_ecmp_delete(rinfo);
+ ripng_ecmp_delete(ripng, rinfo);
- ri = ifp->info;
if (ri->running) {
if (IS_RIPNG_DEBUG_EVENT)
zlog_debug("turn off %s", ifp->name);
/* Leave from multicast group. */
- ripng_multicast_leave(ifp);
+ ripng_multicast_leave(ifp, ripng->sock);
ri->running = 0;
}
@@ -207,9 +209,11 @@ int ripng_interface_up(int command, struct zclient *zclient,
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
- "interface up %s index %d flags %llx metric %d mtu %d",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu6);
+ "interface up %s vrf %u index %d flags %llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
+
+ ripng_interface_sync(ifp);
/* Check if this interface is RIPng enabled or not. */
ripng_enable_apply(ifp);
@@ -238,13 +242,14 @@ int ripng_interface_down(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
+ ripng_interface_sync(ifp);
ripng_if_down(ifp);
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
- "interface down %s index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu6);
+ "interface down %s vrf %u index %d flags %#llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
return 0;
}
@@ -256,12 +261,13 @@ int ripng_interface_add(int command, struct zclient *zclient,
struct interface *ifp;
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
+ ripng_interface_sync(ifp);
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
- "RIPng interface add %s index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu6);
+ "RIPng interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
/* Check is this interface is RIP enabled or not.*/
ripng_enable_apply(ifp);
@@ -289,13 +295,15 @@ int ripng_interface_delete(int command, struct zclient *zclient,
if (ifp == NULL)
return 0;
+ ripng_interface_sync(ifp);
if (if_is_up(ifp)) {
ripng_if_down(ifp);
}
- zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
- ifp->metric, ifp->mtu6);
+ zlog_info(
+ "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex,
+ (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
/* To support pseudo interface do not free interface structure. */
/* if_delete(ifp); */
@@ -304,13 +312,34 @@ int ripng_interface_delete(int command, struct zclient *zclient,
return 0;
}
-void ripng_interface_clean(void)
+/* VRF update for an interface. */
+int ripng_interface_vrf_update(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct interface *ifp;
+ vrf_id_t new_vrf_id;
+
+ ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
+ &new_vrf_id);
+ if (!ifp)
+ return 0;
+
+ if (IS_RIPNG_DEBUG_ZEBRA)
+ zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
+ ifp->name, vrf_id, new_vrf_id);
+
+ if_update_to_new_vrf(ifp, new_vrf_id);
+ ripng_interface_sync(ifp);
+
+ return 0;
+}
+
+void ripng_interface_clean(struct ripng *ripng)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct ripng_interface *ri;
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (ripng->vrf, ifp) {
ri = ifp->info;
ri->enable_network = 0;
@@ -326,6 +355,8 @@ void ripng_interface_clean(void)
static void ripng_apply_address_add(struct connected *ifc)
{
+ struct ripng_interface *ri = ifc->ifp->info;
+ struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
@@ -345,9 +376,9 @@ static void ripng_apply_address_add(struct connected *ifc)
/* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */
- if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0)
+ if ((ripng_enable_if_lookup(ripng, ifc->ifp->name) >= 0)
|| (ripng_enable_network_lookup2(ifc) >= 0))
- ripng_redistribute_add(ZEBRA_ROUTE_CONNECT,
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
ifc->ifp->ifindex, NULL, 0);
}
@@ -395,6 +426,8 @@ int ripng_interface_address_add(int command, struct zclient *zclient,
static void ripng_apply_address_del(struct connected *ifc)
{
+ struct ripng_interface *ri = ifc->ifp->info;
+ struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
@@ -412,8 +445,9 @@ static void ripng_apply_address_del(struct connected *ifc)
address.prefixlen = p->prefixlen;
apply_mask_ipv6(&address);
- ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
- &address, ifc->ifp->ifindex);
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
+ RIPNG_ROUTE_INTERFACE, &address,
+ ifc->ifp->ifindex);
}
int ripng_interface_address_delete(int command, struct zclient *zclient,
@@ -446,21 +480,20 @@ int ripng_interface_address_delete(int command, struct zclient *zclient,
return 0;
}
-/* RIPng enable interface vector. */
-vector ripng_enable_if;
-
-/* RIPng enable network table. */
-struct agg_table *ripng_enable_network;
-
/* Lookup RIPng enable network. */
/* Check wether the interface has at least a connected prefix that
- * is within the ripng_enable_network table. */
+ * is within the ripng->enable_network table. */
static int ripng_enable_network_lookup_if(struct interface *ifp)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct listnode *node;
struct connected *connected;
struct prefix_ipv6 address;
+ if (!ripng)
+ return -1;
+
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
struct prefix *p;
struct agg_node *n;
@@ -472,7 +505,7 @@ static int ripng_enable_network_lookup_if(struct interface *ifp)
address.prefix = p->u.prefix6;
address.prefixlen = IPV6_MAX_BITLEN;
- n = agg_node_match(ripng_enable_network,
+ n = agg_node_match(ripng->enable_network,
(struct prefix *)&address);
if (n) {
agg_unlock_node(n);
@@ -483,12 +516,17 @@ static int ripng_enable_network_lookup_if(struct interface *ifp)
return -1;
}
-/* Check wether connected is within the ripng_enable_network table. */
+/* Check wether connected is within the ripng->enable_network table. */
static int ripng_enable_network_lookup2(struct connected *connected)
{
+ struct ripng_interface *ri = connected->ifp->info;
+ struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
+ if (!ripng)
+ return -1;
+
p = connected->address;
if (p->family == AF_INET6) {
@@ -499,8 +537,8 @@ static int ripng_enable_network_lookup2(struct connected *connected)
address.prefixlen = IPV6_MAX_BITLEN;
/* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within
- * ripng_enable_network */
- node = agg_node_match(ripng_enable_network,
+ * ripng->enable_network */
+ node = agg_node_match(ripng->enable_network,
(struct prefix *)&address);
if (node) {
@@ -513,11 +551,11 @@ static int ripng_enable_network_lookup2(struct connected *connected)
}
/* Add RIPng enable network. */
-int ripng_enable_network_add(struct prefix *p)
+int ripng_enable_network_add(struct ripng *ripng, struct prefix *p)
{
struct agg_node *node;
- node = agg_node_get(ripng_enable_network, p);
+ node = agg_node_get(ripng->enable_network, p);
if (node->info) {
agg_unlock_node(node);
@@ -526,17 +564,17 @@ int ripng_enable_network_add(struct prefix *p)
node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */
- ripng_enable_apply_all();
+ ripng_enable_apply_all(ripng);
return NB_OK;
}
/* Delete RIPng enable network. */
-int ripng_enable_network_delete(struct prefix *p)
+int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p)
{
struct agg_node *node;
- node = agg_node_lookup(ripng_enable_network, p);
+ node = agg_node_lookup(ripng->enable_network, p);
if (node) {
node->info = NULL;
@@ -553,49 +591,50 @@ int ripng_enable_network_delete(struct prefix *p)
}
/* Lookup function. */
-static int ripng_enable_if_lookup(const char *ifname)
+static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname)
{
unsigned int i;
char *str;
- for (i = 0; i < vector_active(ripng_enable_if); i++)
- if ((str = vector_slot(ripng_enable_if, i)) != NULL)
+ if (!ripng)
+ return -1;
+
+ for (i = 0; i < vector_active(ripng->enable_if); i++)
+ if ((str = vector_slot(ripng->enable_if, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
}
-/* Add interface to ripng_enable_if. */
-int ripng_enable_if_add(const char *ifname)
+int ripng_enable_if_add(struct ripng *ripng, const char *ifname)
{
int ret;
- ret = ripng_enable_if_lookup(ifname);
+ ret = ripng_enable_if_lookup(ripng, ifname);
if (ret >= 0)
return NB_ERR_INCONSISTENCY;
- vector_set(ripng_enable_if, strdup(ifname));
+ vector_set(ripng->enable_if, strdup(ifname));
- ripng_enable_apply_all();
+ ripng_enable_apply_all(ripng);
return NB_OK;
}
-/* Delete interface from ripng_enable_if. */
-int ripng_enable_if_delete(const char *ifname)
+int ripng_enable_if_delete(struct ripng *ripng, const char *ifname)
{
int index;
char *str;
- index = ripng_enable_if_lookup(ifname);
+ index = ripng_enable_if_lookup(ripng, ifname);
if (index < 0)
return NB_ERR_INCONSISTENCY;
- str = vector_slot(ripng_enable_if, index);
+ str = vector_slot(ripng->enable_if, index);
free(str);
- vector_unset(ripng_enable_if, index);
+ vector_unset(ripng->enable_if, index);
- ripng_enable_apply_all();
+ ripng_enable_apply_all(ripng);
return NB_OK;
}
@@ -613,7 +652,7 @@ static int ripng_interface_wakeup(struct thread *t)
ri->t_wakeup = NULL;
/* Join to multicast group. */
- if (ripng_multicast_join(ifp) < 0) {
+ if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"multicast join failed, interface %s not running",
ifp->name);
@@ -631,6 +670,8 @@ static int ripng_interface_wakeup(struct thread *t)
static void ripng_connect_set(struct interface *ifp, int set)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv6 address;
@@ -650,19 +691,22 @@ static void ripng_connect_set(struct interface *ifp, int set)
if (set) {
/* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */
- if ((ripng_enable_if_lookup(connected->ifp->name) >= 0)
+ if ((ripng_enable_if_lookup(ripng, connected->ifp->name)
+ >= 0)
|| (ripng_enable_network_lookup2(connected) >= 0))
ripng_redistribute_add(
- ZEBRA_ROUTE_CONNECT,
+ ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
connected->ifp->ifindex, NULL, 0);
} else {
- ripng_redistribute_delete(
- ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
- &address, connected->ifp->ifindex);
- if (ripng_redistribute_check(ZEBRA_ROUTE_CONNECT))
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
+ RIPNG_ROUTE_INTERFACE,
+ &address,
+ connected->ifp->ifindex);
+ if (ripng_redistribute_check(ripng,
+ ZEBRA_ROUTE_CONNECT))
ripng_redistribute_add(
- ZEBRA_ROUTE_CONNECT,
+ ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_REDISTRIBUTE, &address,
connected->ifp->ifindex, NULL, 0);
}
@@ -691,7 +735,7 @@ void ripng_enable_apply(struct interface *ifp)
ri->enable_network = 0;
/* Check interface name configuration. */
- ret = ripng_enable_if_lookup(ifp->name);
+ ret = ripng_enable_if_lookup(ri->ripng, ifp->name);
if (ret >= 0)
ri->enable_interface = 1;
else
@@ -729,49 +773,46 @@ void ripng_enable_apply(struct interface *ifp)
}
/* Set distribute list to all interfaces. */
-static void ripng_enable_apply_all(void)
+static void ripng_enable_apply_all(struct ripng *ripng)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- FOR_ALL_INTERFACES (vrf, ifp)
+ FOR_ALL_INTERFACES (ripng->vrf, ifp)
ripng_enable_apply(ifp);
}
/* Clear all network and neighbor configuration */
-void ripng_clean_network(void)
+void ripng_clean_network(struct ripng *ripng)
{
unsigned int i;
char *str;
struct agg_node *rn;
- /* ripng_enable_network */
- for (rn = agg_route_top(ripng_enable_network); rn;
+ /* ripng->enable_network */
+ for (rn = agg_route_top(ripng->enable_network); rn;
rn = agg_route_next(rn))
if (rn->info) {
rn->info = NULL;
agg_unlock_node(rn);
}
- /* ripng_enable_if */
- for (i = 0; i < vector_active(ripng_enable_if); i++)
- if ((str = vector_slot(ripng_enable_if, i)) != NULL) {
+ /* ripng->enable_if */
+ for (i = 0; i < vector_active(ripng->enable_if); i++)
+ if ((str = vector_slot(ripng->enable_if, i)) != NULL) {
free(str);
- vector_slot(ripng_enable_if, i) = NULL;
+ vector_slot(ripng->enable_if, i) = NULL;
}
}
-/* Vector to store passive-interface name. */
-vector Vripng_passive_interface;
-
/* Utility function for looking up passive interface settings. */
-static int ripng_passive_interface_lookup(const char *ifname)
+static int ripng_passive_interface_lookup(struct ripng *ripng,
+ const char *ifname)
{
unsigned int i;
char *str;
- for (i = 0; i < vector_active(Vripng_passive_interface); i++)
- if ((str = vector_slot(Vripng_passive_interface, i)) != NULL)
+ for (i = 0; i < vector_active(ripng->passive_interface); i++)
+ if ((str = vector_slot(ripng->passive_interface, i)) != NULL)
if (strcmp(str, ifname) == 0)
return i;
return -1;
@@ -781,72 +822,75 @@ void ripng_passive_interface_apply(struct interface *ifp)
{
int ret;
struct ripng_interface *ri;
+ struct ripng *ripng;
ri = ifp->info;
+ ripng = ri->ripng;
+ if (!ripng)
+ return;
- ret = ripng_passive_interface_lookup(ifp->name);
+ ret = ripng_passive_interface_lookup(ripng, ifp->name);
if (ret < 0)
ri->passive = 0;
else
ri->passive = 1;
}
-static void ripng_passive_interface_apply_all(void)
+static void ripng_passive_interface_apply_all(struct ripng *ripng)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- FOR_ALL_INTERFACES (vrf, ifp)
+ FOR_ALL_INTERFACES (ripng->vrf, ifp)
ripng_passive_interface_apply(ifp);
}
/* Passive interface. */
-int ripng_passive_interface_set(const char *ifname)
+int ripng_passive_interface_set(struct ripng *ripng, const char *ifname)
{
- if (ripng_passive_interface_lookup(ifname) >= 0)
+ if (ripng_passive_interface_lookup(ripng, ifname) >= 0)
return NB_ERR_INCONSISTENCY;
- vector_set(Vripng_passive_interface, strdup(ifname));
+ vector_set(ripng->passive_interface, strdup(ifname));
- ripng_passive_interface_apply_all();
+ ripng_passive_interface_apply_all(ripng);
return NB_OK;
}
-int ripng_passive_interface_unset(const char *ifname)
+int ripng_passive_interface_unset(struct ripng *ripng, const char *ifname)
{
int i;
char *str;
- i = ripng_passive_interface_lookup(ifname);
+ i = ripng_passive_interface_lookup(ripng, ifname);
if (i < 0)
return NB_ERR_INCONSISTENCY;
- str = vector_slot(Vripng_passive_interface, i);
+ str = vector_slot(ripng->passive_interface, i);
free(str);
- vector_unset(Vripng_passive_interface, i);
+ vector_unset(ripng->passive_interface, i);
- ripng_passive_interface_apply_all();
+ ripng_passive_interface_apply_all(ripng);
return NB_OK;
}
/* Free all configured RIP passive-interface settings. */
-void ripng_passive_interface_clean(void)
+void ripng_passive_interface_clean(struct ripng *ripng)
{
unsigned int i;
char *str;
- for (i = 0; i < vector_active(Vripng_passive_interface); i++)
- if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) {
+ for (i = 0; i < vector_active(ripng->passive_interface); i++)
+ if ((str = vector_slot(ripng->passive_interface, i)) != NULL) {
free(str);
- vector_slot(Vripng_passive_interface, i) = NULL;
+ vector_slot(ripng->passive_interface, i) = NULL;
}
- ripng_passive_interface_apply_all();
+ ripng_passive_interface_apply_all(ripng);
}
/* Write RIPng enable network and interface to the vty. */
-int ripng_network_write(struct vty *vty)
+int ripng_network_write(struct vty *vty, struct ripng *ripng)
{
unsigned int i;
const char *ifname;
@@ -854,7 +898,7 @@ int ripng_network_write(struct vty *vty)
char buf[BUFSIZ];
/* Write enable network. */
- for (node = agg_route_top(ripng_enable_network); node;
+ for (node = agg_route_top(ripng->enable_network); node;
node = agg_route_next(node))
if (node->info) {
struct prefix *p = &node->p;
@@ -864,8 +908,8 @@ int ripng_network_write(struct vty *vty)
}
/* Write enable interface. */
- for (i = 0; i < vector_active(ripng_enable_if); i++)
- if ((ifname = vector_slot(ripng_enable_if, i)) != NULL)
+ for (i = 0; i < vector_active(ripng->enable_if); i++)
+ if ((ifname = vector_slot(ripng->enable_if, i)) != NULL)
vty_out(vty, " %s\n", ifname);
return 0;
@@ -874,6 +918,7 @@ int ripng_network_write(struct vty *vty)
static struct ripng_interface *ri_new(void)
{
struct ripng_interface *ri;
+
ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface));
/* Set default split-horizon behavior. If the interface is Frame
@@ -886,9 +931,25 @@ static struct ripng_interface *ri_new(void)
return ri;
}
+void ripng_interface_sync(struct interface *ifp)
+{
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(ifp->vrf_id);
+ if (vrf) {
+ struct ripng_interface *ri;
+
+ ri = ifp->info;
+ if (ri)
+ ri->ripng = vrf->info;
+ }
+}
+
static int ripng_if_new_hook(struct interface *ifp)
{
ifp->info = ri_new();
+ ripng_interface_sync(ifp);
+
return 0;
}
@@ -903,22 +964,25 @@ static int ripng_if_delete_hook(struct interface *ifp)
/* Configuration write function for ripngd. */
static int interface_config_write(struct vty *vty)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp;
+ struct vrf *vrf;
int write = 0;
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ struct interface *ifp;
- dnode = yang_dnode_get(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct lyd_node *dnode;
- write = 1;
- nb_cli_show_dnode_cmds(vty, dnode, false);
+ dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+ ifp->name, vrf->name);
+ if (dnode == NULL)
+ continue;
+
+ write = 1;
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+ }
}
return write;
@@ -936,15 +1000,6 @@ void ripng_if_init(void)
hook_register_prio(if_add, 0, ripng_if_new_hook);
hook_register_prio(if_del, 0, ripng_if_delete_hook);
- /* RIPng enable network init. */
- ripng_enable_network = agg_table_init();
-
- /* RIPng enable interface init. */
- ripng_enable_if = vector_init(1);
-
- /* RIPng passive interface. */
- Vripng_passive_interface = vector_init(1);
-
/* Install interface node. */
install_node(&interface_node, interface_config_write);
if_cmd_init();
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index 10e19efe7..c755bd83c 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -35,6 +35,7 @@
#include "privs.h"
#include "sigevent.h"
#include "vrf.h"
+#include "if_rmap.h"
#include "libfrr.h"
#include "ripngd/ripngd.h"
@@ -46,7 +47,7 @@
struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}};
/* ripngd privileges */
-zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
+zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
struct zebra_privs_t ripngd_privs = {
#if defined(FRR_USER)
@@ -59,7 +60,7 @@ struct zebra_privs_t ripngd_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
- .cap_num_p = 2,
+ .cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
@@ -82,8 +83,8 @@ static void sigint(void)
{
zlog_notice("Terminating on signal");
- ripng_clean();
-
+ ripng_vrf_terminate();
+ if_rmap_terminate();
ripng_zebra_stop();
frr_fini();
exit(0);
@@ -170,13 +171,12 @@ int main(int argc, char **argv)
master = frr_init();
/* Library inits. */
- vrf_init(NULL, NULL, NULL, NULL, NULL);
+ ripng_vrf_init();
/* RIPngd inits. */
ripng_init();
ripng_cli_init();
zebra_init(master);
- ripng_peer_init();
frr_config_fork();
frr_run(master);
diff --git a/ripngd/ripng_memory.c b/ripngd/ripng_memory.c
index 0cb24052e..f459566be 100644
--- a/ripngd/ripng_memory.c
+++ b/ripngd/ripng_memory.c
@@ -27,6 +27,7 @@
DEFINE_MGROUP(RIPNGD, "ripngd")
DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure")
+DEFINE_MTYPE(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name")
DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info")
DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer")
diff --git a/ripngd/ripng_memory.h b/ripngd/ripng_memory.h
index a4102086c..3dfc57b3f 100644
--- a/ripngd/ripng_memory.h
+++ b/ripngd/ripng_memory.h
@@ -26,6 +26,7 @@
DECLARE_MGROUP(RIPNGD)
DECLARE_MTYPE(RIPNG)
+DECLARE_MTYPE(RIPNG_VRF_NAME)
DECLARE_MTYPE(RIPNG_ROUTE)
DECLARE_MTYPE(RIPNG_AGGREGATE)
DECLARE_MTYPE(RIPNG_PEER)
diff --git a/ripngd/ripng_nexthop.c b/ripngd/ripng_nexthop.c
index 74a132aa9..882c2fbc8 100644
--- a/ripngd/ripng_nexthop.c
+++ b/ripngd/ripng_nexthop.c
@@ -114,7 +114,8 @@ void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
struct sockaddr_in6 *to)
{
-
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct ripng_rte_data *data;
struct listnode *node, *nnode;
diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c
index b6998b4dd..c483ad65f 100644
--- a/ripngd/ripng_northbound.c
+++ b/ripngd/ripng_northbound.c
@@ -32,6 +32,7 @@
#include "libfrr.h"
#include "ripngd/ripngd.h"
+#include "ripngd/ripng_debug.h"
#include "ripngd/ripng_route.h"
#include "ripngd/ripng_cli.h"
@@ -42,41 +43,98 @@ static int ripngd_instance_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+ struct vrf *vrf;
+ const char *vrf_name;
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) {
case NB_EV_VALIDATE:
break;
case NB_EV_PREPARE:
- socket = ripng_make_socket();
+ if (!vrf || !vrf_is_enabled(vrf))
+ break;
+
+ socket = ripng_make_socket(vrf);
if (socket < 0)
return NB_ERR_RESOURCE;
resource->fd = socket;
break;
case NB_EV_ABORT:
+ if (!vrf || !vrf_is_enabled(vrf))
+ break;
+
socket = resource->fd;
close(socket);
break;
case NB_EV_APPLY:
- socket = resource->fd;
- ripng_create(socket);
+ if (vrf && vrf_is_enabled(vrf))
+ socket = resource->fd;
+ else
+ socket = -1;
+
+ ripng = ripng_create(vrf_name, vrf, socket);
+ yang_dnode_set_entry(dnode, ripng);
break;
}
return NB_OK;
}
-static int ripngd_instance_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripngd_instance_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
- ripng_clean();
+ ripng = yang_dnode_get_entry(dnode, true);
+ ripng_clean(ripng);
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
*/
@@ -84,12 +142,15 @@ static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
if (!ripng->ecmp)
- ripng_ecmp_disable();
+ ripng_ecmp_disable(ripng);
return NB_OK;
}
@@ -101,19 +162,22 @@ static int ripngd_instance_default_information_originate_modify(
enum nb_event event, const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
bool default_information;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
default_information = yang_dnode_get_bool(dnode, NULL);
+
str2prefix_ipv6("::/0", &p);
if (default_information) {
- ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
- &p, 0, NULL, 0);
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
+ RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
} else {
- ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG,
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
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,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
return NB_OK;
@@ -142,29 +209,33 @@ static int ripngd_instance_network_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
struct prefix p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
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,
- const struct lyd_node *dnode)
+static int ripngd_instance_network_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct ripng *ripng;
struct prefix p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
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,
union nb_resource *resource)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
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,
- const struct lyd_node *dnode)
+static int ripngd_instance_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return ripng_enable_if_delete(ifname);
+ return ripng_enable_if_delete(ripng, ifname);
}
/*
@@ -204,22 +279,24 @@ static int ripngd_instance_offset_list_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
const char *ifname;
struct ripng_offset_list *offset;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
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);
return NB_OK;
}
-static int ripngd_instance_offset_list_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripngd_instance_offset_list_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
int direct;
struct ripng_offset_list *offset;
@@ -299,28 +376,32 @@ ripngd_instance_passive_interface_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return ripng_passive_interface_set(ifname);
+ return ripng_passive_interface_set(ripng, ifname);
}
static int
-ripngd_instance_passive_interface_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripngd_instance_passive_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
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,
union nb_resource *resource)
{
+ 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 = true;
+
return NB_OK;
}
-static int ripngd_instance_redistribute_delete(enum nb_event event,
- const struct lyd_node *dnode)
+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_redistribute_conf_delete(type);
+ 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;
}
@@ -351,10 +455,14 @@ static int ripngd_instance_redistribute_delete(enum nb_event event,
static void
ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
{
+ struct ripng *ripng;
int type;
+ ripng = yang_dnode_get_entry(dnode, true);
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,
union nb_resource *resource)
{
+ struct ripng *ripng;
int type;
const char *rmap_name;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
rmap_name = yang_dnode_get_string(dnode, NULL);
- if (ripng->route_map[type].name)
- free(ripng->route_map[type].name);
- ripng->route_map[type].name = strdup(rmap_name);
- ripng->route_map[type].map = route_map_lookup_by_name(rmap_name);
+ if (ripng->redist[type].route_map.name)
+ free(ripng->redist[type].route_map.name);
+ ripng->redist[type].route_map.name = strdup(rmap_name);
+ ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
return NB_OK;
}
static int
-ripngd_instance_redistribute_route_map_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripngd_instance_redistribute_route_map_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");
- free(ripng->route_map[type].name);
- ripng->route_map[type].name = NULL;
- ripng->route_map[type].map = NULL;
+ free(ripng->redist[type].route_map.name);
+ ripng->redist[type].route_map.name = NULL;
+ ripng->redist[type].route_map.map = NULL;
return NB_OK;
}
@@ -408,34 +520,38 @@ ripngd_instance_redistribute_metric_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
int type;
uint8_t metric;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
metric = yang_dnode_get_uint8(dnode, NULL);
- ripng->route_map[type].metric_config = true;
- ripng->route_map[type].metric = metric;
+ ripng->redist[type].metric_config = true;
+ ripng->redist[type].metric = metric;
return NB_OK;
}
static int
-ripngd_instance_redistribute_metric_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripngd_instance_redistribute_metric_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->route_map[type].metric_config = false;
- ripng->route_map[type].metric = 0;
+ ripng->redist[type].metric_config = false;
+ ripng->redist[type].metric = 0;
return NB_OK;
}
@@ -447,32 +563,37 @@ static int ripngd_instance_static_route_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0,
- NULL, 0);
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
+ 0, NULL, 0);
return NB_OK;
}
-static int ripngd_instance_static_route_delete(enum nb_event event,
- const struct lyd_node *dnode)
+static int ripngd_instance_static_route_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
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;
}
@@ -485,32 +606,36 @@ ripngd_instance_aggregate_address_create(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_aggregate_add((struct prefix *)&p);
+ ripng_aggregate_add(ripng, (struct prefix *)&p);
return NB_OK;
}
static int
-ripngd_instance_aggregate_address_delete(enum nb_event event,
- const struct lyd_node *dnode)
+ripngd_instance_aggregate_address_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_aggregate_delete((struct prefix *)&p);
+ ripng_aggregate_delete(ripng, (struct prefix *)&p);
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)
{
+ struct ripng *ripng;
+
+ ripng = yang_dnode_get_entry(dnode, true);
+
/* 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,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK;
@@ -548,9 +680,12 @@ ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK;
@@ -564,33 +699,38 @@ ripngd_instance_timers_update_interval_modify(enum nb_event event,
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK;
}
/*
- * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor
+ * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
*/
static const void *
-ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
- const void *list_entry)
+ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
+ const void *list_entry)
{
+ const struct ripng *ripng = parent_list_entry;
struct listnode *node;
if (list_entry == NULL)
- node = listhead(peer_list);
+ node = listhead(ripng->peer_list);
else
node = listnextnode((struct listnode *)list_entry);
return node;
}
-static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
+static int
+ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
{
const struct listnode *node = list_entry;
const struct ripng_peer *peer = listgetdata(node);
@@ -602,17 +742,17 @@ static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry,
return NB_OK;
}
-static const void *
-ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
- const struct yang_list_keys *keys)
+static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys)
{
+ const struct ripng *ripng = parent_list_entry;
struct in6_addr address;
struct ripng_peer *peer;
struct listnode *node;
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))
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 *
-ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_neighbors_neighbor_address_get_elem(
+ const char *xpath, const void *list_entry)
{
const struct listnode *node = list_entry;
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 *
-ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
+ const char *xpath, const void *list_entry)
{
/* TODO: yang:date-and-time is tricky */
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 *
-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 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 *
-ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
+ const char *xpath, const void *list_entry)
{
const struct listnode *node = list_entry;
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 *
-ripngd_state_routes_route_get_next(const void *parent_list_entry,
- const void *list_entry)
+ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
+ const void *list_entry)
{
+ const struct ripng *ripng = parent_list_entry;
struct agg_node *rn;
- if (ripng == NULL)
- return NULL;
-
if (list_entry == NULL)
rn = agg_route_top(ripng->table);
else
@@ -692,8 +830,9 @@ ripngd_state_routes_route_get_next(const void *parent_list_entry,
return rn;
}
-static int ripngd_state_routes_route_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
+static int
+ripngd_instance_state_routes_route_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
{
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;
}
-static const void *
-ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
- const struct yang_list_keys *keys)
+static const void *ripngd_instance_state_routes_route_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys)
{
+ const struct ripng *ripng = parent_list_entry;
struct prefix prefix;
struct agg_node *rn;
@@ -722,11 +861,11 @@ 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 *
-ripngd_state_routes_route_prefix_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct agg_node *rn = list_entry;
const struct ripng_info *rinfo = listnode_head(rn->info);
@@ -735,11 +874,11 @@ 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 *
-ripngd_state_routes_route_next_hop_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct agg_node *rn = list_entry;
const struct ripng_info *rinfo = listnode_head(rn->info);
@@ -748,25 +887,26 @@ 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 *
-ripngd_state_routes_route_interface_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct agg_node *rn = list_entry;
const struct ripng_info *rinfo = listnode_head(rn->info);
+ const struct ripng *ripng = ripng_info_get_instance(rinfo);
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 *
-ripngd_state_routes_route_metric_get_elem(const char *xpath,
- const void *list_entry)
+ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
+ const void *list_entry)
{
const struct agg_node *rn = list_entry;
const struct ripng_info *rinfo = listnode_head(rn->info);
@@ -777,16 +917,20 @@ ripngd_state_routes_route_metric_get_elem(const char *xpath,
/*
* XPath: /frr-ripngd:clear-ripng-route
*/
-static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
- struct list *output)
+static void clear_ripng_route(struct ripng *ripng)
{
struct agg_node *rp;
- struct ripng_info *rinfo;
- struct list *list;
- struct listnode *listnode;
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("Clearing all RIPng routes (VRF %s)",
+ ripng->vrf_name);
/* Clear received RIPng routes */
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;
if (list == NULL)
continue;
@@ -796,7 +940,7 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
continue;
if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
break;
}
@@ -813,6 +957,30 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
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;
}
@@ -845,7 +1013,10 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance",
.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,
},
{
@@ -866,19 +1037,19 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/network",
.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,
},
{
.xpath = "/frr-ripngd:ripngd/instance/interface",
.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,
},
{
.xpath = "/frr-ripngd:ripngd/instance/offset-list",
.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,
},
{
@@ -892,36 +1063,36 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/passive-interface",
.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,
},
{
.xpath = "/frr-ripngd:ripngd/instance/redistribute",
.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.cli_show = cli_show_ripng_redistribute,
},
{
.xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
.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",
.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",
.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,
},
{
.xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
.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,
},
{
@@ -942,48 +1113,48 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs.modify = ripngd_instance_timers_update_interval_modify,
},
{
- .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor",
- .cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
- .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
- .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor",
+ .cbs.get_next = ripngd_instance_state_neighbors_neighbor_get_next,
+ .cbs.get_keys = ripngd_instance_state_neighbors_neighbor_get_keys,
+ .cbs.lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry,
},
{
- .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
- .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
+ .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
- .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
+ .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
- .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd",
+ .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
- .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd",
+ .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/routes/route",
- .cbs.get_next = ripngd_state_routes_route_get_next,
- .cbs.get_keys = ripngd_state_routes_route_get_keys,
- .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route",
+ .cbs.get_next = ripngd_instance_state_routes_route_get_next,
+ .cbs.get_keys = ripngd_instance_state_routes_route_get_keys,
+ .cbs.lookup_entry = ripngd_instance_state_routes_route_lookup_entry,
},
{
- .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
- .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
+ .cbs.get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
- .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
+ .cbs.get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
- .cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
+ .cbs.get_elem = ripngd_instance_state_routes_route_interface_get_elem,
},
{
- .xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
- .cbs.get_elem = ripngd_state_routes_route_metric_get_elem,
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
+ .cbs.get_elem = ripngd_instance_state_routes_route_metric_get_elem,
},
{
.xpath = "/frr-ripngd:clear-ripng-route",
diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c
index 278df7589..41ba2360b 100644
--- a/ripngd/ripng_offset.c
+++ b/ripngd/ripng_offset.c
@@ -33,29 +33,29 @@
#include "ripngd/ripngd.h"
-static struct list *ripng_offset_list_master;
-
#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
-struct ripng_offset_list *ripng_offset_list_new(const char *ifname)
+struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
+ const char *ifname)
{
struct ripng_offset_list *new;
new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
sizeof(struct ripng_offset_list));
+ new->ripng = ripng;
new->ifname = strdup(ifname);
- listnode_add_sort(ripng_offset_list_master, new);
+ listnode_add_sort(ripng->offset_list_master, new);
return new;
}
void ripng_offset_list_del(struct ripng_offset_list *offset)
{
- listnode_delete(ripng_offset_list_master, offset);
+ listnode_delete(offset->ripng->offset_list_master, offset);
if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_NAME(offset))
@@ -64,12 +64,14 @@ void ripng_offset_list_del(struct ripng_offset_list *offset)
XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
}
-struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
+struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
+ const char *ifname)
{
struct ripng_offset_list *offset;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
+ for (ALL_LIST_ELEMENTS(ripng->offset_list_master, node, nnode,
+ offset)) {
if (strcmp(offset->ifname, ifname) == 0)
return offset;
}
@@ -77,14 +79,14 @@ struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
}
/* If metric is modifed return 1. */
-int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
- uint8_t *metric)
+int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric)
{
struct ripng_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
- offset = ripng_offset_list_lookup(ifp->name);
+ offset = ripng_offset_list_lookup(ripng, ifp->name);
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
@@ -98,7 +100,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
return 0;
}
/* Look up offset-list without interface name. */
- offset = ripng_offset_list_lookup("*");
+ offset = ripng_offset_list_lookup(ripng, "*");
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
@@ -115,14 +117,14 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
}
/* If metric is modifed return 1. */
-int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
- uint8_t *metric)
+int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric)
{
struct ripng_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
- offset = ripng_offset_list_lookup(ifp->name);
+ offset = ripng_offset_list_lookup(ripng, ifp->name);
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
@@ -137,7 +139,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
}
/* Look up offset-list without interface name. */
- offset = ripng_offset_list_lookup("*");
+ offset = ripng_offset_list_lookup(ripng, "*");
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
@@ -153,26 +155,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
return 0;
}
-static int offset_list_cmp(struct ripng_offset_list *o1,
- struct ripng_offset_list *o2)
+int offset_list_cmp(struct ripng_offset_list *o1, struct ripng_offset_list *o2)
{
return strcmp(o1->ifname, o2->ifname);
}
-
-void ripng_offset_init(void)
-{
- ripng_offset_list_master = list_new();
- ripng_offset_list_master->cmp =
- (int (*)(void *, void *))offset_list_cmp;
- ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
-}
-
-void ripng_offset_clean(void)
-{
- list_delete(&ripng_offset_list_master);
-
- ripng_offset_list_master = list_new();
- ripng_offset_list_master->cmp =
- (int (*)(void *, void *))offset_list_cmp;
- ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
-}
diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c
index 756162d65..537600774 100644
--- a/ripngd/ripng_peer.c
+++ b/ripngd/ripng_peer.c
@@ -34,10 +34,6 @@
#include "ripngd/ripngd.h"
#include "ripngd/ripng_nexthop.h"
-
-/* Linked list of RIPng peer. */
-struct list *peer_list;
-
static struct ripng_peer *ripng_peer_new(void)
{
return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer));
@@ -45,27 +41,29 @@ static struct ripng_peer *ripng_peer_new(void)
static void ripng_peer_free(struct ripng_peer *peer)
{
+ RIPNG_TIMER_OFF(peer->t_timeout);
XFREE(MTYPE_RIPNG_PEER, peer);
}
-struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr)
+struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
+ for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
if (IPV6_ADDR_SAME(&peer->addr, addr))
return peer;
}
return NULL;
}
-struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *addr)
+struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
+ struct in6_addr *addr)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
+ for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
if (addr6_cmp(&peer->addr, addr) > 0)
return peer;
}
@@ -80,26 +78,28 @@ static int ripng_peer_timeout(struct thread *t)
struct ripng_peer *peer;
peer = THREAD_ARG(t);
- listnode_delete(peer_list, peer);
+ listnode_delete(peer->ripng->peer_list, peer);
ripng_peer_free(peer);
return 0;
}
/* Get RIPng peer. At the same time update timeout thread. */
-static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
+static struct ripng_peer *ripng_peer_get(struct ripng *ripng,
+ struct in6_addr *addr)
{
struct ripng_peer *peer;
- peer = ripng_peer_lookup(addr);
+ peer = ripng_peer_lookup(ripng, addr);
if (peer) {
if (peer->t_timeout)
thread_cancel(peer->t_timeout);
} else {
peer = ripng_peer_new();
- peer->addr = *addr; /* XXX */
- listnode_add_sort(peer_list, peer);
+ peer->ripng = ripng;
+ peer->addr = *addr;
+ listnode_add_sort(ripng->peer_list, peer);
}
/* Update timeout thread. */
@@ -113,24 +113,25 @@ static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
return peer;
}
-void ripng_peer_update(struct sockaddr_in6 *from, uint8_t version)
+void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
+ uint8_t version)
{
struct ripng_peer *peer;
- peer = ripng_peer_get(&from->sin6_addr);
+ peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->version = version;
}
-void ripng_peer_bad_route(struct sockaddr_in6 *from)
+void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from)
{
struct ripng_peer *peer;
- peer = ripng_peer_get(&from->sin6_addr);
+ peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badroutes++;
}
-void ripng_peer_bad_packet(struct sockaddr_in6 *from)
+void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from)
{
struct ripng_peer *peer;
- peer = ripng_peer_get(&from->sin6_addr);
+ peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badpackets++;
}
@@ -163,14 +164,14 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
return buf;
}
-void ripng_peer_display(struct vty *vty)
+void ripng_peer_display(struct vty *vty, struct ripng *ripng)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
#define RIPNG_UPTIME_LEN 25
char timebuf[RIPNG_UPTIME_LEN];
- for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) {
+ for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
vty_out(vty, " %s \n%14s %10d %10d %10d %s\n",
inet6_ntoa(peer->addr), " ", peer->recv_badpackets,
peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT,
@@ -178,13 +179,12 @@ void ripng_peer_display(struct vty *vty)
}
}
-static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
+int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
{
return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr));
}
-void ripng_peer_init(void)
+void ripng_peer_list_del(void *arg)
{
- peer_list = list_new();
- peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
+ ripng_peer_free(arg);
}
diff --git a/ripngd/ripng_route.c b/ripngd/ripng_route.c
index f66a0b952..1bf1007fe 100644
--- a/ripngd/ripng_route.c
+++ b/ripngd/ripng_route.c
@@ -86,7 +86,7 @@ void ripng_aggregate_decrement_list(struct agg_node *child, struct list *list)
}
/* RIPng routes treatment. */
-int ripng_aggregate_add(struct prefix *p)
+int ripng_aggregate_add(struct ripng *ripng, struct prefix *p)
{
struct agg_node *top;
struct agg_node *rp;
@@ -124,7 +124,7 @@ int ripng_aggregate_add(struct prefix *p)
}
/* Delete RIPng static route. */
-int ripng_aggregate_delete(struct prefix *p)
+int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p)
{
struct agg_node *top;
struct agg_node *rp;
diff --git a/ripngd/ripng_route.h b/ripngd/ripng_route.h
index e402f4a66..afc1d1cbc 100644
--- a/ripngd/ripng_route.h
+++ b/ripngd/ripng_route.h
@@ -48,8 +48,8 @@ extern void ripng_aggregate_decrement(struct agg_node *rp,
struct ripng_info *rinfo);
extern void ripng_aggregate_decrement_list(struct agg_node *rp,
struct list *list);
-extern int ripng_aggregate_add(struct prefix *p);
-extern int ripng_aggregate_delete(struct prefix *p);
+extern int ripng_aggregate_add(struct ripng *ripng, struct prefix *p);
+extern int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p);
extern void ripng_aggregate_free(struct ripng_aggregate *aggregate);
#endif /* _ZEBRA_RIPNG_ROUTE_H */
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index c68c066f0..cf60de2de 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -37,7 +37,8 @@
struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */
-static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
+static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
+ uint8_t cmd)
{
struct list *list = (struct list *)rp->info;
struct zapi_route api;
@@ -47,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
int count = 0;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = ripng->vrf->vrf_id;
api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST;
api.prefix = rp->p;
@@ -57,7 +58,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
- api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->vrf_id = ripng->vrf->vrf_id;
api_nh->gate.ipv6 = rinfo->nexthop;
api_nh->ifindex = rinfo->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
@@ -100,25 +101,30 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
}
/* Add/update ECMP routes to zebra. */
-void ripng_zebra_ipv6_add(struct agg_node *rp)
+void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp)
{
- ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
+ ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD);
}
/* Delete ECMP routes from zebra. */
-void ripng_zebra_ipv6_delete(struct agg_node *rp)
+void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp)
{
- ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
+ ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE);
}
/* Zebra route add and delete treatment. */
static int ripng_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
+ struct ripng *ripng;
struct zapi_route api;
struct in6_addr nexthop;
unsigned long ifindex;
+ ripng = ripng_lookup_by_vrf_id(vrf_id);
+ if (!ripng)
+ return 0;
+
if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
@@ -133,69 +139,97 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
ifindex = api.nexthops[0].ifindex;
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
- ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
+ ripng_redistribute_add(ripng, api.type,
+ RIPNG_ROUTE_REDISTRIBUTE,
(struct prefix_ipv6 *)&api.prefix,
ifindex, &nexthop, api.tag);
else
- ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
- (struct prefix_ipv6 *)&api.prefix,
- ifindex);
+ ripng_redistribute_delete(
+ ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
+ (struct prefix_ipv6 *)&api.prefix, ifindex);
return 0;
}
-void ripng_redistribute_conf_update(int type)
+void ripng_redistribute_conf_update(struct ripng *ripng, int type)
{
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
- VRF_DEFAULT);
+ ripng->vrf->vrf_id);
}
-void ripng_redistribute_conf_delete(int type)
+void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
{
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
- AFI_IP6, type, 0, VRF_DEFAULT);
+ AFI_IP6, type, 0, ripng->vrf->vrf_id);
- ripng_redistribute_withdraw(type);
+ ripng_redistribute_withdraw(ripng, type);
}
-int ripng_redistribute_check(int type)
+int ripng_redistribute_check(struct ripng *ripng, int type)
{
- return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
+ return ripng->redist[type].enabled;
}
-void ripng_redistribute_clean(void)
+void ripng_redistribute_enable(struct ripng *ripng)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
+ if (!ripng_redistribute_check(ripng, i))
continue;
- if (zclient->sock > 0)
- zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
- zclient, AFI_IP6, i, 0,
- VRF_DEFAULT);
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
+ AFI_IP6, i, 0, ripng->vrf->vrf_id);
+ }
+}
- vrf_bitmap_unset(zclient->redist[AFI_IP6][i], VRF_DEFAULT);
+void ripng_redistribute_disable(struct ripng *ripng)
+{
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ if (!ripng_redistribute_check(ripng, i))
+ continue;
- /* Remove the routes from RIP table. */
- ripng_redistribute_withdraw(i);
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
+ AFI_IP6, i, 0, ripng->vrf->vrf_id);
}
}
-void ripng_redistribute_write(struct vty *vty)
+void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
{
int i;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default
- || !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
- VRF_DEFAULT))
+ || !ripng_redistribute_check(ripng, i))
continue;
vty_out(vty, " %s", zebra_route_string(i));
}
}
+void ripng_zebra_vrf_register(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
+ vrf->name, vrf->vrf_id);
+
+ zclient_send_reg_requests(zclient, vrf->vrf_id);
+}
+
+void ripng_zebra_vrf_deregister(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
+ vrf->name, vrf->vrf_id);
+
+ zclient_send_dereg_requests(zclient, vrf->vrf_id);
+}
+
static void ripng_zebra_connected(struct zclient *zclient)
{
zclient_send_reg_requests(zclient, VRF_DEFAULT);
@@ -215,6 +249,7 @@ void zebra_init(struct thread_master *master)
zclient->interface_delete = ripng_interface_delete;
zclient->interface_address_add = ripng_interface_address_add;
zclient->interface_address_delete = ripng_interface_address_delete;
+ zclient->interface_vrf_update = ripng_interface_vrf_update;
zclient->redistribute_route_add = ripng_zebra_read_route;
zclient->redistribute_route_del = ripng_zebra_read_route;
}
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 9faebcf0d..b36cee2c5 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -43,11 +43,6 @@
#include "ripngd/ripng_debug.h"
#include "ripngd/ripng_nexthop.h"
-/* RIPng structure which includes many parameters related to RIPng
- protocol. If ripng couldn't active or ripng doesn't configured,
- ripng->fd must be negative value. */
-struct ripng *ripng = NULL;
-
enum { ripng_all_route,
ripng_changed_route,
};
@@ -57,12 +52,23 @@ static void ripng_distribute_update(struct distribute_ctx *ctx,
/* Prototypes. */
void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
-
+static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
+ int sock);
+static void ripng_instance_disable(struct ripng *ripng);
int ripng_triggered_update(struct thread *);
-
static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
struct if_rmap *if_rmap);
+/* Generate rb-tree of RIPng instances. */
+static inline int ripng_instance_compare(const struct ripng *a,
+ const struct ripng *b)
+{
+ return strcmp(a->vrf_name, b->vrf_name);
+}
+RB_GENERATE(ripng_instance_head, ripng, entry, ripng_instance_compare)
+
+struct ripng_instance_head ripng_instances = RB_INITIALIZER(&ripng_instances);
+
/* RIPng next hop specification. */
struct ripng_nexthop {
enum ripng_nexthop_type {
@@ -93,19 +99,36 @@ void ripng_info_free(struct ripng_info *rinfo)
XFREE(MTYPE_RIPNG_ROUTE, rinfo);
}
+struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo)
+{
+ return agg_get_table_info(agg_get_table(rinfo->rp));
+}
+
/* Create ripng socket. */
-int ripng_make_socket(void)
+int ripng_make_socket(struct vrf *vrf)
{
int ret;
int sock;
struct sockaddr_in6 ripaddr;
-
- sock = socket(AF_INET6, SOCK_DGRAM, 0);
- if (sock < 0) {
- flog_err_sys(EC_LIB_SOCKET, "Can't make ripng socket");
- return sock;
+ const char *vrf_dev = NULL;
+
+ /* Make datagram socket. */
+ if (vrf->vrf_id != VRF_DEFAULT)
+ vrf_dev = vrf->name;
+ frr_elevate_privs(&ripngd_privs)
+ {
+ sock = vrf_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
+ vrf->vrf_id, vrf_dev);
+ if (sock < 0) {
+ flog_err_sys(EC_LIB_SOCKET,
+ "Cannot create UDP socket: %s",
+ safe_strerror(errno));
+ return -1;
+ }
}
+ sockopt_reuseaddr(sock);
+ sockopt_reuseport(sock);
setsockopt_so_recvbuf(sock, 8096);
ret = setsockopt_ipv6_pktinfo(sock, 1);
if (ret < 0)
@@ -151,11 +174,13 @@ error:
int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to,
struct interface *ifp)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
int ret;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsgptr;
- char adata[256];
+ char adata[256] = {};
struct in6_pktinfo *pkt;
struct sockaddr_in6 addr;
@@ -424,13 +449,14 @@ static int ripng_garbage_collect(struct thread *t)
return 0;
}
-static void ripng_timeout_update(struct ripng_info *rinfo);
+static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo);
/* Add new route to the ECMP list.
* RETURN: the new entry added in the list, or NULL if it is not the first
* entry and ECMP is not allowed.
*/
-struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new)
+struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
+ struct ripng_info *rinfo_new)
{
struct agg_node *rp = rinfo_new->rp;
struct ripng_info *rinfo = NULL;
@@ -450,8 +476,8 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new)
listnode_add(list, rinfo);
if (ripng_route_rte(rinfo)) {
- ripng_timeout_update(rinfo);
- ripng_zebra_ipv6_add(rp);
+ ripng_timeout_update(ripng, rinfo);
+ ripng_zebra_ipv6_add(ripng, rp);
}
ripng_aggregate_increment(rp, rinfo);
@@ -461,7 +487,7 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new)
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
return rinfo;
}
@@ -469,7 +495,8 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new)
/* Replace the ECMP list with the new route.
* RETURN: the new entry added in the list
*/
-struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
+struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
+ struct ripng_info *rinfo_new)
{
struct agg_node *rp = rinfo_new->rp;
struct list *list = (struct list *)rp->info;
@@ -477,7 +504,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
struct listnode *node = NULL, *nextnode = NULL;
if (list == NULL || listcount(list) == 0)
- return ripng_ecmp_add(rinfo_new);
+ return ripng_ecmp_add(ripng, rinfo_new);
/* Get the first entry */
rinfo = listgetdata(listhead(list));
@@ -485,7 +512,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
/* Learnt route replaced by a local one. Delete it from zebra. */
if (ripng_route_rte(rinfo) && !ripng_route_rte(rinfo_new))
if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
if (rinfo->metric != RIPNG_METRIC_INFINITY)
ripng_aggregate_decrement_list(rp, list);
@@ -504,9 +531,9 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
memcpy(rinfo, rinfo_new, sizeof(struct ripng_info));
if (ripng_route_rte(rinfo)) {
- ripng_timeout_update(rinfo);
+ ripng_timeout_update(ripng, rinfo);
/* The ADD message implies an update. */
- ripng_zebra_ipv6_add(rp);
+ ripng_zebra_ipv6_add(ripng, rp);
}
ripng_aggregate_increment(rp, rinfo);
@@ -515,7 +542,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
return rinfo;
}
@@ -526,7 +553,8 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
* the entry - the entry is the last one in the list; its metric is set
* to INFINITY, and the garbage collector is started for it
*/
-struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo)
+struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
+ struct ripng_info *rinfo)
{
struct agg_node *rp = rinfo->rp;
struct list *list = (struct list *)rp->info;
@@ -544,7 +572,7 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo)
if (ripng_route_rte(rinfo)
&& CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
/* The ADD message implies the update. */
- ripng_zebra_ipv6_add(rp);
+ ripng_zebra_ipv6_add(ripng, rp);
ripng_info_free(rinfo);
rinfo = NULL;
} else {
@@ -560,7 +588,7 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo)
if (ripng_route_rte(rinfo)
&& CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
}
/* Set the route change flag on the first entry. */
@@ -568,7 +596,7 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo)
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
return rinfo;
}
@@ -576,16 +604,20 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo)
/* Timeout RIPng routes. */
static int ripng_timeout(struct thread *t)
{
- ripng_ecmp_delete((struct ripng_info *)THREAD_ARG(t));
+ struct ripng_info *rinfo = THREAD_ARG(t);
+ struct ripng *ripng = ripng_info_get_instance(rinfo);
+
+ ripng_ecmp_delete(ripng, rinfo);
+
return 0;
}
-static void ripng_timeout_update(struct ripng_info *rinfo)
+static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo)
{
if (rinfo->metric != RIPNG_METRIC_INFINITY) {
RIPNG_TIMER_OFF(rinfo->t_timeout);
- RIPNG_TIMER_ON(rinfo->t_timeout, ripng_timeout,
- ripng->timeout_time);
+ thread_add_timer(master, ripng_timeout, rinfo,
+ ripng->timeout_time, &rinfo->t_timeout);
}
}
@@ -625,7 +657,7 @@ static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p,
}
/* All interface filter check. */
- dist = distribute_lookup(ripng->distribute_ctx, NULL);
+ dist = distribute_lookup(ri->ripng->distribute_ctx, NULL);
if (dist) {
if (dist->list[distribute]) {
alist = access_list_lookup(AFI_IP6,
@@ -673,6 +705,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
struct agg_node *rp;
struct ripng_info *rinfo = NULL, newinfo;
struct ripng_interface *ri;
+ struct ripng *ripng;
struct in6_addr *nexthop;
int same = 0;
struct list *list = NULL;
@@ -690,9 +723,10 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
apply_mask_ipv6. */
apply_mask_ipv6(&p);
- /* Apply input filters. */
ri = ifp->info;
+ ripng = ri->ripng;
+ /* Apply input filters. */
ret = ripng_filter(RIPNG_FILTER_IN, &p, ri);
if (ret < 0)
return;
@@ -760,7 +794,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
**/
/* Zebra ripngd can handle offset-list in. */
- ret = ripng_offset_list_apply_in(&p, ifp, &rte->metric);
+ ret = ripng_offset_list_apply_in(ripng, &p, ifp, &rte->metric);
/* If offset-list does not modify the metric use interface's
* one. */
@@ -846,7 +880,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
infinity (there is no point in adding a route which
unusable). */
if (rte->metric != RIPNG_METRIC_INFINITY)
- ripng_ecmp_add(&newinfo);
+ ripng_ecmp_add(ripng, &newinfo);
else
agg_unlock_node(rp);
} else {
@@ -871,7 +905,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
&& rinfo->t_timeout
&& (thread_timer_remain_second(rinfo->t_timeout)
< (ripng->timeout_time / 2))) {
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
}
/* Next, compare the metrics. If the datagram is from the same
router as the existing route, and the new metric is different
@@ -881,17 +915,17 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
|| rte->metric < rinfo->metric) {
if (listcount(list) == 1) {
if (newinfo.metric != RIPNG_METRIC_INFINITY)
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
else
- ripng_ecmp_delete(rinfo);
+ ripng_ecmp_delete(ripng, rinfo);
} else {
if (newinfo.metric < rinfo->metric)
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
else /* newinfo.metric > rinfo->metric */
- ripng_ecmp_delete(rinfo);
+ ripng_ecmp_delete(ripng, rinfo);
}
} else /* same & no change */
- ripng_timeout_update(rinfo);
+ ripng_timeout_update(ripng, rinfo);
/* Unlock tempolary lock of the route. */
agg_unlock_node(rp);
@@ -899,9 +933,9 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
}
/* Add redistributed route to RIPng table. */
-void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p,
- ifindex_t ifindex, struct in6_addr *nexthop,
- route_tag_t tag)
+void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
+ struct prefix_ipv6 *p, ifindex_t ifindex,
+ struct in6_addr *nexthop, route_tag_t tag)
{
struct agg_node *rp;
struct ripng_info *rinfo = NULL, newinfo;
@@ -950,31 +984,31 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p,
}
}
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
agg_unlock_node(rp);
} else
- ripng_ecmp_add(&newinfo);
+ ripng_ecmp_add(ripng, &newinfo);
if (IS_RIPNG_DEBUG_EVENT) {
if (!nexthop)
zlog_debug(
"Redistribute new prefix %s/%d on the interface %s",
inet6_ntoa(p->prefix), p->prefixlen,
- ifindex2ifname(ifindex, VRF_DEFAULT));
+ ifindex2ifname(ifindex, ripng->vrf->vrf_id));
else
zlog_debug(
"Redistribute new prefix %s/%d with nexthop %s on the interface %s",
inet6_ntoa(p->prefix), p->prefixlen,
inet6_ntoa(*nexthop),
- ifindex2ifname(ifindex, VRF_DEFAULT));
+ ifindex2ifname(ifindex, ripng->vrf->vrf_id));
}
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
/* Delete redistributed route to RIPng table. */
-void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p,
- ifindex_t ifindex)
+void ripng_redistribute_delete(struct ripng *ripng, int type, int sub_type,
+ struct prefix_ipv6 *p, ifindex_t ifindex)
{
struct agg_node *rp;
struct ripng_info *rinfo;
@@ -1012,10 +1046,11 @@ void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p,
"infinity metric [delete]",
inet6_ntoa(p->prefix),
p->prefixlen,
- ifindex2ifname(ifindex,
- VRF_DEFAULT));
+ ifindex2ifname(
+ ifindex,
+ ripng->vrf->vrf_id));
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
}
agg_unlock_node(rp);
@@ -1023,15 +1058,12 @@ void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p,
}
/* Withdraw redistributed route. */
-void ripng_redistribute_withdraw(int type)
+void ripng_redistribute_withdraw(struct ripng *ripng, int type)
{
struct agg_node *rp;
struct ripng_info *rinfo = NULL;
struct list *list = NULL;
- if (!ripng)
- return;
-
for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp))
if ((list = rp->info) != NULL) {
rinfo = listgetdata(listhead(list));
@@ -1057,11 +1089,12 @@ void ripng_redistribute_withdraw(int type)
"Poisone %s/%d on the interface %s [withdraw]",
inet6_ntoa(p->prefix),
p->prefixlen,
- ifindex2ifname(rinfo->ifindex,
- VRF_DEFAULT));
+ ifindex2ifname(
+ rinfo->ifindex,
+ ripng->vrf->vrf_id));
}
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
}
}
@@ -1071,6 +1104,8 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
struct sockaddr_in6 *from,
struct interface *ifp, int hoplimit)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
caddr_t lim;
struct rte *rte;
struct ripng_nexthop nexthop;
@@ -1080,7 +1115,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
if (ntohs(from->sin6_port) != RIPNG_PORT_DEFAULT) {
zlog_warn("RIPng packet comes from non RIPng port %d from %s",
ntohs(from->sin6_port), inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
@@ -1090,7 +1125,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
zlog_warn("RIPng packet comes from non link local address %s",
inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
@@ -1103,7 +1138,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
zlog_warn(
"RIPng packet comes from my own link local address %s",
inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
@@ -1115,12 +1150,12 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
zlog_warn(
"RIPng packet comes with non 255 hop count %d from %s",
hoplimit, inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
/* Update RIPng peer. */
- ripng_peer_update(from, packet->version);
+ ripng_peer_update(ripng, from, packet->version);
/* Reset nexthop. */
memset(&nexthop, 0, sizeof(struct ripng_nexthop));
@@ -1148,7 +1183,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
"Destination prefix is a multicast address %s/%d [%d]",
inet6_ntoa(rte->addr), rte->prefixlen,
rte->metric);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) {
@@ -1156,7 +1191,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
"Destination prefix is a link-local address %s/%d [%d]",
inet6_ntoa(rte->addr), rte->prefixlen,
rte->metric);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
if (IN6_IS_ADDR_LOOPBACK(&rte->addr)) {
@@ -1164,7 +1199,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
"Destination prefix is a loopback address %s/%d [%d]",
inet6_ntoa(rte->addr), rte->prefixlen,
rte->metric);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
@@ -1174,7 +1209,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
zlog_warn("Invalid prefix length %s/%d from %s%%%s",
inet6_ntoa(rte->addr), rte->prefixlen,
inet6_ntoa(from->sin6_addr), ifp->name);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
@@ -1182,7 +1217,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size,
if (!(rte->metric >= 1 && rte->metric <= 16)) {
zlog_warn("Invalid metric %d from %s%%%s", rte->metric,
inet6_ntoa(from->sin6_addr), ifp->name);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
@@ -1200,6 +1235,7 @@ static void ripng_request_process(struct ripng_packet *packet, int size,
struct sockaddr_in6 *from,
struct interface *ifp)
{
+ struct ripng *ripng;
caddr_t lim;
struct rte *rte;
struct prefix_ipv6 p;
@@ -1215,13 +1251,14 @@ static void ripng_request_process(struct ripng_packet *packet, int size,
ri = ifp->info;
if (!ri->running)
return;
+ ripng = ri->ripng;
/* When passive interface is specified, suppress responses */
if (ri->passive)
return;
/* RIPng peer update. */
- ripng_peer_update(from, packet->version);
+ ripng_peer_update(ripng, from, packet->version);
lim = ((caddr_t)packet) + size;
rte = packet->rte;
@@ -1278,6 +1315,7 @@ static void ripng_request_process(struct ripng_packet *packet, int size,
/* First entry point of reading RIPng packet. */
static int ripng_read(struct thread *thread)
{
+ struct ripng *ripng = THREAD_ARG(thread);
int len;
int sock;
struct sockaddr_in6 from;
@@ -1296,34 +1334,36 @@ static int ripng_read(struct thread *thread)
ripng->t_read = NULL;
/* Add myself to the next event. */
- ripng_event(RIPNG_READ, sock);
+ ripng_event(ripng, RIPNG_READ, sock);
/* Read RIPng packet. */
len = ripng_recv_packet(sock, STREAM_DATA(ripng->ibuf),
STREAM_SIZE(ripng->ibuf), &from, &ifindex,
&hoplimit);
if (len < 0) {
- zlog_warn("RIPng recvfrom failed: %s.", safe_strerror(errno));
+ zlog_warn("RIPng recvfrom failed (VRF %s): %s.",
+ ripng->vrf_name, safe_strerror(errno));
return len;
}
/* Check RTE boundary. RTE size (Packet length - RIPng header size
(4)) must be multiple size of one RTE size (20). */
if (((len - 4) % 20) != 0) {
- zlog_warn("RIPng invalid packet size %d from %s", len,
- inet6_ntoa(from.sin6_addr));
- ripng_peer_bad_packet(&from);
+ zlog_warn("RIPng invalid packet size %d from %s (VRF %s)", len,
+ inet6_ntoa(from.sin6_addr), ripng->vrf_name);
+ ripng_peer_bad_packet(ripng, &from);
return 0;
}
packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf);
- ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(ifindex, ripng->vrf->vrf_id);
/* RIPng packet received. */
if (IS_RIPNG_DEBUG_EVENT)
- zlog_debug("RIPng packet received from %s port %d on %s",
- inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port),
- ifp ? ifp->name : "unknown");
+ zlog_debug(
+ "RIPng packet received from %s port %d on %s (VRF %s)",
+ inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port),
+ ifp ? ifp->name : "unknown", ripng->vrf_name);
/* Logging before packet checking. */
if (IS_RIPNG_DEBUG_RECV)
@@ -1331,17 +1371,18 @@ static int ripng_read(struct thread *thread)
/* Packet comes from unknown interface. */
if (ifp == NULL) {
- zlog_warn("RIPng packet comes from unknown interface %d",
- ifindex);
+ zlog_warn(
+ "RIPng packet comes from unknown interface %d (VRF %s)",
+ ifindex, ripng->vrf_name);
return 0;
}
/* Packet version mismatch checking. */
if (packet->version != ripng->version) {
zlog_warn(
- "RIPng packet version %d doesn't fit to my version %d",
- packet->version, ripng->version);
- ripng_peer_bad_packet(&from);
+ "RIPng packet version %d doesn't fit to my version %d (VRF %s)",
+ packet->version, ripng->version, ripng->vrf_name);
+ ripng_peer_bad_packet(ripng, &from);
return 0;
}
@@ -1354,15 +1395,16 @@ static int ripng_read(struct thread *thread)
ripng_response_process(packet, len, &from, ifp, hoplimit);
break;
default:
- zlog_warn("Invalid RIPng command %d", packet->command);
- ripng_peer_bad_packet(&from);
+ zlog_warn("Invalid RIPng command %d (VRF %s)", packet->command,
+ ripng->vrf_name);
+ ripng_peer_bad_packet(ripng, &from);
break;
}
return 0;
}
/* Walk down the RIPng routing table then clear changed flag. */
-static void ripng_clear_changed_flag(void)
+static void ripng_clear_changed_flag(struct ripng *ripng)
{
struct agg_node *rp;
struct ripng_info *rinfo = NULL;
@@ -1383,7 +1425,7 @@ static void ripng_clear_changed_flag(void)
enabled interface. */
static int ripng_update(struct thread *t)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng = THREAD_ARG(t);
struct interface *ifp;
struct ripng_interface *ri;
@@ -1395,7 +1437,7 @@ static int ripng_update(struct thread *t)
zlog_debug("RIPng update timer expired!");
/* Supply routes to each interface. */
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (ripng->vrf, ifp) {
ri = ifp->info;
if (if_is_loopback(ifp) || !if_is_up(ifp))
@@ -1431,7 +1473,7 @@ static int ripng_update(struct thread *t)
ripng->trigger = 0;
/* Reset flush event. */
- ripng_event(RIPNG_UPDATE_EVENT, 0);
+ ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
return 0;
}
@@ -1439,6 +1481,8 @@ static int ripng_update(struct thread *t)
/* Triggered update interval timer. */
static int ripng_triggered_interval(struct thread *t)
{
+ struct ripng *ripng = THREAD_ARG(t);
+
ripng->t_triggered_interval = NULL;
if (ripng->trigger) {
@@ -1451,7 +1495,7 @@ static int ripng_triggered_interval(struct thread *t)
/* Execute triggered update. */
int ripng_triggered_update(struct thread *t)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng = THREAD_ARG(t);
struct interface *ifp;
struct ripng_interface *ri;
int interval;
@@ -1471,7 +1515,7 @@ int ripng_triggered_update(struct thread *t)
/* Split Horizon processing is done when generating triggered
updates as well as normal updates (see section 2.6). */
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (ripng->vrf, ifp) {
ri = ifp->info;
if (if_is_loopback(ifp) || !if_is_up(ifp))
@@ -1490,7 +1534,7 @@ int ripng_triggered_update(struct thread *t)
/* Once all of the triggered updates have been generated, the route
change flags should be cleared. */
- ripng_clear_changed_flag();
+ ripng_clear_changed_flag(ripng);
/* After a triggered update is sent, a timer should be set for a
random interval between 1 and 5 seconds. If other changes that
@@ -1499,7 +1543,7 @@ int ripng_triggered_update(struct thread *t)
interval = (random() % 5) + 1;
ripng->t_triggered_interval = NULL;
- thread_add_timer(master, ripng_triggered_interval, NULL, interval,
+ thread_add_timer(master, ripng_triggered_interval, ripng, interval,
&ripng->t_triggered_interval);
return 0;
@@ -1537,6 +1581,7 @@ int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
int route_type)
{
+ struct ripng *ripng;
int ret;
struct agg_node *rp;
struct ripng_info *rinfo;
@@ -1556,8 +1601,9 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
ifp->name);
}
- /* Get RIPng interface. */
+ /* Get RIPng interface and instance. */
ri = ifp->info;
+ ripng = ri->ripng;
ripng_rte_list = ripng_rte_new();
@@ -1637,10 +1683,11 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
}
/* Redistribute route-map. */
- if (ripng->route_map[rinfo->type].name) {
- ret = route_map_apply(
- ripng->route_map[rinfo->type].map,
- (struct prefix *)p, RMAP_RIPNG, rinfo);
+ if (ripng->redist[rinfo->type].route_map.name) {
+ ret = route_map_apply(ripng->redist[rinfo->type]
+ .route_map.map,
+ (struct prefix *)p,
+ RMAP_RIPNG, rinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIPNG_DEBUG_PACKET)
@@ -1655,10 +1702,10 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
/* When the route-map does not set metric. */
if (!rinfo->metric_set) {
/* If the redistribute metric is set. */
- if (ripng->route_map[rinfo->type].metric_config
+ if (ripng->redist[rinfo->type].metric_config
&& rinfo->metric != RIPNG_METRIC_INFINITY) {
rinfo->metric_out =
- ripng->route_map[rinfo->type]
+ ripng->redist[rinfo->type]
.metric;
} else {
/* If the route is not connected or
@@ -1676,7 +1723,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
/* Apply offset-list */
if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
- ripng_offset_list_apply_out(p, ifp,
+ ripng_offset_list_apply_out(ripng, p, ifp,
&rinfo->metric_out);
if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
@@ -1769,7 +1816,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
/* Apply offset-list */
if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
ripng_offset_list_apply_out(
- p, ifp, &aggregate->metric_out);
+ ripng, p, ifp, &aggregate->metric_out);
if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
aggregate->metric_out = RIPNG_METRIC_INFINITY;
@@ -1784,14 +1831,34 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
ripng_rte_free(ripng_rte_list);
}
+struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id)
+{
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
+ return vrf->info;
+}
+
+struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name)
+{
+ struct ripng ripng;
+
+ ripng.vrf_name = (char *)vrf_name;
+
+ return RB_FIND(ripng_instance_head, &ripng_instances, &ripng);
+}
+
/* Create new RIPng instance and set it to global variable. */
-int ripng_create(int socket)
+struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf, int socket)
{
- /* ripng should be NULL. */
- assert(ripng == NULL);
+ struct ripng *ripng;
/* Allocaste RIPng instance. */
ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng));
+ ripng->vrf_name = XSTRDUP(MTYPE_RIPNG_VRF_NAME, vrf_name);
/* Default version and timer values. */
ripng->version = RIPNG_V1;
@@ -1809,30 +1876,42 @@ int ripng_create(int socket)
ripng->ibuf = stream_new(RIPNG_MAX_PACKET_SIZE * 5);
ripng->obuf = stream_new(RIPNG_MAX_PACKET_SIZE);
- /* Initialize RIPng routig table. */
+ /* Initialize RIPng data structures. */
ripng->table = agg_table_init();
-
- /* Distribute list install. */
- ripng->distribute_ctx = distribute_list_ctx_create(
- vrf_lookup_by_id(VRF_DEFAULT));
+ agg_set_table_info(ripng->table, ripng);
+ ripng->peer_list = list_new();
+ ripng->peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
+ ripng->peer_list->del = ripng_peer_list_del;
+ ripng->enable_if = vector_init(1);
+ ripng->enable_network = agg_table_init();
+ ripng->passive_interface = vector_init(1);
+ 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;
+ ripng->distribute_ctx = distribute_list_ctx_create(vrf);
distribute_list_add_hook(ripng->distribute_ctx,
ripng_distribute_update);
distribute_list_delete_hook(ripng->distribute_ctx,
ripng_distribute_update);
/* if rmap install. */
- ripng->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ ripng->if_rmap_ctx = if_rmap_ctx_create(vrf_name);
if_rmap_hook_add(ripng->if_rmap_ctx, ripng_if_rmap_update);
if_rmap_hook_delete(ripng->if_rmap_ctx, ripng_if_rmap_update);
- /* Make socket. */
- ripng->sock = socket;
+ /* Enable the routing instance if possible. */
+ if (vrf && vrf_is_enabled(vrf))
+ ripng_instance_enable(ripng, vrf, socket);
+ else {
+ ripng->vrf = NULL;
+ ripng->sock = -1;
+ }
- /* Threads. */
- ripng_event(RIPNG_READ, ripng->sock);
- ripng_event(RIPNG_UPDATE_EVENT, 1);
+ RB_INSERT(ripng_instance_head, &ripng_instances, ripng);
- return 0;
+ return ripng;
}
/* Send RIPng request to the interface. */
@@ -1869,13 +1948,14 @@ static int ripng_update_jitter(int time)
return ((random() % (time + 1)) - (time / 2));
}
-void ripng_event(enum ripng_event event, int sock)
+void ripng_event(struct ripng *ripng, enum ripng_event event, int sock)
{
int jitter = 0;
switch (event) {
case RIPNG_READ:
- thread_add_read(master, ripng_read, NULL, sock, &ripng->t_read);
+ thread_add_read(master, ripng_read, ripng, sock,
+ &ripng->t_read);
break;
case RIPNG_UPDATE_EVENT:
if (ripng->t_update) {
@@ -1886,7 +1966,7 @@ void ripng_event(enum ripng_event event, int sock)
jitter = ripng_update_jitter(ripng->update_time);
ripng->t_update = NULL;
- thread_add_timer(master, ripng_update, NULL,
+ thread_add_timer(master, ripng_update, ripng,
sock ? 2 : ripng->update_time + jitter,
&ripng->t_update);
break;
@@ -1894,7 +1974,7 @@ void ripng_event(enum ripng_event event, int sock)
if (ripng->t_triggered_interval)
ripng->trigger = 1;
else
- thread_add_event(master, ripng_triggered_update, NULL,
+ thread_add_event(master, ripng_triggered_update, ripng,
0, &ripng->t_triggered_update);
break;
default:
@@ -1959,11 +2039,13 @@ static char *ripng_route_subtype_print(struct ripng_info *rinfo)
DEFUN (show_ipv6_ripng,
show_ipv6_ripng_cmd,
- "show ipv6 ripng",
+ "show ipv6 ripng [vrf NAME]",
SHOW_STR
IPV6_STR
- "Show RIPng routes\n")
+ "Show RIPng routes\n"
+ VRF_CMD_HELP_STR)
{
+ struct ripng *ripng;
struct agg_node *rp;
struct ripng_info *rinfo;
struct ripng_aggregate *aggregate;
@@ -1971,9 +2053,23 @@ DEFUN (show_ipv6_ripng,
struct list *list = NULL;
struct listnode *listnode = NULL;
int len;
+ const char *vrf_name;
+ int idx = 0;
- if (!ripng)
+ if (argv_find(argv, argc, "vrf", &idx))
+ vrf_name = argv[idx + 1]->arg;
+ else
+ vrf_name = VRF_DEFAULT_NAME;
+
+ ripng = ripng_lookup_by_vrf_name(vrf_name);
+ if (!ripng) {
+ vty_out(vty, "%% RIPng instance not found\n");
+ return CMD_SUCCESS;
+ }
+ if (!ripng->enabled) {
+ vty_out(vty, "%% RIPng instance is disabled\n");
return CMD_SUCCESS;
+ }
/* Header of display. */
vty_out(vty,
@@ -2033,8 +2129,9 @@ DEFUN (show_ipv6_ripng,
&& (rinfo->sub_type == RIPNG_ROUTE_RTE)) {
len = vty_out(
vty, "%s",
- ifindex2ifname(rinfo->ifindex,
- VRF_DEFAULT));
+ ifindex2ifname(
+ rinfo->ifindex,
+ ripng->vrf->vrf_id));
} else if (rinfo->metric
== RIPNG_METRIC_INFINITY) {
len = vty_out(vty, "kill");
@@ -2068,17 +2165,32 @@ DEFUN (show_ipv6_ripng,
DEFUN (show_ipv6_ripng_status,
show_ipv6_ripng_status_cmd,
- "show ipv6 ripng status",
+ "show ipv6 ripng [vrf NAME] status",
SHOW_STR
IPV6_STR
"Show RIPng routes\n"
+ VRF_CMD_HELP_STR
"IPv6 routing protocol process parameters and statistics\n")
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng;
struct interface *ifp;
+ const char *vrf_name;
+ int idx = 0;
- if (!ripng)
+ if (argv_find(argv, argc, "vrf", &idx))
+ vrf_name = argv[idx + 1]->arg;
+ else
+ vrf_name = VRF_DEFAULT_NAME;
+
+ ripng = ripng_lookup_by_vrf_name(vrf_name);
+ if (!ripng) {
+ vty_out(vty, "%% RIPng instance not found\n");
+ return CMD_SUCCESS;
+ }
+ if (!ripng->enabled) {
+ vty_out(vty, "%% RIPng instance is disabled\n");
return CMD_SUCCESS;
+ }
vty_out(vty, "Routing Protocol is \"RIPng\"\n");
vty_out(vty, " Sending updates every %u seconds with +/-50%%,",
@@ -2098,7 +2210,7 @@ DEFUN (show_ipv6_ripng_status,
/* Redistribute information. */
vty_out(vty, " Redistributing:");
- ripng_redistribute_write(vty);
+ ripng_redistribute_write(vty, ripng);
vty_out(vty, "\n");
vty_out(vty, " Default version control: send version %d,",
@@ -2107,7 +2219,7 @@ DEFUN (show_ipv6_ripng_status,
vty_out(vty, " Interface Send Recv\n");
- FOR_ALL_INTERFACES (vrf, ifp) {
+ FOR_ALL_INTERFACES (ripng->vrf, ifp) {
struct ripng_interface *ri;
ri = ifp->info;
@@ -2120,12 +2232,12 @@ DEFUN (show_ipv6_ripng_status,
}
vty_out(vty, " Routing for Networks:\n");
- ripng_network_write(vty);
+ ripng_network_write(vty, ripng);
vty_out(vty, " Routing Information Sources:\n");
vty_out(vty,
" Gateway BadPackets BadRoutes Distance Last Update\n");
- ripng_peer_display(vty);
+ ripng_peer_display(vty, ripng);
return CMD_SUCCESS;
}
@@ -2261,7 +2373,7 @@ DEFUN (show_ipv6_protocols,
#endif
/* Update ECMP routes to zebra when ECMP is disabled. */
-void ripng_ecmp_disable(void)
+void ripng_ecmp_disable(struct ripng *ripng)
{
struct agg_node *rp;
struct ripng_info *rinfo, *tmp_rinfo;
@@ -2288,30 +2400,36 @@ void ripng_ecmp_disable(void)
}
/* Update zebra. */
- ripng_zebra_ipv6_add(rp);
+ ripng_zebra_ipv6_add(ripng, rp);
/* Set the route change flag. */
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
}
/* RIPng configuration write function. */
static int ripng_config_write(struct vty *vty)
{
- struct lyd_node *dnode;
+ struct ripng *ripng;
int write = 0;
- dnode = yang_dnode_get(running_config->dnode,
- "/frr-ripngd:ripngd/instance");
- if (dnode) {
- nb_cli_show_dnode_cmds(vty, dnode, false);
+ RB_FOREACH(ripng, ripng_instance_head, &ripng_instances) {
+ char xpath[XPATH_MAXLEN];
+ struct lyd_node *dnode;
- config_write_distribute(vty,
- ripng->distribute_ctx);
+ snprintf(xpath, sizeof(xpath),
+ "/frr-ripngd:ripngd/instance[vrf='%s']",
+ ripng->vrf_name);
+ dnode = yang_dnode_get(running_config->dnode, xpath);
+ assert(dnode);
+
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+
+ config_write_distribute(vty, ripng->distribute_ctx);
config_write_if_rmap(vty, ripng->if_rmap_ctx);
write = 1;
@@ -2333,10 +2451,10 @@ static void ripng_distribute_update(struct distribute_ctx *ctx,
struct access_list *alist;
struct prefix_list *plist;
- if (!dist->ifname)
+ if (!ctx->vrf || !dist->ifname)
return;
- ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT);
+ ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id);
if (ifp == NULL)
return;
@@ -2385,6 +2503,8 @@ static void ripng_distribute_update(struct distribute_ctx *ctx,
void ripng_distribute_update_interface(struct interface *ifp)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct distribute *dist;
if (!ripng)
@@ -2410,80 +2530,34 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused)
}
/* delete all the added ripng routes. */
-void ripng_clean(void)
+void ripng_clean(struct ripng *ripng)
{
- int i;
- struct agg_node *rp;
- struct ripng_info *rinfo;
- struct ripng_aggregate *aggregate;
- struct list *list = NULL;
- struct listnode *listnode = NULL;
-
- if (ripng) {
- /* Clear RIPng routes */
- for (rp = agg_route_top(ripng->table); rp;
- rp = agg_route_next(rp)) {
- if ((list = rp->info) != NULL) {
- rinfo = listgetdata(listhead(list));
- if (ripng_route_rte(rinfo))
- ripng_zebra_ipv6_delete(rp);
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode,
- rinfo)) {
- RIPNG_TIMER_OFF(rinfo->t_timeout);
- RIPNG_TIMER_OFF(
- rinfo->t_garbage_collect);
- ripng_info_free(rinfo);
- }
- list_delete(&list);
- rp->info = NULL;
- agg_unlock_node(rp);
- }
-
- if ((aggregate = rp->aggregate) != NULL) {
- ripng_aggregate_free(aggregate);
- rp->aggregate = NULL;
- agg_unlock_node(rp);
- }
- }
-
- /* Cancel the RIPng timers */
- RIPNG_TIMER_OFF(ripng->t_update);
- RIPNG_TIMER_OFF(ripng->t_triggered_update);
- RIPNG_TIMER_OFF(ripng->t_triggered_interval);
-
- /* Cancel the read thread */
- if (ripng->t_read) {
- thread_cancel(ripng->t_read);
- ripng->t_read = NULL;
- }
-
- /* Close the RIPng socket */
- if (ripng->sock >= 0) {
- close(ripng->sock);
- ripng->sock = -1;
- }
-
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (ripng->route_map[i].name)
- free(ripng->route_map[i].name);
-
- agg_table_finish(ripng->table);
-
- stream_free(ripng->ibuf);
- stream_free(ripng->obuf);
-
- distribute_list_delete(&ripng->distribute_ctx);
- XFREE(MTYPE_RIPNG, ripng);
- ripng = NULL;
- } /* if (ripng) */
-
- ripng_clean_network();
- ripng_passive_interface_clean();
- ripng_offset_clean();
- ripng_interface_clean();
- ripng_redistribute_clean();
- if_rmap_terminate();
+ if (ripng->enabled)
+ ripng_instance_disable(ripng);
+
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (ripng->redist[i].route_map.name)
+ free(ripng->redist[i].route_map.name);
+
+ agg_table_finish(ripng->table);
+ list_delete(&ripng->peer_list);
+ distribute_list_delete(&ripng->distribute_ctx);
+ if_rmap_ctx_delete(ripng->if_rmap_ctx);
+
+ stream_free(ripng->ibuf);
+ stream_free(ripng->obuf);
+
+ ripng_clean_network(ripng);
+ ripng_passive_interface_clean(ripng);
+ vector_free(ripng->enable_if);
+ agg_table_finish(ripng->enable_network);
+ vector_free(ripng->passive_interface);
+ list_delete(&ripng->offset_list_master);
+ ripng_interface_clean(ripng);
+
+ RB_REMOVE(ripng_instance_head, &ripng_instances, ripng);
+ XFREE(MTYPE_RIPNG_VRF_NAME, ripng->vrf_name);
+ XFREE(MTYPE_RIPNG, ripng);
}
static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
@@ -2524,11 +2598,11 @@ static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
void ripng_if_rmap_update_interface(struct interface *ifp)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct if_rmap *if_rmap;
struct if_rmap_ctx *ctx;
- if (ifp->vrf_id != VRF_DEFAULT)
- return;
if (!ripng)
return;
ctx = ripng->if_rmap_ctx;
@@ -2539,19 +2613,15 @@ void ripng_if_rmap_update_interface(struct interface *ifp)
ripng_if_rmap_update(ctx, if_rmap);
}
-static void ripng_routemap_update_redistribute(void)
+static void ripng_routemap_update_redistribute(struct ripng *ripng)
{
- int i;
-
- if (ripng) {
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (ripng->route_map[i].name) {
- ripng->route_map[i].map =
- route_map_lookup_by_name(
- ripng->route_map[i].name);
- route_map_counter_increment(
- ripng->route_map[i].map);
- }
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ if (ripng->redist[i].route_map.name) {
+ ripng->redist[i].route_map.map =
+ route_map_lookup_by_name(
+ ripng->redist[i].route_map.name);
+ route_map_counter_increment(
+ ripng->redist[i].route_map.map);
}
}
}
@@ -2559,12 +2629,196 @@ static void ripng_routemap_update_redistribute(void)
static void ripng_routemap_update(const char *unused)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng;
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
ripng_if_rmap_update_interface(ifp);
- ripng_routemap_update_redistribute();
+ ripng = vrf->info;
+ if (ripng)
+ ripng_routemap_update_redistribute(ripng);
+}
+
+/* Link RIPng instance to VRF. */
+static void ripng_vrf_link(struct ripng *ripng, struct vrf *vrf)
+{
+ struct interface *ifp;
+
+ ripng->vrf = vrf;
+ ripng->distribute_ctx->vrf = vrf;
+ vrf->info = ripng;
+
+ FOR_ALL_INTERFACES (vrf, ifp)
+ ripng_interface_sync(ifp);
+}
+
+/* Unlink RIPng instance from VRF. */
+static void ripng_vrf_unlink(struct ripng *ripng, struct vrf *vrf)
+{
+ struct interface *ifp;
+
+ ripng->vrf = NULL;
+ ripng->distribute_ctx->vrf = NULL;
+ vrf->info = NULL;
+
+ FOR_ALL_INTERFACES (vrf, ifp)
+ ripng_interface_sync(ifp);
+}
+
+static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
+ int sock)
+{
+ ripng->sock = sock;
+
+ ripng_vrf_link(ripng, vrf);
+ ripng->enabled = true;
+
+ /* Resend all redistribute requests. */
+ ripng_redistribute_enable(ripng);
+
+ /* Create read and timer thread. */
+ ripng_event(ripng, RIPNG_READ, ripng->sock);
+ ripng_event(ripng, RIPNG_UPDATE_EVENT, 1);
+
+ ripng_zebra_vrf_register(vrf);
+}
+
+static void ripng_instance_disable(struct ripng *ripng)
+{
+ struct vrf *vrf = ripng->vrf;
+ struct agg_node *rp;
+
+ /* Clear RIPng routes */
+ for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
+ struct ripng_aggregate *aggregate;
+ struct list *list;
+
+ if ((list = rp->info) != NULL) {
+ struct ripng_info *rinfo;
+ struct listnode *listnode;
+
+ rinfo = listgetdata(listhead(list));
+ if (ripng_route_rte(rinfo))
+ ripng_zebra_ipv6_delete(ripng, rp);
+
+ for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+ RIPNG_TIMER_OFF(rinfo->t_timeout);
+ RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
+ ripng_info_free(rinfo);
+ }
+ list_delete(&list);
+ rp->info = NULL;
+ agg_unlock_node(rp);
+ }
+
+ if ((aggregate = rp->aggregate) != NULL) {
+ ripng_aggregate_free(aggregate);
+ rp->aggregate = NULL;
+ agg_unlock_node(rp);
+ }
+ }
+
+ /* Flush all redistribute requests. */
+ ripng_redistribute_disable(ripng);
+
+ /* Cancel the RIPng timers */
+ RIPNG_TIMER_OFF(ripng->t_update);
+ RIPNG_TIMER_OFF(ripng->t_triggered_update);
+ RIPNG_TIMER_OFF(ripng->t_triggered_interval);
+
+ /* Cancel the read thread */
+ if (ripng->t_read) {
+ thread_cancel(ripng->t_read);
+ ripng->t_read = NULL;
+ }
+
+ /* Close the RIPng socket */
+ if (ripng->sock >= 0) {
+ close(ripng->sock);
+ ripng->sock = -1;
+ }
+
+ /* Clear existing peers. */
+ list_delete_all_node(ripng->peer_list);
+
+ ripng_zebra_vrf_deregister(vrf);
+
+ ripng_vrf_unlink(ripng, vrf);
+ ripng->enabled = false;
+}
+
+static int ripng_vrf_new(struct vrf *vrf)
+{
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name,
+ vrf->vrf_id);
+
+ return 0;
+}
+
+static int ripng_vrf_delete(struct vrf *vrf)
+{
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name,
+ vrf->vrf_id);
+
+ return 0;
+}
+
+static int ripng_vrf_enable(struct vrf *vrf)
+{
+ struct ripng *ripng;
+ int socket;
+
+ ripng = ripng_lookup_by_vrf_name(vrf->name);
+ if (!ripng || ripng->enabled)
+ return 0;
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name,
+ vrf->vrf_id);
+
+ /* Activate the VRF RIPng instance. */
+ if (!ripng->enabled) {
+ socket = ripng_make_socket(vrf);
+ if (socket < 0)
+ return -1;
+
+ ripng_instance_enable(ripng, vrf, socket);
+ }
+
+ return 0;
+}
+
+static int ripng_vrf_disable(struct vrf *vrf)
+{
+ struct ripng *ripng;
+
+ ripng = ripng_lookup_by_vrf_name(vrf->name);
+ if (!ripng || !ripng->enabled)
+ return 0;
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name,
+ vrf->vrf_id);
+
+ /* Deactivate the VRF RIPng instance. */
+ if (ripng->enabled)
+ ripng_instance_disable(ripng);
+
+ return 0;
+}
+
+void ripng_vrf_init(void)
+{
+ vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable,
+ ripng_vrf_delete, NULL);
+}
+
+void ripng_vrf_terminate(void)
+{
+ vrf_terminate();
}
/* Initialize ripng structure and set commands. */
@@ -2607,7 +2861,6 @@ void ripng_init(void)
/* Route-map for interface. */
ripng_route_map_init();
- ripng_offset_init();
route_map_add_hook(ripng_routemap_update);
route_map_delete_hook(ripng_routemap_update);
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 3f0ef13a0..dcc61ae58 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -25,6 +25,7 @@
#include <zclient.h>
#include <vty.h>
#include <distribute.h>
+#include <vector.h>
#include "ripng_memory.h"
@@ -88,6 +89,17 @@
/* RIPng structure. */
struct ripng {
+ RB_ENTRY(ripng) entry;
+
+ /* VRF this routing instance is associated with. */
+ char *vrf_name;
+
+ /* VRF backpointer (might be NULL if the VRF doesn't exist). */
+ struct vrf *vrf;
+
+ /* Status of the routing instance. */
+ bool enabled;
+
/* RIPng socket. */
int sock;
@@ -107,6 +119,21 @@ struct ripng {
/* RIPng routing information base. */
struct agg_table *table;
+ /* Linked list of RIPng peers. */
+ struct list *peer_list;
+
+ /* RIPng enabled interfaces. */
+ vector enable_if;
+
+ /* RIPng enabled networks. */
+ struct agg_table *enable_network;
+
+ /* Vector to store passive-interface name. */
+ vector passive_interface;
+
+ /* RIPng offset-lists. */
+ struct list *offset_list_master;
+
/* RIPng threads. */
struct thread *t_read;
struct thread *t_write;
@@ -122,13 +149,16 @@ struct ripng {
/* RIPng ECMP flag */
bool ecmp;
- /* For redistribute route map. */
+ /* RIPng redistribute configuration. */
struct {
- char *name;
- struct route_map *map;
+ bool enabled;
+ struct {
+ char *name;
+ struct route_map *map;
+ } route_map;
bool metric_config;
uint8_t metric;
- } route_map[ZEBRA_ROUTE_MAX];
+ } redist[ZEBRA_ROUTE_MAX];
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
@@ -136,6 +166,8 @@ struct ripng {
/* For if_rmap container */
struct if_rmap_ctx *if_rmap_ctx;
};
+RB_HEAD(ripng_instance_head, ripng);
+RB_PROTOTYPE(ripng_instance_head, ripng, entry, ripng_instance_compare)
/* Routing table entry. */
struct rte {
@@ -234,6 +266,9 @@ typedef enum {
/* RIPng specific interface configuration. */
struct ripng_interface {
+ /* Parent routing instance. */
+ struct ripng *ripng;
+
/* RIPng is enabled on this interface. */
int enable_network;
int enable_interface;
@@ -280,6 +315,9 @@ struct ripng_interface {
/* RIPng peer information. */
struct ripng_peer {
+ /* Parent routing instance. */
+ struct ripng *ripng;
+
/* Peer address. */
struct in6_addr addr;
@@ -325,6 +363,9 @@ enum ripng_event {
#define RIPNG_OFFSET_LIST_MAX 2
struct ripng_offset_list {
+ /* Parent routing instance. */
+ struct ripng *ripng;
+
char *ifname;
struct {
@@ -335,72 +376,87 @@ struct ripng_offset_list {
};
/* Extern variables. */
-extern struct ripng *ripng;
-extern struct list *peer_list;
extern struct zebra_privs_t ripngd_privs;
extern struct thread_master *master;
+extern struct ripng_instance_head ripng_instances;
/* Prototypes. */
extern void ripng_init(void);
-extern void ripng_clean(void);
-extern void ripng_clean_network(void);
-extern void ripng_interface_clean(void);
-extern int ripng_enable_network_add(struct prefix *p);
-extern int ripng_enable_network_delete(struct prefix *p);
-extern int ripng_enable_if_add(const char *ifname);
-extern int ripng_enable_if_delete(const char *ifname);
-extern int ripng_passive_interface_set(const char *ifname);
-extern int ripng_passive_interface_unset(const char *ifname);
-extern void ripng_passive_interface_clean(void);
+extern void ripng_clean(struct ripng *ripng);
+extern void ripng_clean_network(struct ripng *ripng);
+extern void ripng_interface_clean(struct ripng *ripng);
+extern int ripng_enable_network_add(struct ripng *ripng, struct prefix *p);
+extern int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p);
+extern int ripng_enable_if_add(struct ripng *ripng, const char *ifname);
+extern int ripng_enable_if_delete(struct ripng *ripng, const char *ifname);
+extern int ripng_passive_interface_set(struct ripng *ripng, const char *ifname);
+extern int ripng_passive_interface_unset(struct ripng *ripng,
+ const char *ifname);
+extern void ripng_passive_interface_clean(struct ripng *ripng);
extern void ripng_if_init(void);
extern void ripng_route_map_init(void);
+extern void ripng_zebra_vrf_register(struct vrf *vrf);
+extern void ripng_zebra_vrf_deregister(struct vrf *vrf);
extern void ripng_terminate(void);
/* zclient_init() is done by ripng_zebra.c:zebra_init() */
extern void zebra_init(struct thread_master *);
extern void ripng_zebra_stop(void);
-extern void ripng_redistribute_conf_update(int type);
-extern void ripng_redistribute_conf_delete(int type);
-
-extern void ripng_peer_init(void);
-extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t);
-extern void ripng_peer_bad_route(struct sockaddr_in6 *);
-extern void ripng_peer_bad_packet(struct sockaddr_in6 *);
-extern void ripng_peer_display(struct vty *);
-extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *);
-extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *);
-
-extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname);
+extern void ripng_redistribute_conf_update(struct ripng *ripng, int type);
+extern void ripng_redistribute_conf_delete(struct ripng *ripng, int type);
+
+extern void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
+ uint8_t version);
+extern void ripng_peer_bad_route(struct ripng *ripng,
+ struct sockaddr_in6 *from);
+extern void ripng_peer_bad_packet(struct ripng *ripng,
+ struct sockaddr_in6 *from);
+extern void ripng_peer_display(struct vty *vty, struct ripng *ripng);
+extern struct ripng_peer *ripng_peer_lookup(struct ripng *ripng,
+ struct in6_addr *addr);
+extern struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
+ struct in6_addr *addr);
+extern int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2);
+extern void ripng_peer_list_del(void *arg);
+
+extern struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
+ const char *ifname);
extern void ripng_offset_list_del(struct ripng_offset_list *offset);
-extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
-extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
-extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *,
- uint8_t *);
-extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *,
- uint8_t *);
-extern void ripng_offset_init(void);
-extern void ripng_offset_clean(void);
+extern struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
+ const char *ifname);
+extern int ripng_offset_list_apply_in(struct ripng *ripng,
+ struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric);
+extern int ripng_offset_list_apply_out(struct ripng *ripng,
+ struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric);
+extern int offset_list_cmp(struct ripng_offset_list *o1,
+ struct ripng_offset_list *o2);
extern int ripng_route_rte(struct ripng_info *rinfo);
extern struct ripng_info *ripng_info_new(void);
extern void ripng_info_free(struct ripng_info *rinfo);
-extern void ripng_event(enum ripng_event, int);
+extern struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo);
+extern void ripng_event(struct ripng *ripng, enum ripng_event event, int sock);
extern int ripng_request(struct interface *ifp);
-extern void ripng_redistribute_add(int, int, struct prefix_ipv6 *, ifindex_t,
- struct in6_addr *, route_tag_t);
-extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *,
- ifindex_t);
-extern void ripng_redistribute_withdraw(int type);
-
-extern void ripng_ecmp_disable(void);
+extern void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
+ struct prefix_ipv6 *p, ifindex_t ifindex,
+ struct in6_addr *nexthop, route_tag_t tag);
+extern void ripng_redistribute_delete(struct ripng *ripng, int type,
+ int sub_type, struct prefix_ipv6 *p,
+ ifindex_t ifindex);
+extern void ripng_redistribute_withdraw(struct ripng *ripng, int type);
+
+extern void ripng_ecmp_disable(struct ripng *ripng);
extern void ripng_distribute_update_interface(struct interface *);
extern void ripng_if_rmap_update_interface(struct interface *);
-extern void ripng_zebra_ipv6_add(struct agg_node *node);
-extern void ripng_zebra_ipv6_delete(struct agg_node *node);
+extern void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *node);
+extern void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *node);
-extern void ripng_redistribute_clean(void);
-extern int ripng_redistribute_check(int);
-extern void ripng_redistribute_write(struct vty *);
+extern void ripng_redistribute_enable(struct ripng *ripng);
+extern void ripng_redistribute_disable(struct ripng *ripng);
+extern int ripng_redistribute_check(struct ripng *ripng, int type);
+extern void ripng_redistribute_write(struct vty *vty, struct ripng *ripng);
extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
struct in6_addr *nexthop, uint16_t tag,
@@ -423,14 +479,26 @@ extern int ripng_interface_address_add(int command, struct zclient *,
zebra_size_t, vrf_id_t);
extern int ripng_interface_address_delete(int command, struct zclient *,
zebra_size_t, vrf_id_t);
-
-extern int ripng_create(int socket);
-extern int ripng_make_socket(void);
-extern int ripng_network_write(struct vty *);
-
-extern struct ripng_info *ripng_ecmp_add(struct ripng_info *);
-extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *);
-extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *);
+extern 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 struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id);
+extern struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name);
+extern struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf,
+ int socket);
+extern int ripng_make_socket(struct vrf *vrf);
+extern int ripng_network_write(struct vty *vty, struct ripng *ripng);
+
+extern struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
+ struct ripng_info *rinfo);
+extern struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
+ struct ripng_info *rinfo);
+extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
+ struct ripng_info *rinfo);
+
+extern void ripng_vrf_init(void);
+extern void ripng_vrf_terminate(void);
/* Northbound. */
extern void ripng_cli_init(void);
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 1f1152d36..b8da90ca8 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1521,15 +1521,15 @@ DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
return CMD_SUCCESS;
}
-DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip",
- ROUTER_STR "RIP\n")
+DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
+ ROUTER_STR "RIP\n" VRF_CMD_HELP_STR)
{
vty->node = RIP_NODE;
return CMD_SUCCESS;
}
-DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng",
- ROUTER_STR "RIPng\n")
+DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
+ ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
{
vty->node = RIPNG_NODE;
return CMD_SUCCESS;
diff --git a/yang/example/ripd.json b/yang/example/ripd.json
index 888c52b93..00040622e 100644
--- a/yang/example/ripd.json
+++ b/yang/example/ripd.json
@@ -20,25 +20,28 @@
]
},
"frr-ripd:ripd": {
- "instance": {
- "allow-ecmp": "true",
- "distance": {
- "source": [
+ "instance": [
+ {
+ "vrf": "default",
+ "allow-ecmp": "true",
+ "distance": {
+ "source": [
+ {
+ "distance": "25",
+ "prefix": "172.16.1.0/24"
+ }
+ ]
+ },
+ "redistribute": [
{
- "prefix": "172.16.1.0/24",
- "distance": "25"
+ "metric": "3",
+ "protocol": "ospf"
}
+ ],
+ "static-route": [
+ "10.0.1.0/24"
]
- },
- "redistribute": [
- {
- "protocol": "ospf",
- "metric": "3"
- }
- ],
- "static-route": [
- "10.0.1.0/24"
- ]
- }
+ }
+ ]
}
}
diff --git a/yang/example/ripd.xml b/yang/example/ripd.xml
index 756e382bd..2feddde2d 100644
--- a/yang/example/ripd.xml
+++ b/yang/example/ripd.xml
@@ -18,6 +18,7 @@
</lib>
<ripd xmlns="http://frrouting.org/yang/ripd">
<instance>
+ <vrf>default</vrf>
<allow-ecmp>true</allow-ecmp>
<static-route>10.0.1.0/24</static-route>
<distance>
diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang
index 8073fba77..07690793f 100644
--- a/yang/frr-ripd.yang
+++ b/yang/frr-ripd.yang
@@ -34,13 +34,18 @@ module frr-ripd {
container ripd {
/*
- * Global configuration data
+ * Routing instance configuration.
*/
- container instance {
- presence "Present if the RIP protocol is enabled.";
+ list instance {
+ key "vrf";
description
"RIP routing instance.";
+ leaf vrf {
+ type string;
+ description
+ "VRF name.";
+ }
leaf allow-ecmp {
type boolean;
default "false";
@@ -293,83 +298,83 @@ module frr-ripd {
'(./receive = "2" and ./send = "2") or ' +
'(./receive = "1-2" and ./send = "2")';
}
- }
-
- /*
- * Operational data.
- */
- container state {
- config false;
- description
- "Operational data.";
- container neighbors {
+ /*
+ * Operational data.
+ */
+ container state {
+ config false;
description
- "Neighbor information.";
- list neighbor {
- key "address";
+ "Operational data.";
+
+ container neighbors {
description
- "A RIP neighbor.";
- leaf address {
- type inet:ipv4-address;
- description
- "IP address that a RIP neighbor is using as its
- source address.";
- }
- leaf last-update {
- type yang:date-and-time;
- description
- "The time when the most recent RIP update was
- received from this neighbor.";
- }
- leaf bad-packets-rcvd {
- type yang:counter32;
+ "Neighbor information.";
+ list neighbor {
+ key "address";
description
- "The number of RIP invalid packets received from
- this neighbor which were subsequently discarded
- for any reason (e.g. a version 0 packet, or an
- unknown command type).";
- }
- leaf bad-routes-rcvd {
- type yang:counter32;
- description
- "The number of routes received from this neighbor,
- in valid RIP packets, which were ignored for any
- reason (e.g. unknown address family, or invalid
- metric).";
+ "A RIP neighbor.";
+ leaf address {
+ type inet:ipv4-address;
+ description
+ "IP address that a RIP neighbor is using as its
+ source address.";
+ }
+ leaf last-update {
+ type yang:date-and-time;
+ description
+ "The time when the most recent RIP update was
+ received from this neighbor.";
+ }
+ leaf bad-packets-rcvd {
+ type yang:counter32;
+ description
+ "The number of RIP invalid packets received from
+ this neighbor which were subsequently discarded
+ for any reason (e.g. a version 0 packet, or an
+ unknown command type).";
+ }
+ leaf bad-routes-rcvd {
+ type yang:counter32;
+ description
+ "The number of routes received from this neighbor,
+ in valid RIP packets, which were ignored for any
+ reason (e.g. unknown address family, or invalid
+ metric).";
+ }
}
}
- }
- container routes {
- description
- "Route information.";
- list route {
- key "prefix";
+ container routes {
description
- "A RIP IPv4 route.";
- leaf prefix {
- type inet:ipv4-prefix;
- description
- "IP address (in the form A.B.C.D) and prefix length,
- separated by the slash (/) character. The range of
- values for the prefix-length is 0 to 32.";
- }
- leaf next-hop {
- type inet:ipv4-address;
+ "Route information.";
+ list route {
+ key "prefix";
description
- "Next hop IPv4 address.";
- }
- leaf interface {
- type string;
- description
- "The interface that the route uses.";
- }
- leaf metric {
- type uint8 {
- range "0..16";
+ "A RIP IPv4 route.";
+ leaf prefix {
+ type inet:ipv4-prefix;
+ description
+ "IP address (in the form A.B.C.D) and prefix length,
+ separated by the slash (/) character. The range of
+ values for the prefix-length is 0 to 32.";
+ }
+ leaf next-hop {
+ type inet:ipv4-address;
+ description
+ "Next hop IPv4 address.";
+ }
+ leaf interface {
+ type string;
+ description
+ "The interface that the route uses.";
+ }
+ leaf metric {
+ type uint8 {
+ range "0..16";
+ }
+ description
+ "Route metric.";
}
- description
- "Route metric.";
}
}
}
@@ -547,6 +552,19 @@ module frr-ripd {
description
"Clears RIP routes from the IP routing table and routes
redistributed into the RIP protocol.";
+
+ input {
+ leaf vrf {
+ type string;
+ description
+ "VRF name identifying a specific RIP instance.
+ This leaf is optional for the rpc.
+ If it is specified, the rpc will clear all routes in the
+ specified RIP instance;
+ if it is not specified, the rpc will clear all routes in
+ all RIP instances.";
+ }
+ }
}
/*
diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang
index 0cc5f18a5..b341b438a 100644
--- a/yang/frr-ripngd.yang
+++ b/yang/frr-ripngd.yang
@@ -33,13 +33,18 @@ module frr-ripngd {
container ripngd {
/*
- * Global configuration data
+ * Routing instance configuration.
*/
- container instance {
- presence "Present if the RIPng protocol is enabled.";
+ list instance {
+ key "vrf";
description
"RIPng routing instance.";
+ leaf vrf {
+ type string;
+ description
+ "VRF name.";
+ }
leaf allow-ecmp {
type boolean;
default "false";
@@ -194,82 +199,82 @@ module frr-ripngd {
"Interval at which RIPng updates are sent.";
}
}
- }
- /*
- * Operational data.
- */
- container state {
- config false;
- description
- "Operational data.";
-
- container neighbors {
+ /*
+ * Operational data.
+ */
+ container state {
+ config false;
description
- "Neighbor information.";
- list neighbor {
- key "address";
+ "Operational data.";
+
+ container neighbors {
description
- "A RIPng neighbor.";
- leaf address {
- type inet:ipv6-address;
+ "Neighbor information.";
+ list neighbor {
+ key "address";
description
- "IPv6 address that a RIPng neighbor is using as its
- source address.";
- }
- leaf last-update {
- type yang:date-and-time;
- description
- "The time when the most recent RIPng update was
- received from this neighbor.";
- }
- leaf bad-packets-rcvd {
- type yang:counter32;
- description
- "The number of RIPng invalid packets received from
- this neighbor which were subsequently discarded
- for any reason (e.g. a version 0 packet, or an
- unknown command type).";
- }
- leaf bad-routes-rcvd {
- type yang:counter32;
- description
- "The number of routes received from this neighbor,
- in valid RIPng packets, which were ignored for any
- reason (e.g. unknown address family, or invalid
- metric).";
+ "A RIPng neighbor.";
+ leaf address {
+ type inet:ipv6-address;
+ description
+ "IPv6 address that a RIPng neighbor is using as its
+ source address.";
+ }
+ leaf last-update {
+ type yang:date-and-time;
+ description
+ "The time when the most recent RIPng update was
+ received from this neighbor.";
+ }
+ leaf bad-packets-rcvd {
+ type yang:counter32;
+ description
+ "The number of RIPng invalid packets received from
+ this neighbor which were subsequently discarded
+ for any reason (e.g. a version 0 packet, or an
+ unknown command type).";
+ }
+ leaf bad-routes-rcvd {
+ type yang:counter32;
+ description
+ "The number of routes received from this neighbor,
+ in valid RIPng packets, which were ignored for any
+ reason (e.g. unknown address family, or invalid
+ metric).";
+ }
}
}
- }
- container routes {
- description
- "Route information.";
- list route {
- key "prefix";
+ container routes {
description
- "A RIPng IPv6 route.";
- leaf prefix {
- type inet:ipv6-prefix;
- description
- "IPv6 address and prefix length, in the format
- specified in RFC6991.";
- }
- leaf next-hop {
- type inet:ipv6-address;
+ "Route information.";
+ list route {
+ key "prefix";
description
- "Next hop IPv6 address.";
- }
- leaf interface {
- type string;
- description
- "The interface that the route uses.";
- }
- leaf metric {
- type uint8 {
- range "0..16";
+ "A RIPng IPv6 route.";
+ leaf prefix {
+ type inet:ipv6-prefix;
+ description
+ "IPv6 address and prefix length, in the format
+ specified in RFC6991.";
+ }
+ leaf next-hop {
+ type inet:ipv6-address;
+ description
+ "Next hop IPv6 address.";
+ }
+ leaf interface {
+ type string;
+ description
+ "The interface that the route uses.";
+ }
+ leaf metric {
+ type uint8 {
+ range "0..16";
+ }
+ description
+ "Route metric.";
}
- description
- "Route metric.";
}
}
}
@@ -317,5 +322,18 @@ module frr-ripngd {
description
"Clears RIPng routes from the IPv6 routing table and routes
redistributed into the RIPng protocol.";
+
+ input {
+ leaf vrf {
+ type string;
+ description
+ "VRF name identifying a specific RIPng instance.
+ This leaf is optional for the rpc.
+ If it is specified, the rpc will clear all routes in the
+ specified RIPng instance;
+ if it is not specified, the rpc will clear all routes in
+ all RIPng instances.";
+ }
+ }
}
}
diff --git a/yang/ietf/frr-ietf-translator.json b/yang/ietf/frr-ietf-translator.json
index 9855480b4..38a609982 100644
--- a/yang/ietf/frr-ietf-translator.json
+++ b/yang/ietf/frr-ietf-translator.json
@@ -22,7 +22,7 @@
"mappings": [
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']",
- "native": "/frr-ripd:ripd/instance"
+ "native": "/frr-ripd:ripd/instance[vrf='default']"
}
]
},
@@ -32,31 +32,31 @@
"mappings": [
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/default-metric",
- "native": "/frr-ripd:ripd/instance/default-metric"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/default-metric"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/distance",
- "native": "/frr-ripd:ripd/instance/distance/default"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/distance/default"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/originate-default-route/enabled",
- "native": "/frr-ripd:ripd/instance/default-information-originate"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/default-information-originate"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/update-interval",
- "native": "/frr-ripd:ripd/instance/timers/update-interval"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/timers/update-interval"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/holddown-interval",
- "native": "/frr-ripd:ripd/instance/timers/holddown-interval"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/timers/holddown-interval"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/flush-interval",
- "native": "/frr-ripd:ripd/instance/timers/flush-interval"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/timers/flush-interval"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']",
- "native": "/frr-ripd:ripd/instance/interface[.='KEY1']"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/interface[.='KEY1']"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']/split-horizon",
@@ -64,43 +64,43 @@
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']",
- "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/ipv4-address",
- "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/address"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/address"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/last-update",
- "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/last-update"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/last-update"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-packets-rcvd",
- "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-routes-rcvd",
- "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']",
- "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/ipv4-prefix",
- "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/prefix"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/prefix"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/next-hop",
- "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/next-hop"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/next-hop"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/interface",
- "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/interface"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/interface"
},
{
"custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/metric",
- "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/metric"
+ "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/metric"
},
{
"custom": "/ietf-rip:clear-rip-route",