/* Static utility function. */
static void ripng_enable_apply(struct interface *);
static void ripng_passive_interface_apply(struct interface *);
-static int ripng_enable_if_lookup(const char *);
+static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname);
static int ripng_enable_network_lookup2(struct connected *);
-static void ripng_enable_apply_all(void);
+static void ripng_enable_apply_all(struct ripng *ripng);
/* Join to the all rip routers multicast group. */
-static int ripng_multicast_join(struct interface *ifp)
+static int ripng_multicast_join(struct interface *ifp, int sock)
{
int ret;
struct ipv6_mreq mreq;
*/
frr_elevate_privs(&ripngd_privs) {
- ret = setsockopt(ripng->sock, IPPROTO_IPV6,
- IPV6_JOIN_GROUP,
+ ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char *)&mreq, sizeof(mreq));
save_errno = errno;
}
/* Leave from the all rip routers multicast group. */
-static int ripng_multicast_leave(struct interface *ifp)
+static int ripng_multicast_leave(struct interface *ifp, int sock)
{
int ret;
struct ipv6_mreq mreq;
inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = ifp->ifindex;
- ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
(char *)&mreq, sizeof(mreq));
if (ret < 0)
zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s\n",
struct agg_node *rp;
struct ripng_info *rinfo;
struct ripng_interface *ri;
+ struct ripng *ripng;
struct list *list = NULL;
struct listnode *listnode = NULL, *nextnode = NULL;
+ ri = ifp->info;
+ ripng = ri->ripng;
+
if (ripng)
for (rp = agg_route_top(ripng->table); rp;
rp = agg_route_next(rp))
for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
rinfo))
if (rinfo->ifindex == ifp->ifindex)
- ripng_ecmp_delete(rinfo);
+ ripng_ecmp_delete(ripng, rinfo);
- ri = ifp->info;
if (ri->running) {
if (IS_RIPNG_DEBUG_EVENT)
zlog_debug("turn off %s", ifp->name);
/* Leave from multicast group. */
- ripng_multicast_leave(ifp);
+ ripng_multicast_leave(ifp, ripng->sock);
ri->running = 0;
}
return 0;
}
-void ripng_interface_clean(void)
+void ripng_interface_clean(struct ripng *ripng)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
struct interface *ifp;
struct ripng_interface *ri;
static void ripng_apply_address_add(struct connected *ifc)
{
+ struct ripng_interface *ri = ifc->ifp->info;
+ struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
/* Check if this interface is RIP enabled or not
or Check if this address's prefix is RIP enabled */
- if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0)
+ if ((ripng_enable_if_lookup(ripng, ifc->ifp->name) >= 0)
|| (ripng_enable_network_lookup2(ifc) >= 0))
- ripng_redistribute_add(ZEBRA_ROUTE_CONNECT,
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
ifc->ifp->ifindex, NULL, 0);
}
static void ripng_apply_address_del(struct connected *ifc)
{
+ struct ripng_interface *ri = ifc->ifp->info;
+ struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
address.prefixlen = p->prefixlen;
apply_mask_ipv6(&address);
- ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
- &address, ifc->ifp->ifindex);
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
+ RIPNG_ROUTE_INTERFACE, &address,
+ ifc->ifp->ifindex);
}
int ripng_interface_address_delete(int command, struct zclient *zclient,
* is within the ripng->enable_network table. */
static int ripng_enable_network_lookup_if(struct interface *ifp)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct listnode *node;
struct connected *connected;
struct prefix_ipv6 address;
/* Check wether connected is within the ripng->enable_network table. */
static int ripng_enable_network_lookup2(struct connected *connected)
{
+ struct ripng_interface *ri = connected->ifp->info;
+ struct ripng *ripng = ri->ripng;
struct prefix_ipv6 address;
struct prefix *p;
}
/* Add RIPng enable network. */
-int ripng_enable_network_add(struct prefix *p)
+int ripng_enable_network_add(struct ripng *ripng, struct prefix *p)
{
struct agg_node *node;
node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */
- ripng_enable_apply_all();
+ ripng_enable_apply_all(ripng);
return NB_OK;
}
/* Delete RIPng enable network. */
-int ripng_enable_network_delete(struct prefix *p)
+int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p)
{
struct agg_node *node;
}
/* Lookup function. */
-static int ripng_enable_if_lookup(const char *ifname)
+static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname)
{
unsigned int i;
char *str;
return -1;
}
-int ripng_enable_if_add(const char *ifname)
+int ripng_enable_if_add(struct ripng *ripng, const char *ifname)
{
int ret;
- ret = ripng_enable_if_lookup(ifname);
+ ret = ripng_enable_if_lookup(ripng, ifname);
if (ret >= 0)
return NB_ERR_INCONSISTENCY;
vector_set(ripng->enable_if, strdup(ifname));
- ripng_enable_apply_all();
+ ripng_enable_apply_all(ripng);
return NB_OK;
}
-int ripng_enable_if_delete(const char *ifname)
+int ripng_enable_if_delete(struct ripng *ripng, const char *ifname)
{
int index;
char *str;
- index = ripng_enable_if_lookup(ifname);
+ index = ripng_enable_if_lookup(ripng, ifname);
if (index < 0)
return NB_ERR_INCONSISTENCY;
free(str);
vector_unset(ripng->enable_if, index);
- ripng_enable_apply_all();
+ ripng_enable_apply_all(ripng);
return NB_OK;
}
ri->t_wakeup = NULL;
/* Join to multicast group. */
- if (ripng_multicast_join(ifp) < 0) {
+ if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"multicast join failed, interface %s not running",
ifp->name);
static void ripng_connect_set(struct interface *ifp, int set)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct listnode *node, *nnode;
struct connected *connected;
struct prefix_ipv6 address;
if (set) {
/* Check once more wether this prefix is within a
* "network IF_OR_PREF" one */
- if ((ripng_enable_if_lookup(connected->ifp->name) >= 0)
+ if ((ripng_enable_if_lookup(ripng, connected->ifp->name)
+ >= 0)
|| (ripng_enable_network_lookup2(connected) >= 0))
ripng_redistribute_add(
- ZEBRA_ROUTE_CONNECT,
+ ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_INTERFACE, &address,
connected->ifp->ifindex, NULL, 0);
} else {
- ripng_redistribute_delete(
- ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
- &address, connected->ifp->ifindex);
- if (ripng_redistribute_check(ZEBRA_ROUTE_CONNECT))
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT,
+ RIPNG_ROUTE_INTERFACE,
+ &address,
+ connected->ifp->ifindex);
+ if (ripng_redistribute_check(ripng,
+ ZEBRA_ROUTE_CONNECT))
ripng_redistribute_add(
- ZEBRA_ROUTE_CONNECT,
+ ripng, ZEBRA_ROUTE_CONNECT,
RIPNG_ROUTE_REDISTRIBUTE, &address,
connected->ifp->ifindex, NULL, 0);
}
ri->enable_network = 0;
/* Check interface name configuration. */
- ret = ripng_enable_if_lookup(ifp->name);
+ ret = ripng_enable_if_lookup(ri->ripng, ifp->name);
if (ret >= 0)
ri->enable_interface = 1;
else
}
/* Set distribute list to all interfaces. */
-static void ripng_enable_apply_all(void)
+static void ripng_enable_apply_all(struct ripng *ripng)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
}
/* Clear all network and neighbor configuration */
-void ripng_clean_network()
+void ripng_clean_network(struct ripng *ripng)
{
unsigned int i;
char *str;
}
/* Utility function for looking up passive interface settings. */
-static int ripng_passive_interface_lookup(const char *ifname)
+static int ripng_passive_interface_lookup(struct ripng *ripng,
+ const char *ifname)
{
unsigned int i;
char *str;
- if (!ripng)
- return -1;
-
for (i = 0; i < vector_active(ripng->passive_interface); i++)
if ((str = vector_slot(ripng->passive_interface, i)) != NULL)
if (strcmp(str, ifname) == 0)
{
int ret;
struct ripng_interface *ri;
+ struct ripng *ripng;
ri = ifp->info;
+ ripng = ri->ripng;
+ if (!ripng)
+ return;
- ret = ripng_passive_interface_lookup(ifp->name);
+ ret = ripng_passive_interface_lookup(ripng, ifp->name);
if (ret < 0)
ri->passive = 0;
else
ri->passive = 1;
}
-static void ripng_passive_interface_apply_all(void)
+static void ripng_passive_interface_apply_all(struct ripng *ripng)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
}
/* Passive interface. */
-int ripng_passive_interface_set(const char *ifname)
+int ripng_passive_interface_set(struct ripng *ripng, const char *ifname)
{
- if (ripng_passive_interface_lookup(ifname) >= 0)
+ if (ripng_passive_interface_lookup(ripng, ifname) >= 0)
return NB_ERR_INCONSISTENCY;
vector_set(ripng->passive_interface, strdup(ifname));
- ripng_passive_interface_apply_all();
+ ripng_passive_interface_apply_all(ripng);
return NB_OK;
}
-int ripng_passive_interface_unset(const char *ifname)
+int ripng_passive_interface_unset(struct ripng *ripng, const char *ifname)
{
int i;
char *str;
- i = ripng_passive_interface_lookup(ifname);
+ i = ripng_passive_interface_lookup(ripng, ifname);
if (i < 0)
return NB_ERR_INCONSISTENCY;
free(str);
vector_unset(ripng->passive_interface, i);
- ripng_passive_interface_apply_all();
+ ripng_passive_interface_apply_all(ripng);
return NB_OK;
}
/* Free all configured RIP passive-interface settings. */
-void ripng_passive_interface_clean(void)
+void ripng_passive_interface_clean(struct ripng *ripng)
{
unsigned int i;
char *str;
free(str);
vector_slot(ripng->passive_interface, i) = NULL;
}
- ripng_passive_interface_apply_all();
+ ripng_passive_interface_apply_all(ripng);
}
/* Write RIPng enable network and interface to the vty. */
-int ripng_network_write(struct vty *vty)
+int ripng_network_write(struct vty *vty, struct ripng *ripng)
{
unsigned int i;
const char *ifname;
return 0;
}
-static struct ripng_interface *ri_new(void)
+static struct ripng_interface *ri_new(struct interface *ifp)
{
+ struct vrf *vrf;
struct ripng_interface *ri;
+
ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface));
+ vrf = vrf_lookup_by_id(ifp->vrf_id);
+ if (vrf)
+ ri->ripng = vrf->info;
+
/* Set default split-horizon behavior. If the interface is Frame
Relay or SMDS is enabled, the default value for split-horizon is
off. But currently Zebra does detect Frame Relay or SMDS
static int ripng_if_new_hook(struct interface *ifp)
{
- ifp->info = ri_new();
+ ifp->info = ri_new(ifp);
return 0;
}
/* SIGINT handler. */
static void sigint(void)
{
+ struct vrf *vrf;
+
zlog_notice("Terminating on signal");
- if (ripng)
- ripng_clean();
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ struct ripng *ripng;
+
+ ripng = vrf->info;
+ if (ripng)
+ ripng_clean(ripng);
+ }
ripng_zebra_stop();
frr_fini();
void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
struct sockaddr_in6 *to)
{
-
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
struct ripng_rte_data *data;
struct listnode *node, *nnode;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+ struct vrf *vrf;
int socket;
switch (event) {
close(socket);
break;
case NB_EV_APPLY:
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
socket = resource->fd;
- ripng_create(socket);
+ ripng = ripng_create(vrf, socket);
+ yang_dnode_set_entry(dnode, ripng);
break;
}
static int ripngd_instance_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
- ripng_clean();
+ ripng = yang_dnode_get_entry(dnode, true);
+ ripng_clean(ripng);
return NB_OK;
}
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
if (!ripng->ecmp)
- ripng_ecmp_disable();
+ ripng_ecmp_disable(ripng);
return NB_OK;
}
enum nb_event event, const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
bool default_information;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
default_information = yang_dnode_get_bool(dnode, NULL);
+
str2prefix_ipv6("::/0", &p);
if (default_information) {
- ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
- &p, 0, NULL, 0);
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
+ RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
} else {
- ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG,
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
RIPNG_ROUTE_DEFAULT, &p, 0);
}
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
return NB_OK;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
struct prefix p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6((struct prefix_ipv6 *)&p);
- return ripng_enable_network_add(&p);
+ return ripng_enable_network_add(ripng, &p);
}
static int ripngd_instance_network_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
struct prefix p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6((struct prefix_ipv6 *)&p);
- return ripng_enable_network_delete(&p);
+ return ripng_enable_network_delete(ripng, &p);
}
/*
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return ripng_enable_if_add(ifname);
+ return ripng_enable_if_add(ripng, ifname);
}
static int ripngd_instance_interface_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return ripng_enable_if_delete(ifname);
+ return ripng_enable_if_delete(ripng, ifname);
}
/*
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
const char *ifname;
struct ripng_offset_list *offset;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, "./interface");
- offset = ripng_offset_list_new(ifname);
+ offset = ripng_offset_list_new(ripng, ifname);
yang_dnode_set_entry(dnode, offset);
return NB_OK;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return ripng_passive_interface_set(ifname);
+ return ripng_passive_interface_set(ripng, ifname);
}
static int
ripngd_instance_passive_interface_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
const char *ifname;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ifname = yang_dnode_get_string(dnode, NULL);
- return ripng_passive_interface_unset(ifname);
+ return ripng_passive_interface_unset(ripng, ifname);
}
/*
static int ripngd_instance_redistribute_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol");
- ripng_redistribute_conf_delete(type);
+ ripng_redistribute_conf_delete(ripng, type);
return NB_OK;
}
static void
ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
{
+ struct ripng *ripng;
int type;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "./protocol");
- ripng_redistribute_conf_update(type);
+
+ ripng_redistribute_conf_update(ripng, type);
}
/*
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
int type;
const char *rmap_name;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
rmap_name = yang_dnode_get_string(dnode, NULL);
ripngd_instance_redistribute_route_map_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
free(ripng->route_map[type].name);
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
int type;
uint8_t metric;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
metric = yang_dnode_get_uint8(dnode, NULL);
ripngd_instance_redistribute_metric_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
int type;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
type = yang_dnode_get_enum(dnode, "../protocol");
ripng->route_map[type].metric_config = false;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0,
- NULL, 0);
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
+ 0, NULL, 0);
return NB_OK;
}
static int ripngd_instance_static_route_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
+ &p, 0);
return NB_OK;
}
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_aggregate_add((struct prefix *)&p);
+ ripng_aggregate_add(ripng, (struct prefix *)&p);
return NB_OK;
}
ripngd_instance_aggregate_address_delete(enum nb_event event,
const struct lyd_node *dnode)
{
+ struct ripng *ripng;
struct prefix_ipv6 p;
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
yang_dnode_get_ipv6p(&p, dnode, NULL);
apply_mask_ipv6(&p);
- ripng_aggregate_delete((struct prefix *)&p);
+ ripng_aggregate_delete(ripng, (struct prefix *)&p);
return NB_OK;
}
*/
static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
{
+ struct ripng *ripng;
+
+ ripng = yang_dnode_get_entry(dnode, true);
+
/* Reset update timer thread. */
- ripng_event(RIPNG_UPDATE_EVENT, 0);
+ ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
}
/*
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK;
const struct lyd_node *dnode,
union nb_resource *resource)
{
+ struct ripng *ripng;
+
if (event != NB_EV_APPLY)
return NB_OK;
+ ripng = yang_dnode_get_entry(dnode, true);
ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
return NB_OK;
ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
const void *list_entry)
{
+ struct ripng *ripng;
struct listnode *node;
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
if (!ripng)
return NULL;
ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
const struct yang_list_keys *keys)
{
+ struct ripng *ripng;
struct in6_addr address;
struct ripng_peer *peer;
struct listnode *node;
yang_str2ipv6(keys->key[0], &address);
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
if (!ripng)
return NULL;
ripngd_state_routes_route_get_next(const void *parent_list_entry,
const void *list_entry)
{
+ struct ripng *ripng;
struct agg_node *rn;
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
if (ripng == NULL)
return NULL;
ripngd_state_routes_route_lookup_entry(const void *parent_list_entry,
const struct yang_list_keys *keys)
{
+ struct ripng *ripng;
struct prefix prefix;
struct agg_node *rn;
yang_str2ipv6p(keys->key[0], &prefix);
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
+ if (!ripng)
+ return NULL;
+
rn = agg_node_lookup(ripng->table, &prefix);
if (!rn || !rn->info)
return NULL;
static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
struct list *output)
{
+ struct ripng *ripng;
struct agg_node *rp;
struct ripng_info *rinfo;
struct list *list;
struct listnode *listnode;
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
if (!ripng)
return NB_OK;
continue;
if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
break;
}
#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
-struct ripng_offset_list *ripng_offset_list_new(const char *ifname)
+struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
+ const char *ifname)
{
struct ripng_offset_list *new;
new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
sizeof(struct ripng_offset_list));
+ new->ripng = ripng;
new->ifname = strdup(ifname);
listnode_add_sort(ripng->offset_list_master, new);
void ripng_offset_list_del(struct ripng_offset_list *offset)
{
- listnode_delete(ripng->offset_list_master, offset);
+ listnode_delete(offset->ripng->offset_list_master, offset);
if (OFFSET_LIST_IN_NAME(offset))
free(OFFSET_LIST_IN_NAME(offset));
if (OFFSET_LIST_OUT_NAME(offset))
XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
}
-struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
+struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
+ const char *ifname)
{
struct ripng_offset_list *offset;
struct listnode *node, *nnode;
}
/* If metric is modifed return 1. */
-int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
- uint8_t *metric)
+int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric)
{
struct ripng_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
- offset = ripng_offset_list_lookup(ifp->name);
+ offset = ripng_offset_list_lookup(ripng, ifp->name);
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
return 0;
}
/* Look up offset-list without interface name. */
- offset = ripng_offset_list_lookup("*");
+ offset = ripng_offset_list_lookup(ripng, "*");
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
}
/* If metric is modifed return 1. */
-int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
- uint8_t *metric)
+int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric)
{
struct ripng_offset_list *offset;
struct access_list *alist;
/* Look up offset-list with interface name. */
- offset = ripng_offset_list_lookup(ifp->name);
+ offset = ripng_offset_list_lookup(ripng, ifp->name);
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
}
/* Look up offset-list without interface name. */
- offset = ripng_offset_list_lookup("*");
+ offset = ripng_offset_list_lookup(ripng, "*");
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
XFREE(MTYPE_RIPNG_PEER, peer);
}
-struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr)
+struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
return NULL;
}
-struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *addr)
+struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
+ struct in6_addr *addr)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
struct ripng_peer *peer;
peer = THREAD_ARG(t);
- listnode_delete(ripng->peer_list, peer);
+ listnode_delete(peer->ripng->peer_list, peer);
ripng_peer_free(peer);
return 0;
}
/* Get RIPng peer. At the same time update timeout thread. */
-static struct ripng_peer *ripng_peer_get(struct in6_addr *addr)
+static struct ripng_peer *ripng_peer_get(struct ripng *ripng,
+ struct in6_addr *addr)
{
struct ripng_peer *peer;
- peer = ripng_peer_lookup(addr);
+ peer = ripng_peer_lookup(ripng, addr);
if (peer) {
if (peer->t_timeout)
thread_cancel(peer->t_timeout);
} else {
peer = ripng_peer_new();
- peer->addr = *addr; /* XXX */
+ peer->ripng = ripng;
+ peer->addr = *addr;
listnode_add_sort(ripng->peer_list, peer);
}
return peer;
}
-void ripng_peer_update(struct sockaddr_in6 *from, uint8_t version)
+void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
+ uint8_t version)
{
struct ripng_peer *peer;
- peer = ripng_peer_get(&from->sin6_addr);
+ peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->version = version;
}
-void ripng_peer_bad_route(struct sockaddr_in6 *from)
+void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from)
{
struct ripng_peer *peer;
- peer = ripng_peer_get(&from->sin6_addr);
+ peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badroutes++;
}
-void ripng_peer_bad_packet(struct sockaddr_in6 *from)
+void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from)
{
struct ripng_peer *peer;
- peer = ripng_peer_get(&from->sin6_addr);
+ peer = ripng_peer_get(ripng, &from->sin6_addr);
peer->recv_badpackets++;
}
return buf;
}
-void ripng_peer_display(struct vty *vty)
+void ripng_peer_display(struct vty *vty, struct ripng *ripng)
{
struct ripng_peer *peer;
struct listnode *node, *nnode;
}
/* RIPng routes treatment. */
-int ripng_aggregate_add(struct prefix *p)
+int ripng_aggregate_add(struct ripng *ripng, struct prefix *p)
{
struct agg_node *top;
struct agg_node *rp;
}
/* Delete RIPng static route. */
-int ripng_aggregate_delete(struct prefix *p)
+int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p)
{
struct agg_node *top;
struct agg_node *rp;
struct ripng_info *rinfo);
extern void ripng_aggregate_decrement_list(struct agg_node *rp,
struct list *list);
-extern int ripng_aggregate_add(struct prefix *p);
-extern int ripng_aggregate_delete(struct prefix *p);
+extern int ripng_aggregate_add(struct ripng *ripng, struct prefix *p);
+extern int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p);
extern void ripng_aggregate_free(struct ripng_aggregate *aggregate);
#endif /* _ZEBRA_RIPNG_ROUTE_H */
struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */
-static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
+static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
+ uint8_t cmd)
{
struct list *list = (struct list *)rp->info;
struct zapi_route api;
int count = 0;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = ripng->vrf_id;
api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST;
api.prefix = rp->p;
if (count >= MULTIPATH_NUM)
break;
api_nh = &api.nexthops[count];
- api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->vrf_id = ripng->vrf_id;
api_nh->gate.ipv6 = rinfo->nexthop;
api_nh->ifindex = rinfo->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
}
/* Add/update ECMP routes to zebra. */
-void ripng_zebra_ipv6_add(struct agg_node *rp)
+void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp)
{
- ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
+ ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD);
}
/* Delete ECMP routes from zebra. */
-void ripng_zebra_ipv6_delete(struct agg_node *rp)
+void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp)
{
- ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
+ ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE);
}
/* Zebra route add and delete treatment. */
static int ripng_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
+ struct ripng *ripng;
struct zapi_route api;
struct in6_addr nexthop;
unsigned long ifindex;
+ ripng = ripng_lookup_by_vrf_id(vrf_id);
+ if (!ripng)
+ return 0;
+
if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
ifindex = api.nexthops[0].ifindex;
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
- ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
+ ripng_redistribute_add(ripng, api.type,
+ RIPNG_ROUTE_REDISTRIBUTE,
(struct prefix_ipv6 *)&api.prefix,
ifindex, &nexthop, api.tag);
else
- ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
- (struct prefix_ipv6 *)&api.prefix,
- ifindex);
+ ripng_redistribute_delete(
+ ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
+ (struct prefix_ipv6 *)&api.prefix, ifindex);
return 0;
}
-void ripng_redistribute_conf_update(int type)
+void ripng_redistribute_conf_update(struct ripng *ripng, int type)
{
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
- VRF_DEFAULT);
+ ripng->vrf_id);
}
-void ripng_redistribute_conf_delete(int type)
+void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
{
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
- AFI_IP6, type, 0, VRF_DEFAULT);
+ AFI_IP6, type, 0, ripng->vrf_id);
- ripng_redistribute_withdraw(type);
+ ripng_redistribute_withdraw(ripng, type);
}
-int ripng_redistribute_check(int type)
+int ripng_redistribute_check(struct ripng *ripng, int type)
{
- return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
+ return vrf_bitmap_check(zclient->redist[AFI_IP6][type], ripng->vrf_id);
}
-void ripng_redistribute_clean()
+void ripng_redistribute_clean(struct ripng *ripng)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
+ if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i],
+ ripng->vrf_id))
continue;
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
zclient, AFI_IP6, i, 0,
- VRF_DEFAULT);
+ ripng->vrf_id);
- vrf_bitmap_unset(zclient->redist[AFI_IP6][i], VRF_DEFAULT);
+ vrf_bitmap_unset(zclient->redist[AFI_IP6][i], ripng->vrf_id);
}
}
-void ripng_redistribute_write(struct vty *vty)
+void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
{
int i;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default
|| !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
- VRF_DEFAULT))
+ ripng->vrf_id))
continue;
vty_out(vty, " %s", zebra_route_string(i));
#include "ripngd/ripng_debug.h"
#include "ripngd/ripng_nexthop.h"
-/* RIPng structure which includes many parameters related to RIPng
- protocol. If ripng couldn't active or ripng doesn't configured,
- ripng->fd must be negative value. */
-struct ripng *ripng = NULL;
-
enum { ripng_all_route,
ripng_changed_route,
};
XFREE(MTYPE_RIPNG_ROUTE, rinfo);
}
+struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo)
+{
+ return agg_get_table_info(agg_get_table(rinfo->rp));
+}
+
/* Create ripng socket. */
int ripng_make_socket(void)
{
int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to,
struct interface *ifp)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
int ret;
struct msghdr msg;
struct iovec iov;
return 0;
}
-static void ripng_timeout_update(struct ripng_info *rinfo);
+static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo);
/* Add new route to the ECMP list.
* RETURN: the new entry added in the list, or NULL if it is not the first
* entry and ECMP is not allowed.
*/
-struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new)
+struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
+ struct ripng_info *rinfo_new)
{
struct agg_node *rp = rinfo_new->rp;
struct ripng_info *rinfo = NULL;
listnode_add(list, rinfo);
if (ripng_route_rte(rinfo)) {
- ripng_timeout_update(rinfo);
- ripng_zebra_ipv6_add(rp);
+ ripng_timeout_update(ripng, rinfo);
+ ripng_zebra_ipv6_add(ripng, rp);
}
ripng_aggregate_increment(rp, rinfo);
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
return rinfo;
}
/* Replace the ECMP list with the new route.
* RETURN: the new entry added in the list
*/
-struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new)
+struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
+ struct ripng_info *rinfo_new)
{
struct agg_node *rp = rinfo_new->rp;
struct list *list = (struct list *)rp->info;
struct listnode *node = NULL, *nextnode = NULL;
if (list == NULL || listcount(list) == 0)
- return ripng_ecmp_add(rinfo_new);
+ return ripng_ecmp_add(ripng, rinfo_new);
/* Get the first entry */
rinfo = listgetdata(listhead(list));
/* Learnt route replaced by a local one. Delete it from zebra. */
if (ripng_route_rte(rinfo) && !ripng_route_rte(rinfo_new))
if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
if (rinfo->metric != RIPNG_METRIC_INFINITY)
ripng_aggregate_decrement_list(rp, list);
memcpy(rinfo, rinfo_new, sizeof(struct ripng_info));
if (ripng_route_rte(rinfo)) {
- ripng_timeout_update(rinfo);
+ ripng_timeout_update(ripng, rinfo);
/* The ADD message implies an update. */
- ripng_zebra_ipv6_add(rp);
+ ripng_zebra_ipv6_add(ripng, rp);
}
ripng_aggregate_increment(rp, rinfo);
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
return rinfo;
}
* the entry - the entry is the last one in the list; its metric is set
* to INFINITY, and the garbage collector is started for it
*/
-struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo)
+struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
+ struct ripng_info *rinfo)
{
struct agg_node *rp = rinfo->rp;
struct list *list = (struct list *)rp->info;
if (ripng_route_rte(rinfo)
&& CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
/* The ADD message implies the update. */
- ripng_zebra_ipv6_add(rp);
+ ripng_zebra_ipv6_add(ripng, rp);
ripng_info_free(rinfo);
rinfo = NULL;
} else {
if (ripng_route_rte(rinfo)
&& CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
}
/* Set the route change flag on the first entry. */
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
return rinfo;
}
/* Timeout RIPng routes. */
static int ripng_timeout(struct thread *t)
{
- ripng_ecmp_delete((struct ripng_info *)THREAD_ARG(t));
+ struct ripng_info *rinfo = THREAD_ARG(t);
+ struct ripng *ripng = ripng_info_get_instance(rinfo);
+
+ ripng_ecmp_delete(ripng, rinfo);
+
return 0;
}
-static void ripng_timeout_update(struct ripng_info *rinfo)
+static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo)
{
if (rinfo->metric != RIPNG_METRIC_INFINITY) {
RIPNG_TIMER_OFF(rinfo->t_timeout);
- RIPNG_TIMER_ON(rinfo->t_timeout, ripng_timeout,
- ripng->timeout_time);
+ thread_add_timer(master, ripng_timeout, rinfo,
+ ripng->timeout_time, &rinfo->t_timeout);
}
}
struct agg_node *rp;
struct ripng_info *rinfo = NULL, newinfo;
struct ripng_interface *ri;
+ struct ripng *ripng;
struct in6_addr *nexthop;
int same = 0;
struct list *list = NULL;
apply_mask_ipv6. */
apply_mask_ipv6(&p);
- /* Apply input filters. */
ri = ifp->info;
+ ripng = ri->ripng;
+ /* Apply input filters. */
ret = ripng_filter(RIPNG_FILTER_IN, &p, ri);
if (ret < 0)
return;
**/
/* Zebra ripngd can handle offset-list in. */
- ret = ripng_offset_list_apply_in(&p, ifp, &rte->metric);
+ ret = ripng_offset_list_apply_in(ripng, &p, ifp, &rte->metric);
/* If offset-list does not modify the metric use interface's
* one. */
infinity (there is no point in adding a route which
unusable). */
if (rte->metric != RIPNG_METRIC_INFINITY)
- ripng_ecmp_add(&newinfo);
+ ripng_ecmp_add(ripng, &newinfo);
else
agg_unlock_node(rp);
} else {
&& rinfo->t_timeout
&& (thread_timer_remain_second(rinfo->t_timeout)
< (ripng->timeout_time / 2))) {
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
}
/* Next, compare the metrics. If the datagram is from the same
router as the existing route, and the new metric is different
|| rte->metric < rinfo->metric) {
if (listcount(list) == 1) {
if (newinfo.metric != RIPNG_METRIC_INFINITY)
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
else
- ripng_ecmp_delete(rinfo);
+ ripng_ecmp_delete(ripng, rinfo);
} else {
if (newinfo.metric < rinfo->metric)
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
else /* newinfo.metric > rinfo->metric */
- ripng_ecmp_delete(rinfo);
+ ripng_ecmp_delete(ripng, rinfo);
}
} else /* same & no change */
- ripng_timeout_update(rinfo);
+ ripng_timeout_update(ripng, rinfo);
/* Unlock tempolary lock of the route. */
agg_unlock_node(rp);
}
/* Add redistributed route to RIPng table. */
-void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p,
- ifindex_t ifindex, struct in6_addr *nexthop,
- route_tag_t tag)
+void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
+ struct prefix_ipv6 *p, ifindex_t ifindex,
+ struct in6_addr *nexthop, route_tag_t tag)
{
struct agg_node *rp;
struct ripng_info *rinfo = NULL, newinfo;
}
}
- ripng_ecmp_replace(&newinfo);
+ ripng_ecmp_replace(ripng, &newinfo);
agg_unlock_node(rp);
} else
- ripng_ecmp_add(&newinfo);
+ ripng_ecmp_add(ripng, &newinfo);
if (IS_RIPNG_DEBUG_EVENT) {
if (!nexthop)
zlog_debug(
"Redistribute new prefix %s/%d on the interface %s",
inet6_ntoa(p->prefix), p->prefixlen,
- ifindex2ifname(ifindex, VRF_DEFAULT));
+ ifindex2ifname(ifindex, ripng->vrf_id));
else
zlog_debug(
"Redistribute new prefix %s/%d with nexthop %s on the interface %s",
inet6_ntoa(p->prefix), p->prefixlen,
inet6_ntoa(*nexthop),
- ifindex2ifname(ifindex, VRF_DEFAULT));
+ ifindex2ifname(ifindex, ripng->vrf_id));
}
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
/* Delete redistributed route to RIPng table. */
-void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p,
- ifindex_t ifindex)
+void ripng_redistribute_delete(struct ripng *ripng, int type, int sub_type,
+ struct prefix_ipv6 *p, ifindex_t ifindex)
{
struct agg_node *rp;
struct ripng_info *rinfo;
inet6_ntoa(p->prefix),
p->prefixlen,
ifindex2ifname(ifindex,
- VRF_DEFAULT));
+ ripng->vrf_id));
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
}
agg_unlock_node(rp);
}
/* Withdraw redistributed route. */
-void ripng_redistribute_withdraw(int type)
+void ripng_redistribute_withdraw(struct ripng *ripng, int type)
{
struct agg_node *rp;
struct ripng_info *rinfo = NULL;
inet6_ntoa(p->prefix),
p->prefixlen,
ifindex2ifname(rinfo->ifindex,
- VRF_DEFAULT));
+ ripng->vrf_id));
}
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
}
}
struct sockaddr_in6 *from,
struct interface *ifp, int hoplimit)
{
+ struct ripng_interface *ri = ifp->info;
+ struct ripng *ripng = ri->ripng;
caddr_t lim;
struct rte *rte;
struct ripng_nexthop nexthop;
if (ntohs(from->sin6_port) != RIPNG_PORT_DEFAULT) {
zlog_warn("RIPng packet comes from non RIPng port %d from %s",
ntohs(from->sin6_port), inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
zlog_warn("RIPng packet comes from non link local address %s",
inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
zlog_warn(
"RIPng packet comes from my own link local address %s",
inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
zlog_warn(
"RIPng packet comes with non 255 hop count %d from %s",
hoplimit, inet6_ntoa(from->sin6_addr));
- ripng_peer_bad_packet(from);
+ ripng_peer_bad_packet(ripng, from);
return;
}
/* Update RIPng peer. */
- ripng_peer_update(from, packet->version);
+ ripng_peer_update(ripng, from, packet->version);
/* Reset nexthop. */
memset(&nexthop, 0, sizeof(struct ripng_nexthop));
"Destination prefix is a multicast address %s/%d [%d]",
inet6_ntoa(rte->addr), rte->prefixlen,
rte->metric);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) {
"Destination prefix is a link-local address %s/%d [%d]",
inet6_ntoa(rte->addr), rte->prefixlen,
rte->metric);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
if (IN6_IS_ADDR_LOOPBACK(&rte->addr)) {
"Destination prefix is a loopback address %s/%d [%d]",
inet6_ntoa(rte->addr), rte->prefixlen,
rte->metric);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
zlog_warn("Invalid prefix length %s/%d from %s%%%s",
inet6_ntoa(rte->addr), rte->prefixlen,
inet6_ntoa(from->sin6_addr), ifp->name);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
if (!(rte->metric >= 1 && rte->metric <= 16)) {
zlog_warn("Invalid metric %d from %s%%%s", rte->metric,
inet6_ntoa(from->sin6_addr), ifp->name);
- ripng_peer_bad_route(from);
+ ripng_peer_bad_route(ripng, from);
continue;
}
struct sockaddr_in6 *from,
struct interface *ifp)
{
+ struct ripng *ripng;
caddr_t lim;
struct rte *rte;
struct prefix_ipv6 p;
ri = ifp->info;
if (!ri->running)
return;
+ ripng = ri->ripng;
/* When passive interface is specified, suppress responses */
if (ri->passive)
return;
/* RIPng peer update. */
- ripng_peer_update(from, packet->version);
+ ripng_peer_update(ripng, from, packet->version);
lim = ((caddr_t)packet) + size;
rte = packet->rte;
/* First entry point of reading RIPng packet. */
static int ripng_read(struct thread *thread)
{
+ struct ripng *ripng = THREAD_ARG(thread);
int len;
int sock;
struct sockaddr_in6 from;
ripng->t_read = NULL;
/* Add myself to the next event. */
- ripng_event(RIPNG_READ, sock);
+ ripng_event(ripng, RIPNG_READ, sock);
/* Read RIPng packet. */
len = ripng_recv_packet(sock, STREAM_DATA(ripng->ibuf),
if (((len - 4) % 20) != 0) {
zlog_warn("RIPng invalid packet size %d from %s", len,
inet6_ntoa(from.sin6_addr));
- ripng_peer_bad_packet(&from);
+ ripng_peer_bad_packet(ripng, &from);
return 0;
}
packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf);
- ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(ifindex, ripng->vrf_id);
/* RIPng packet received. */
if (IS_RIPNG_DEBUG_EVENT)
zlog_warn(
"RIPng packet version %d doesn't fit to my version %d",
packet->version, ripng->version);
- ripng_peer_bad_packet(&from);
+ ripng_peer_bad_packet(ripng, &from);
return 0;
}
break;
default:
zlog_warn("Invalid RIPng command %d", packet->command);
- ripng_peer_bad_packet(&from);
+ ripng_peer_bad_packet(ripng, &from);
break;
}
return 0;
}
/* Walk down the RIPng routing table then clear changed flag. */
-static void ripng_clear_changed_flag(void)
+static void ripng_clear_changed_flag(struct ripng *ripng)
{
struct agg_node *rp;
struct ripng_info *rinfo = NULL;
enabled interface. */
static int ripng_update(struct thread *t)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng = THREAD_ARG(t);
+ struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
struct interface *ifp;
struct ripng_interface *ri;
ripng->trigger = 0;
/* Reset flush event. */
- ripng_event(RIPNG_UPDATE_EVENT, 0);
+ ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
return 0;
}
/* Triggered update interval timer. */
static int ripng_triggered_interval(struct thread *t)
{
+ struct ripng *ripng = THREAD_ARG(t);
+
ripng->t_triggered_interval = NULL;
if (ripng->trigger) {
/* Execute triggered update. */
int ripng_triggered_update(struct thread *t)
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng = THREAD_ARG(t);
+ struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id);
struct interface *ifp;
struct ripng_interface *ri;
int interval;
/* Once all of the triggered updates have been generated, the route
change flags should be cleared. */
- ripng_clear_changed_flag();
+ ripng_clear_changed_flag(ripng);
/* After a triggered update is sent, a timer should be set for a
random interval between 1 and 5 seconds. If other changes that
interval = (random() % 5) + 1;
ripng->t_triggered_interval = NULL;
- thread_add_timer(master, ripng_triggered_interval, NULL, interval,
+ thread_add_timer(master, ripng_triggered_interval, ripng, interval,
&ripng->t_triggered_interval);
return 0;
void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
int route_type)
{
+ struct ripng *ripng;
int ret;
struct agg_node *rp;
struct ripng_info *rinfo;
ifp->name);
}
- /* Get RIPng interface. */
+ /* Get RIPng interface and instance. */
ri = ifp->info;
+ ripng = ri->ripng;
ripng_rte_list = ripng_rte_new();
/* Apply offset-list */
if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
- ripng_offset_list_apply_out(p, ifp,
+ ripng_offset_list_apply_out(ripng, p, ifp,
&rinfo->metric_out);
if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
/* Apply offset-list */
if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
ripng_offset_list_apply_out(
- p, ifp, &aggregate->metric_out);
+ ripng, p, ifp, &aggregate->metric_out);
if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
aggregate->metric_out = RIPNG_METRIC_INFINITY;
ripng_rte_free(ripng_rte_list);
}
+struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id)
+{
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
+ return vrf->info;
+}
+
/* Create new RIPng instance and set it to global variable. */
-int ripng_create(int socket)
+struct ripng *ripng_create(struct vrf *vrf, int socket)
{
- /* ripng should be NULL. */
- assert(ripng == NULL);
+ struct ripng *ripng;
+ struct interface *ifp;
/* Allocaste RIPng instance. */
ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng));
/* Initialize RIPng data structures. */
ripng->table = agg_table_init();
+ agg_set_table_info(ripng->table, ripng);
ripng->peer_list = list_new();
ripng->peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
ripng->peer_list->del = ripng_peer_list_del;
ripng->sock = socket;
/* Threads. */
- ripng_event(RIPNG_READ, ripng->sock);
- ripng_event(RIPNG_UPDATE_EVENT, 1);
+ ripng_event(ripng, RIPNG_READ, ripng->sock);
+ ripng_event(ripng, RIPNG_UPDATE_EVENT, 1);
- return 0;
+ /* Link RIPng instance to VRF. */
+ ripng->vrf_id = vrf->vrf_id;
+ vrf->info = ripng;
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct ripng_interface *ri;
+
+ ri = ifp->info;
+ ri->ripng = ripng;
+ }
+
+ return ripng;
}
/* Send RIPng request to the interface. */
return ((random() % (time + 1)) - (time / 2));
}
-void ripng_event(enum ripng_event event, int sock)
+void ripng_event(struct ripng *ripng, enum ripng_event event, int sock)
{
int jitter = 0;
switch (event) {
case RIPNG_READ:
- thread_add_read(master, ripng_read, NULL, sock, &ripng->t_read);
+ thread_add_read(master, ripng_read, ripng, sock,
+ &ripng->t_read);
break;
case RIPNG_UPDATE_EVENT:
if (ripng->t_update) {
jitter = ripng_update_jitter(ripng->update_time);
ripng->t_update = NULL;
- thread_add_timer(master, ripng_update, NULL,
+ thread_add_timer(master, ripng_update, ripng,
sock ? 2 : ripng->update_time + jitter,
&ripng->t_update);
break;
if (ripng->t_triggered_interval)
ripng->trigger = 1;
else
- thread_add_event(master, ripng_triggered_update, NULL,
+ thread_add_event(master, ripng_triggered_update, ripng,
0, &ripng->t_triggered_update);
break;
default:
IPV6_STR
"Show RIPng routes\n")
{
+ struct ripng *ripng;
struct agg_node *rp;
struct ripng_info *rinfo;
struct ripng_aggregate *aggregate;
struct listnode *listnode = NULL;
int len;
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
if (!ripng)
return CMD_SUCCESS;
len = vty_out(
vty, "%s",
ifindex2ifname(rinfo->ifindex,
- VRF_DEFAULT));
+ ripng->vrf_id));
} else if (rinfo->metric
== RIPNG_METRIC_INFINITY) {
len = vty_out(vty, "kill");
"Show RIPng routes\n"
"IPv6 routing protocol process parameters and statistics\n")
{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng;
+ struct vrf *vrf;
struct interface *ifp;
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
if (!ripng)
return CMD_SUCCESS;
/* Redistribute information. */
vty_out(vty, " Redistributing:");
- ripng_redistribute_write(vty);
+ ripng_redistribute_write(vty, ripng);
vty_out(vty, "\n");
vty_out(vty, " Default version control: send version %d,",
vty_out(vty, " Interface Send Recv\n");
+ vrf = vrf_lookup_by_id(ripng->vrf_id);
FOR_ALL_INTERFACES (vrf, ifp) {
struct ripng_interface *ri;
}
vty_out(vty, " Routing for Networks:\n");
- ripng_network_write(vty);
+ ripng_network_write(vty, ripng);
vty_out(vty, " Routing Information Sources:\n");
vty_out(vty,
" Gateway BadPackets BadRoutes Distance Last Update\n");
- ripng_peer_display(vty);
+ ripng_peer_display(vty, ripng);
return CMD_SUCCESS;
}
#endif
/* Update ECMP routes to zebra when ECMP is disabled. */
-void ripng_ecmp_disable(void)
+void ripng_ecmp_disable(struct ripng *ripng)
{
struct agg_node *rp;
struct ripng_info *rinfo, *tmp_rinfo;
}
/* Update zebra. */
- ripng_zebra_ipv6_add(rp);
+ ripng_zebra_ipv6_add(ripng, rp);
/* Set the route change flag. */
SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
/* Signal the output process to trigger an update. */
- ripng_event(RIPNG_TRIGGERED_UPDATE, 0);
+ ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
}
}
dnode = yang_dnode_get(running_config->dnode,
"/frr-ripngd:ripngd/instance");
if (dnode) {
- nb_cli_show_dnode_cmds(vty, dnode, false);
+ struct ripng *ripng;
- config_write_distribute(vty,
- ripng->distribute_ctx);
+ nb_cli_show_dnode_cmds(vty, dnode, false);
- config_write_if_rmap(vty);
+ ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT);
+ if (ripng) {
+ config_write_distribute(vty, ripng->distribute_ctx);
+ config_write_if_rmap(vty);
+ }
write = 1;
}
}
/* delete all the added ripng routes. */
-void ripng_clean()
+void ripng_clean(struct ripng *ripng)
{
+ struct vrf *vrf;
+ struct interface *ifp;
struct agg_node *rp;
/* Clear RIPng routes */
rinfo = listgetdata(listhead(list));
if (ripng_route_rte(rinfo))
- ripng_zebra_ipv6_delete(rp);
+ ripng_zebra_ipv6_delete(ripng, rp);
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
RIPNG_TIMER_OFF(rinfo->t_timeout);
stream_free(ripng->ibuf);
stream_free(ripng->obuf);
- ripng_clean_network();
- ripng_passive_interface_clean();
+ ripng_clean_network(ripng);
+ ripng_passive_interface_clean(ripng);
vector_free(ripng->enable_if);
agg_table_finish(ripng->enable_network);
vector_free(ripng->passive_interface);
list_delete(&ripng->offset_list_master);
- ripng_interface_clean();
- ripng_redistribute_clean();
+ ripng_interface_clean(ripng);
+ ripng_redistribute_clean(ripng);
+
+ vrf = vrf_lookup_by_id(ripng->vrf_id);
+ vrf->info = NULL;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct ripng_interface *ri;
+
+ ri = ifp->info;
+ ri->ripng = NULL;
+ }
XFREE(MTYPE_RIPNG, ripng);
}
ripng_if_rmap_update(if_rmap);
}
-static void ripng_routemap_update_redistribute(void)
+static void ripng_routemap_update_redistribute(struct ripng *ripng)
{
- int i;
-
- if (ripng) {
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (ripng->route_map[i].name)
- ripng->route_map[i].map =
- route_map_lookup_by_name(
- ripng->route_map[i].name);
- }
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ if (ripng->route_map[i].name)
+ ripng->route_map[i].map = route_map_lookup_by_name(
+ ripng->route_map[i].name);
}
}
static void ripng_routemap_update(const char *unused)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct ripng *ripng;
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp)
ripng_if_rmap_update_interface(ifp);
- ripng_routemap_update_redistribute();
+ ripng = vrf->info;
+ if (ripng)
+ ripng_routemap_update_redistribute(ripng);
}
/* Initialize ripng structure and set commands. */
/* RIPng structure. */
struct ripng {
+ /* VRF ID. */
+ vrf_id_t vrf_id;
+
/* RIPng socket. */
int sock;
/* RIPng specific interface configuration. */
struct ripng_interface {
+ /* Parent routing instance. */
+ struct ripng *ripng;
+
/* RIPng is enabled on this interface. */
int enable_network;
int enable_interface;
/* RIPng peer information. */
struct ripng_peer {
+ /* Parent routing instance. */
+ struct ripng *ripng;
+
/* Peer address. */
struct in6_addr addr;
#define RIPNG_OFFSET_LIST_MAX 2
struct ripng_offset_list {
+ /* Parent routing instance. */
+ struct ripng *ripng;
+
char *ifname;
struct {
};
/* Extern variables. */
-extern struct ripng *ripng;
extern struct zebra_privs_t ripngd_privs;
extern struct thread_master *master;
/* Prototypes. */
extern void ripng_init(void);
-extern void ripng_clean(void);
-extern void ripng_clean_network(void);
-extern void ripng_interface_clean(void);
-extern int ripng_enable_network_add(struct prefix *p);
-extern int ripng_enable_network_delete(struct prefix *p);
-extern int ripng_enable_if_add(const char *ifname);
-extern int ripng_enable_if_delete(const char *ifname);
-extern int ripng_passive_interface_set(const char *ifname);
-extern int ripng_passive_interface_unset(const char *ifname);
-extern void ripng_passive_interface_clean(void);
+extern void ripng_clean(struct ripng *ripng);
+extern void ripng_clean_network(struct ripng *ripng);
+extern void ripng_interface_clean(struct ripng *ripng);
+extern int ripng_enable_network_add(struct ripng *ripng, struct prefix *p);
+extern int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p);
+extern int ripng_enable_if_add(struct ripng *ripng, const char *ifname);
+extern int ripng_enable_if_delete(struct ripng *ripng, const char *ifname);
+extern int ripng_passive_interface_set(struct ripng *ripng, const char *ifname);
+extern int ripng_passive_interface_unset(struct ripng *ripng,
+ const char *ifname);
+extern void ripng_passive_interface_clean(struct ripng *ripng);
extern void ripng_if_init(void);
extern void ripng_route_map_init(void);
extern void ripng_terminate(void);
/* zclient_init() is done by ripng_zebra.c:zebra_init() */
extern void zebra_init(struct thread_master *);
extern void ripng_zebra_stop(void);
-extern void ripng_redistribute_conf_update(int type);
-extern void ripng_redistribute_conf_delete(int type);
-
-extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t);
-extern void ripng_peer_bad_route(struct sockaddr_in6 *);
-extern void ripng_peer_bad_packet(struct sockaddr_in6 *);
-extern void ripng_peer_display(struct vty *);
-extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *);
-extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *);
+extern void ripng_redistribute_conf_update(struct ripng *ripng, int type);
+extern void ripng_redistribute_conf_delete(struct ripng *ripng, int type);
+
+extern void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
+ uint8_t version);
+extern void ripng_peer_bad_route(struct ripng *ripng,
+ struct sockaddr_in6 *from);
+extern void ripng_peer_bad_packet(struct ripng *ripng,
+ struct sockaddr_in6 *from);
+extern void ripng_peer_display(struct vty *vty, struct ripng *ripng);
+extern struct ripng_peer *ripng_peer_lookup(struct ripng *ripng,
+ struct in6_addr *addr);
+extern struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
+ struct in6_addr *addr);
extern int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2);
extern void ripng_peer_list_del(void *arg);
-extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname);
+extern struct ripng_offset_list *ripng_offset_list_new(struct ripng *ripng,
+ const char *ifname);
extern void ripng_offset_list_del(struct ripng_offset_list *offset);
-extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
-extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
-extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *,
- uint8_t *);
-extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *,
- uint8_t *);
+extern struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
+ const char *ifname);
+extern int ripng_offset_list_apply_in(struct ripng *ripng,
+ struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric);
+extern int ripng_offset_list_apply_out(struct ripng *ripng,
+ struct prefix_ipv6 *p,
+ struct interface *ifp, uint8_t *metric);
extern int offset_list_cmp(struct ripng_offset_list *o1,
struct ripng_offset_list *o2);
extern int ripng_route_rte(struct ripng_info *rinfo);
extern struct ripng_info *ripng_info_new(void);
extern void ripng_info_free(struct ripng_info *rinfo);
-extern void ripng_event(enum ripng_event, int);
+extern struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo);
+extern void ripng_event(struct ripng *ripng, enum ripng_event event, int sock);
extern int ripng_request(struct interface *ifp);
-extern void ripng_redistribute_add(int, int, struct prefix_ipv6 *, ifindex_t,
- struct in6_addr *, route_tag_t);
-extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *,
- ifindex_t);
-extern void ripng_redistribute_withdraw(int type);
-
-extern void ripng_ecmp_disable(void);
+extern void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
+ struct prefix_ipv6 *p, ifindex_t ifindex,
+ struct in6_addr *nexthop, route_tag_t tag);
+extern void ripng_redistribute_delete(struct ripng *ripng, int type,
+ int sub_type, struct prefix_ipv6 *p,
+ ifindex_t ifindex);
+extern void ripng_redistribute_withdraw(struct ripng *ripng, int type);
+
+extern void ripng_ecmp_disable(struct ripng *ripng);
extern void ripng_distribute_update_interface(struct interface *);
extern void ripng_if_rmap_update_interface(struct interface *);
-extern void ripng_zebra_ipv6_add(struct agg_node *node);
-extern void ripng_zebra_ipv6_delete(struct agg_node *node);
+extern void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *node);
+extern void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *node);
-extern void ripng_redistribute_clean(void);
-extern int ripng_redistribute_check(int);
-extern void ripng_redistribute_write(struct vty *);
+extern void ripng_redistribute_clean(struct ripng *ripng);
+extern int ripng_redistribute_check(struct ripng *ripng, int type);
+extern void ripng_redistribute_write(struct vty *vty, struct ripng *ripng);
extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
struct in6_addr *nexthop, uint16_t tag,
extern int ripng_interface_address_delete(int command, struct zclient *,
zebra_size_t, vrf_id_t);
-extern int ripng_create(int socket);
+extern struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id);
+extern struct ripng *ripng_create(struct vrf *vrf, int socket);
extern int ripng_make_socket(void);
-extern int ripng_network_write(struct vty *);
-
-extern struct ripng_info *ripng_ecmp_add(struct ripng_info *);
-extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *);
-extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *);
+extern int ripng_network_write(struct vty *vty, struct ripng *ripng);
+
+extern struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
+ struct ripng_info *rinfo);
+extern struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
+ struct ripng_info *rinfo);
+extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
+ struct ripng_info *rinfo);
/* Northbound. */
extern void ripng_cli_init(void);