summaryrefslogtreecommitdiffstats
path: root/ripd
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2019-04-05 01:24:14 +0200
committerGitHub <noreply@github.com>2019-04-05 01:24:14 +0200
commitf61f266a0e484d3ba78a644f36a3a4f7113cfc74 (patch)
tree728ed9d219c276bbe6e01200c58594b392555c13 /ripd
parentMerge pull request #3899 from ton31337/fix/remove_private_as_with_local_as (diff)
parentlib, ripd, ripngd: rename remaining delete northbound callbacks (diff)
downloadfrr-f61f266a0e484d3ba78a644f36a3a4f7113cfc74.tar.xz
frr-f61f266a0e484d3ba78a644f36a3a4f7113cfc74.zip
Merge pull request #3548 from opensourcerouting/rip-vrf
rip(ng)d: add VRF support
Diffstat (limited to 'ripd')
-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
13 files changed, 1356 insertions, 846 deletions
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;