This is the last step to make ripd ready for multi-instance support.
Remove the rip global variable and add a "rip" parameter to all
functions that need to know the RIP instance they are working
on. On some functions, retrieve the RIP instance from the interface
variable when it exists (this assumes interfaces can pertain to
one RIP instance at most, which is ok for VRF support).
In preparation for the next commits (VRF support), add a "vrd_id"
member to the rip structure, and use rip->vrf_id instead of
VRF_DEFAULT wherever possible.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
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"},
static void rip_interface_reset(struct rip_interface *);
/* Allocate new RIP's interface configuration. */
-static struct rip_interface *rip_interface_new(void)
+static struct rip_interface *rip_interface_new(struct interface *ifp)
{
+ struct vrf *vrf;
struct rip_interface *ri;
ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface));
+ vrf = vrf_lookup_by_id(ifp->vrf_id);
+ if (vrf)
+ ri->rip = vrf->info;
+
rip_interface_reset(ri);
return ri;
/* 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);
/* 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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) {
}
}
-void rip_interfaces_clean(void)
+void rip_interfaces_clean(struct rip *rip)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
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)
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;
/* 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,
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;
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);
}
* 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;
}
/* 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;
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->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;
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;
}
}
/* 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;
}
/* 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,
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;
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
vector_unset(rip->enable_interface, index);
- rip_enable_apply_all(); /* TODOVJ */
+ rip_enable_apply_all(rip); /* TODOVJ */
return NB_OK;
}
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);
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;
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);
}
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
}
/* Apply network configuration to all interface. */
-void rip_enable_apply_all()
+static void rip_enable_apply_all(struct rip *rip)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id);
struct interface *ifp;
/* Check each interface. */
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;
}
/* 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;
}
/* 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;
}
/* Clear all network and neighbor configuration. */
-void rip_clean_network()
+void rip_clean_network(struct rip *rip)
{
unsigned int i;
char *str;
}
/* 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;
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);
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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, 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'.
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
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
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;
XFREE(MTYPE_RIP_INTERFACE_STRING, str);
vector_slot(rip->passive_nondefault, i) = NULL;
}
- rip_passive_interface_apply_all();
+ rip_passive_interface_apply_all(rip);
}
/* Write rip configuration of each interface. */
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;
/* Called when interface structure allocated. */
static int rip_interface_new_hook(struct interface *ifp)
{
- ifp->info = rip_interface_new();
+ ifp->info = rip_interface_new(ifp);
return 0;
}
/* SIGINT handler. */
static void sigint(void)
{
+ struct vrf *vrf;
+
zlog_notice("Terminating on signal");
- if (rip)
- rip_clean();
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ struct rip *rip;
+
+ rip = vrf->info;
+ if (rip)
+ rip_clean(rip);
+ }
rip_zclient_stop();
frr_fini();
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
+ struct vrf *vrf;
int socket;
switch (event) {
close(socket);
break;
case NB_EV_APPLY:
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
socket = resource->fd;
- rip_create(socket);
+ rip = rip_create(vrf, socket);
+ yang_dnode_set_entry(dnode, rip);
break;
}
static int ripd_instance_delete(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;
}
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;
}
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));
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;
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 (); */
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;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct rip *rip;
struct prefix_ipv4 prefix;
struct route_node *rn;
apply_mask_ipv4(&prefix);
/* Get RIP distance node. */
+ 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);
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)
{
+ 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);
}
/*
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)
{
+ 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);
}
/*
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)
{
+ 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);
}
/*
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;
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;
}
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)
{
+ 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);
}
/*
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)
{
+ 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_redistribute_delete(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_redistribute_conf_delete(rip, type);
return NB_OK;
}
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);
+
+ rip_redistribute_conf_update(rip, type);
}
/*
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);
ripd_instance_redistribute_route_map_delete(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);
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);
ripd_instance_redistribute_metric_delete(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;
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)
{
+ 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;
}
*/
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);
}
/*
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;
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;
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;
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;
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;
ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
const void *list_entry)
{
+ struct rip *rip;
struct listnode *node;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (rip == NULL)
return NULL;
ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
const struct yang_list_keys *keys)
{
+ struct rip *rip;
struct in_addr address;
struct rip_peer *peer;
struct listnode *node;
yang_str2ipv4(keys->key[0], &address);
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (rip == NULL)
return NULL;
ripd_state_routes_route_get_next(const void *parent_list_entry,
const void *list_entry)
{
+ struct rip *rip;
struct route_node *rn;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (rip == NULL)
return NULL;
ripd_state_routes_route_lookup_entry(const void *parent_list_entry,
const struct yang_list_keys *keys)
{
+ struct rip *rip;
struct prefix prefix;
struct route_node *rn;
yang_str2ipv4p(keys->key[0], &prefix);
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
+ if (rip == NULL)
+ return NULL;
+
rn = route_node_lookup(rip->table, &prefix);
if (!rn || !rn->info)
return NULL;
static int clear_rip_route_rpc(const char *xpath, const struct list *input,
struct list *output)
{
+ struct rip *rip;
struct route_node *rp;
struct rip_info *rinfo;
struct list *list;
struct listnode *listnode;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (!rip)
return NB_OK;
continue;
if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
- rip_zebra_ipv4_delete(rp);
+ rip_zebra_ipv4_delete(rip, rp);
break;
}
#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);
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))
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;
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));
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));
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));
}
/* 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));
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;
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;
struct rip_peer *peer;
peer = THREAD_ARG(t);
- listnode_delete(rip->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(rip->peer_list, peer);
}
return peer;
}
-void rip_peer_update(struct sockaddr_in *from, uint8_t version)
+void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version)
{
struct rip_peer *peer;
- 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++;
}
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;
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;
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;
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)])
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
return peer;
}
}
- peer = rip_peer_lookup_next(addr);
+ peer = rip_peer_lookup_next(rip, addr);
if (!peer)
return NULL;
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;
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;
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;
int count = 0;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = rip->vrf_id;
api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST;
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
- api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->vrf_id = rip->vrf_id;
api_nh->gate = rinfo->nh.gate;
api_nh->type = NEXTHOP_TYPE_IPV4;
if (cmd == ZEBRA_ROUTE_ADD)
}
/* 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;
/* 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_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_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 vrf_bitmap_check(zclient->redist[AFI_IP][type], rip->vrf_id);
}
-void rip_redistribute_clean(void)
+void rip_redistribute_clean(struct rip *rip)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], VRF_DEFAULT))
+ if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], rip->vrf_id))
continue;
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
zclient, AFI_IP, i, 0,
- VRF_DEFAULT);
+ rip->vrf_id);
- vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT);
+ vrf_bitmap_unset(zclient->redist[AFI_IP][i], rip->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->vrf_id))
continue;
vty_out(vty, " %s", zebra_route_string(i));
/* UDP receive buffer size */
#define RIP_UDP_RCV_BUF 41600
-/* RIP Structure. */
-struct rip *rip = NULL;
-
/* Prototypes. */
static void rip_output_process(struct connected *, struct sockaddr_in *, int,
uint8_t);
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)
{
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;
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. */
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;
}
/* 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;
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));
/* 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))
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;
}
* 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;
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 {
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. */
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;
}
/* 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);
}
}
}
/* 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,
}
/* 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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id);
struct interface *ifp;
struct listnode *cnode;
struct connected *ifc;
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;
/* 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;
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));
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;
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;
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.
*/
|| ((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)
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);
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;
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;
}
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_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;
}
; /* 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;
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;
}
/* - 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;
}
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;
}
}
if (!if_lookup_address((void *)&rte->nexthop, AF_INET,
- VRF_DEFAULT)) {
+ rip->vrf_id)) {
struct route_node *rn;
struct rip_info *rinfo;
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;
}
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;
assert(ifc != NULL);
+ ri = ifc->ifp->info;
+ rip = ri->rip;
if (IS_RIP_DEBUG_PACKET) {
#define ADDRESS_SIZE 20
}
/* 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;
}
}
- (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;
inet_ntoa(p->prefix),
p->prefixlen,
ifindex2ifname(ifindex,
- VRF_DEFAULT));
+ rip->vrf_id));
- rip_event(RIP_TRIGGERED_UPDATE, 0);
+ rip_event(rip, RIP_TRIGGERED_UPDATE, 0);
}
}
route_unlock_node(rp);
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;
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;
/* 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;
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));
}
/* 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");
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_id);
if (ifc)
ifp = ifc->ifp;
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;
}
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;
}
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;
}
/* 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;
}
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;
}
"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;
}
"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) {
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;
}
"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;
}
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;
}
}
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;
}
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;
ifc->ifp->name, ifc->ifp->ifindex);
}
+ /* Get RIP interface. */
+ ri = ifc->ifp->info;
+ rip = ri->rip;
+
/* Set output stream. */
s = rip->obuf;
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)
}
/* 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 vrf *vrf = vrf_lookup_by_id(rip->vrf_id);
struct listnode *ifnode, *ifnnode;
struct connected *connected;
struct interface *ifp;
p = &rp->p;
connected = if_lookup_address(&p->u.prefix4, AF_INET,
- VRF_DEFAULT);
+ rip->vrf_id);
if (!connected) {
zlog_warn(
"Neighbor %s doesn't have connected interface!",
/* RIP's periodical timer. */
static int rip_update(struct thread *t)
{
+ struct rip *rip = THREAD_ARG(t);
+
/* Clear timer pointer. */
rip->t_update = NULL;
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. */
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;
/* 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;
/* Execute triggered update. */
static int rip_triggered_update(struct thread *t)
{
+ struct rip *rip = THREAD_ARG(t);
int interval;
/* Clear thred pointer. */
/* 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
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;
p->prefixlen,
ifindex2ifname(
rinfo->nh.ifindex,
- VRF_DEFAULT));
+ rip->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;
+}
+
/* Create new RIP instance and set it to global variable. */
-int rip_create(int socket)
+struct rip *rip_create(struct vrf *vrf, int socket)
{
+ struct rip *rip;
+ struct interface *ifp;
+
rip = XCALLOC(MTYPE_RIP, sizeof(struct rip));
/* Set initial value. */
/* 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->sock = socket;
/* Create read and timer thread. */
- rip_event(RIP_READ, rip->sock);
- rip_event(RIP_UPDATE_EVENT, 1);
+ rip_event(rip, RIP_READ, rip->sock);
+ rip_event(rip, RIP_UPDATE_EVENT, 1);
- return 0;
+ /* Link RIP instance to VRF. */
+ rip->vrf_id = vrf->vrf_id;
+ vrf->info = rip;
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct rip_interface *ri;
+
+ ri = ifp->info;
+ ri->rip = rip;
+ }
+
+ return rip;
}
/* Sned RIP request to the destination. */
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;
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:
}
/* 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;
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;
}
/* 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));
}
/* 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);
}
}
IP_STR
"Show RIP routes\n")
{
+ struct rip *rip;
struct route_node *np;
struct rip_info *rinfo = NULL;
struct list *list = NULL;
struct listnode *listnode = NULL;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (!rip)
return CMD_SUCCESS;
"Show RIP routes\n"
"IP routing protocol process parameters and statistics\n")
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct rip *rip;
+ struct vrf *vrf;
struct interface *ifp;
struct rip_interface *ri;
extern const struct message ri_version_msg[];
const char *send_version;
const char *receive_version;
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
if (!rip)
return CMD_SUCCESS;
/* 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,",
vty_out(vty, " Interface Send Recv Key-chain\n");
+ vrf = vrf_lookup_by_id(rip->vrf_id);
FOR_ALL_INTERFACES (vrf, ifp) {
ri = ifp->info;
}
vty_out(vty, " Routing for Networks:\n");
- rip_show_network_config(vty);
+ rip_show_network_config(vty, rip);
{
int found_passive = 0;
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;
}
dnode = yang_dnode_get(running_config->dnode,
"/frr-ripd:ripd/instance");
if (dnode) {
+ struct rip *rip;
+
write++;
nb_cli_show_dnode_cmds(vty, dnode, false);
- /* Distribute configuration. */
- write += config_write_distribute(vty,
- rip->distribute_ctx);
+ rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
+ if (rip) {
+ /* Distribute configuration. */
+ write += config_write_distribute(vty,
+ rip->distribute_ctx);
- /* Interface routemap configuration */
- write += config_write_if_rmap(vty);
+ /* Interface routemap configuration */
+ write += config_write_if_rmap(vty);
+ }
}
return write;
}
void rip_distribute_update_interface(struct interface *ifp)
{
+ struct rip_interface *ri = ifp->info;
+ struct rip *rip = ri->rip;
struct distribute *dist;
if (!rip)
}
/* Delete all added rip route. */
-void rip_clean(void)
+void rip_clean(struct rip *rip)
{
+ struct vrf *vrf;
+ struct interface *ifp;
struct route_node *rp;
/* Clear RIP routes */
rinfo = listgetdata(listhead(list));
if (rip_route_rte(rinfo))
- rip_zebra_ipv4_delete(rp);
+ rip_zebra_ipv4_delete(rip, rp);
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
RIP_TIMER_OFF(rinfo->t_timeout);
list_delete(&rip->peer_list);
distribute_list_delete(&rip->distribute_ctx);
- rip_clean_network();
- rip_passive_nondefault_clean();
+ 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_interfaces_clean(rip);
route_table_finish(rip->distance_table);
- rip_redistribute_clean();
+ rip_redistribute_clean(rip);
+
+ vrf = vrf_lookup_by_id(rip->vrf_id);
+ vrf->info = NULL;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct rip_interface *ri;
+
+ ri = ifp->info;
+ ri->rip = NULL;
+ }
XFREE(MTYPE_RIP, rip);
}
rip_if_rmap_update(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);
- }
+ for (int 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);
}
}
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);
}
/* Allocate new rip structure and set default value. */
/* RIP structure. */
struct rip {
+ /* VRF ID. */
+ vrf_id_t vrf_id;
+
/* RIP socket. */
int sock;
/* 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;
/* RIP peer information. */
struct rip_peer {
+ /* Parent routing instance. */
+ struct rip *rip;
+
/* Peer address. */
struct in_addr addr;
#define RIP_OFFSET_LIST_MAX 2
struct rip_offset_list {
+ /* Parent routing instance. */
+ struct rip *rip;
+
char *ifname;
struct {
/* 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_route_map_init(void);
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_create(struct vrf *vrf, int socket);
extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
struct connected *);
-extern int rip_neighbor_lookup(struct sockaddr_in *);
-extern int rip_neighbor_add(struct prefix_ipv4 *p);
-extern int rip_neighbor_delete(struct prefix_ipv4 *p);
+extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from);
+extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p);
+extern int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p);
-extern int rip_enable_network_add(struct prefix *p);
-extern int rip_enable_network_delete(struct prefix *p);
-extern int rip_enable_if_add(const char *ifname);
-extern int rip_enable_if_delete(const char *ifname);
+extern int rip_enable_network_add(struct rip *rip, struct prefix *p);
+extern int rip_enable_network_delete(struct rip *rip, struct prefix *p);
+extern int rip_enable_if_add(struct rip *rip, const char *ifname);
+extern int rip_enable_if_delete(struct rip *rip, const char *ifname);
-extern void rip_event(enum rip_event, int);
-extern void rip_ecmp_disable(void);
+extern void rip_event(struct rip *rip, enum rip_event event, int sock);
+extern void rip_ecmp_disable(struct rip *rip);
extern int rip_create_socket(void);
-extern int rip_redistribute_check(int);
-extern void rip_redistribute_conf_update(int type);
-extern void rip_redistribute_conf_delete(int type);
-extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
- struct nexthop *nh, unsigned int metric,
- unsigned char distance, route_tag_t tag);
-extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t);
-extern void rip_redistribute_withdraw(int);
-extern void rip_zebra_ipv4_add(struct route_node *);
-extern void rip_zebra_ipv4_delete(struct route_node *);
+extern int rip_redistribute_check(struct rip *rip, int type);
+extern void rip_redistribute_conf_update(struct rip *rip, int type);
+extern void rip_redistribute_conf_delete(struct rip *rip, int type);
+extern void rip_redistribute_add(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, struct nexthop *nh,
+ unsigned int metric, unsigned char distance,
+ route_tag_t tag);
+extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, ifindex_t ifindex);
+extern void rip_redistribute_withdraw(struct rip *rip, int type);
+extern void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp);
+extern void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp);
extern void rip_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *);
extern void rip_if_rmap_update_interface(struct interface *);
-extern int rip_show_network_config(struct vty *);
-extern void rip_show_redistribute_config(struct vty *);
-
-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_clean(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 *,
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;
/* Master thread strucutre. */