diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2019-01-04 22:08:10 +0100 |
---|---|---|
committer | Renato Westphal <renato@opensourcerouting.org> | 2019-01-18 19:15:41 +0100 |
commit | 5c84b9a58153f89379e3a99e02173662ea390489 (patch) | |
tree | ea4f0cf53f25e43ace1eeb7b3028cba9526e6859 /ripngd | |
parent | ripngd: move "ripng_offset_list_master" to the ripng structure (diff) | |
download | frr-5c84b9a58153f89379e3a99e02173662ea390489.tar.xz frr-5c84b9a58153f89379e3a99e02173662ea390489.zip |
ripngd: remove the ripng global variable
This is the last step to make ripngd ready for multi-instance
support.
Remove the ripng global variable and add a "ripng" parameter
to all functions that need to know the RIPng instance they are
working on. On some functions, retrieve the RIPng instance from
the interface variable when it exists (this assumes interfaces can
pertain to one RIPng instance at most, which is ok for VRF support).
In preparation for the next commits (VRF support), add a "vrd_id"
member to the ripng structure, and use ripng->vrf_id instead of
VRF_DEFAULT wherever possible.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ripngd')
-rw-r--r-- | ripngd/ripng_interface.c | 136 | ||||
-rw-r--r-- | ripngd/ripng_main.c | 11 | ||||
-rw-r--r-- | ripngd/ripng_nexthop.c | 3 | ||||
-rw-r--r-- | ripngd/ripng_northbound.c | 122 | ||||
-rw-r--r-- | ripngd/ripng_offset.c | 25 | ||||
-rw-r--r-- | ripngd/ripng_peer.c | 30 | ||||
-rw-r--r-- | ripngd/ripng_route.c | 4 | ||||
-rw-r--r-- | ripngd/ripng_route.h | 4 | ||||
-rw-r--r-- | ripngd/ripng_zebra.c | 56 | ||||
-rw-r--r-- | ripngd/ripngd.c | 287 | ||||
-rw-r--r-- | ripngd/ripngd.h | 119 |
11 files changed, 506 insertions, 291 deletions
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index b0a07ab46..af2b1c260 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -52,12 +52,12 @@ /* Static utility function. */ static void ripng_enable_apply(struct interface *); static void ripng_passive_interface_apply(struct interface *); -static int ripng_enable_if_lookup(const char *); +static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname); static int ripng_enable_network_lookup2(struct connected *); -static void ripng_enable_apply_all(void); +static void ripng_enable_apply_all(struct ripng *ripng); /* Join to the all rip routers multicast group. */ -static int ripng_multicast_join(struct interface *ifp) +static int ripng_multicast_join(struct interface *ifp, int sock) { int ret; struct ipv6_mreq mreq; @@ -75,8 +75,7 @@ static int ripng_multicast_join(struct interface *ifp) */ frr_elevate_privs(&ripngd_privs) { - ret = setsockopt(ripng->sock, IPPROTO_IPV6, - IPV6_JOIN_GROUP, + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq, sizeof(mreq)); save_errno = errno; @@ -111,7 +110,7 @@ static int ripng_multicast_join(struct interface *ifp) } /* Leave from the all rip routers multicast group. */ -static int ripng_multicast_leave(struct interface *ifp) +static int ripng_multicast_leave(struct interface *ifp, int sock) { int ret; struct ipv6_mreq mreq; @@ -121,7 +120,7 @@ static int ripng_multicast_leave(struct interface *ifp) inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); mreq.ipv6mr_interface = ifp->ifindex; - ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq, sizeof(mreq)); if (ret < 0) zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s\n", @@ -163,9 +162,13 @@ static int ripng_if_down(struct interface *ifp) struct agg_node *rp; struct ripng_info *rinfo; struct ripng_interface *ri; + struct ripng *ripng; struct list *list = NULL; struct listnode *listnode = NULL, *nextnode = NULL; + ri = ifp->info; + ripng = ri->ripng; + if (ripng) for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) @@ -173,16 +176,15 @@ static int ripng_if_down(struct interface *ifp) for (ALL_LIST_ELEMENTS(list, listnode, nextnode, rinfo)) if (rinfo->ifindex == ifp->ifindex) - ripng_ecmp_delete(rinfo); + ripng_ecmp_delete(ripng, rinfo); - ri = ifp->info; if (ri->running) { if (IS_RIPNG_DEBUG_EVENT) zlog_debug("turn off %s", ifp->name); /* Leave from multicast group. */ - ripng_multicast_leave(ifp); + ripng_multicast_leave(ifp, ripng->sock); ri->running = 0; } @@ -304,9 +306,9 @@ int ripng_interface_delete(int command, struct zclient *zclient, 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; @@ -326,6 +328,8 @@ void ripng_interface_clean(void) static void ripng_apply_address_add(struct connected *ifc) { + struct ripng_interface *ri = ifc->ifp->info; + struct ripng *ripng = ri->ripng; struct prefix_ipv6 address; struct prefix *p; @@ -345,9 +349,9 @@ static void ripng_apply_address_add(struct connected *ifc) /* Check if this interface is RIP enabled or not or Check if this address's prefix is RIP enabled */ - if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) + if ((ripng_enable_if_lookup(ripng, ifc->ifp->name) >= 0) || (ripng_enable_network_lookup2(ifc) >= 0)) - ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, + ripng_redistribute_add(ripng, ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, &address, ifc->ifp->ifindex, NULL, 0); } @@ -395,6 +399,8 @@ int ripng_interface_address_add(int command, struct zclient *zclient, static void ripng_apply_address_del(struct connected *ifc) { + struct ripng_interface *ri = ifc->ifp->info; + struct ripng *ripng = ri->ripng; struct prefix_ipv6 address; struct prefix *p; @@ -412,8 +418,9 @@ static void ripng_apply_address_del(struct connected *ifc) address.prefixlen = p->prefixlen; apply_mask_ipv6(&address); - ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex); + ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT, + RIPNG_ROUTE_INTERFACE, &address, + ifc->ifp->ifindex); } int ripng_interface_address_delete(int command, struct zclient *zclient, @@ -451,6 +458,8 @@ 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; @@ -483,6 +492,8 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) /* 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; @@ -513,7 +524,7 @@ static int ripng_enable_network_lookup2(struct connected *connected) } /* Add RIPng enable network. */ -int ripng_enable_network_add(struct prefix *p) +int ripng_enable_network_add(struct ripng *ripng, struct prefix *p) { struct agg_node *node; @@ -526,13 +537,13 @@ int ripng_enable_network_add(struct prefix *p) node->info = (void *)1; /* XXX: One should find a better solution than a generic one */ - ripng_enable_apply_all(); + ripng_enable_apply_all(ripng); return NB_OK; } /* Delete RIPng enable network. */ -int ripng_enable_network_delete(struct prefix *p) +int ripng_enable_network_delete(struct ripng *ripng, struct prefix *p) { struct agg_node *node; @@ -553,7 +564,7 @@ int ripng_enable_network_delete(struct prefix *p) } /* Lookup function. */ -static int ripng_enable_if_lookup(const char *ifname) +static int ripng_enable_if_lookup(struct ripng *ripng, const char *ifname) { unsigned int i; char *str; @@ -568,27 +579,27 @@ static int ripng_enable_if_lookup(const char *ifname) 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; @@ -596,7 +607,7 @@ int ripng_enable_if_delete(const char *ifname) free(str); vector_unset(ripng->enable_if, index); - ripng_enable_apply_all(); + ripng_enable_apply_all(ripng); return NB_OK; } @@ -614,7 +625,7 @@ static int ripng_interface_wakeup(struct thread *t) ri->t_wakeup = NULL; /* Join to multicast group. */ - if (ripng_multicast_join(ifp) < 0) { + if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) { flog_err_sys(EC_LIB_SOCKET, "multicast join failed, interface %s not running", ifp->name); @@ -632,6 +643,8 @@ static int ripng_interface_wakeup(struct thread *t) static void ripng_connect_set(struct interface *ifp, int set) { + struct ripng_interface *ri = ifp->info; + struct ripng *ripng = ri->ripng; struct listnode *node, *nnode; struct connected *connected; struct prefix_ipv6 address; @@ -651,19 +664,22 @@ static void ripng_connect_set(struct interface *ifp, int set) if (set) { /* Check once more wether this prefix is within a * "network IF_OR_PREF" one */ - if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) + if ((ripng_enable_if_lookup(ripng, connected->ifp->name) + >= 0) || (ripng_enable_network_lookup2(connected) >= 0)) ripng_redistribute_add( - ZEBRA_ROUTE_CONNECT, + ripng, ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, &address, connected->ifp->ifindex, NULL, 0); } else { - ripng_redistribute_delete( - ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, - &address, connected->ifp->ifindex); - if (ripng_redistribute_check(ZEBRA_ROUTE_CONNECT)) + ripng_redistribute_delete(ripng, ZEBRA_ROUTE_CONNECT, + RIPNG_ROUTE_INTERFACE, + &address, + connected->ifp->ifindex); + if (ripng_redistribute_check(ripng, + ZEBRA_ROUTE_CONNECT)) ripng_redistribute_add( - ZEBRA_ROUTE_CONNECT, + ripng, ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE, &address, connected->ifp->ifindex, NULL, 0); } @@ -692,7 +708,7 @@ void ripng_enable_apply(struct interface *ifp) ri->enable_network = 0; /* Check interface name configuration. */ - ret = ripng_enable_if_lookup(ifp->name); + ret = ripng_enable_if_lookup(ri->ripng, ifp->name); if (ret >= 0) ri->enable_interface = 1; else @@ -730,9 +746,9 @@ void ripng_enable_apply(struct interface *ifp) } /* Set distribute list to all interfaces. */ -static void ripng_enable_apply_all(void) +static void ripng_enable_apply_all(struct ripng *ripng) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) @@ -740,7 +756,7 @@ static void ripng_enable_apply_all(void) } /* Clear all network and neighbor configuration */ -void ripng_clean_network() +void ripng_clean_network(struct ripng *ripng) { unsigned int i; char *str; @@ -763,14 +779,12 @@ void ripng_clean_network() } /* 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) @@ -782,19 +796,23 @@ void ripng_passive_interface_apply(struct interface *ifp) { int ret; struct ripng_interface *ri; + struct ripng *ripng; ri = ifp->info; + ripng = ri->ripng; + if (!ripng) + return; - ret = ripng_passive_interface_lookup(ifp->name); + ret = ripng_passive_interface_lookup(ripng, ifp->name); if (ret < 0) ri->passive = 0; else ri->passive = 1; } -static void ripng_passive_interface_apply_all(void) +static void ripng_passive_interface_apply_all(struct ripng *ripng) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) @@ -802,24 +820,24 @@ static void ripng_passive_interface_apply_all(void) } /* 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; @@ -827,13 +845,13 @@ int ripng_passive_interface_unset(const char *ifname) 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; @@ -843,11 +861,11 @@ void ripng_passive_interface_clean(void) 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; @@ -872,11 +890,17 @@ int ripng_network_write(struct vty *vty) 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 @@ -889,7 +913,7 @@ static struct ripng_interface *ri_new(void) static int ripng_if_new_hook(struct interface *ifp) { - ifp->info = ri_new(); + ifp->info = ri_new(ifp); return 0; } diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index 26d602e1a..e7246efc4 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -80,10 +80,17 @@ static void sighup(void) /* 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(); diff --git a/ripngd/ripng_nexthop.c b/ripngd/ripng_nexthop.c index 74a132aa9..882c2fbc8 100644 --- a/ripngd/ripng_nexthop.c +++ b/ripngd/ripng_nexthop.c @@ -114,7 +114,8 @@ void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p, void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp, struct sockaddr_in6 *to) { - + struct ripng_interface *ri = ifp->info; + struct ripng *ripng = ri->ripng; struct ripng_rte_data *data; struct listnode *node, *nnode; diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index ca7a334f4..a6700c845 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -42,6 +42,8 @@ static int ripngd_instance_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; + struct vrf *vrf; int socket; switch (event) { @@ -58,8 +60,10 @@ static int ripngd_instance_create(enum nb_event 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; } @@ -69,10 +73,13 @@ static int ripngd_instance_create(enum nb_event event, 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; } @@ -84,12 +91,15 @@ static int ripngd_instance_allow_ecmp_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; + if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ripng->ecmp = yang_dnode_get_bool(dnode, NULL); if (!ripng->ecmp) - ripng_ecmp_disable(); + ripng_ecmp_disable(ripng); return NB_OK; } @@ -101,19 +111,22 @@ static int ripngd_instance_default_information_originate_modify( enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; bool default_information; struct prefix_ipv6 p; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); default_information = yang_dnode_get_bool(dnode, NULL); + str2prefix_ipv6("::/0", &p); if (default_information) { - ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, - &p, 0, NULL, 0); + ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, + RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0); } else { - ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, + ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0); } @@ -127,9 +140,12 @@ static int ripngd_instance_default_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; + if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ripng->default_metric = yang_dnode_get_uint8(dnode, NULL); return NB_OK; @@ -142,29 +158,33 @@ static int ripngd_instance_network_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; struct prefix p; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv6p(&p, dnode, NULL); apply_mask_ipv6((struct prefix_ipv6 *)&p); - return ripng_enable_network_add(&p); + return ripng_enable_network_add(ripng, &p); } static int ripngd_instance_network_delete(enum nb_event event, const struct lyd_node *dnode) { + struct ripng *ripng; struct prefix p; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv6p(&p, dnode, NULL); apply_mask_ipv6((struct prefix_ipv6 *)&p); - return ripng_enable_network_delete(&p); + return ripng_enable_network_delete(ripng, &p); } /* @@ -174,27 +194,31 @@ static int ripngd_instance_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return ripng_enable_if_add(ifname); + return ripng_enable_if_add(ripng, ifname); } static int ripngd_instance_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct ripng *ripng; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return ripng_enable_if_delete(ifname); + return ripng_enable_if_delete(ripng, ifname); } /* @@ -204,15 +228,17 @@ static int ripngd_instance_offset_list_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; const char *ifname; struct ripng_offset_list *offset; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, "./interface"); - offset = ripng_offset_list_new(ifname); + offset = ripng_offset_list_new(ripng, ifname); yang_dnode_set_entry(dnode, offset); return NB_OK; @@ -299,28 +325,32 @@ ripngd_instance_passive_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return ripng_passive_interface_set(ifname); + return ripng_passive_interface_set(ripng, ifname); } static int ripngd_instance_passive_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + 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); } /* @@ -336,14 +366,16 @@ static int ripngd_instance_redistribute_create(enum nb_event event, 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; } @@ -351,10 +383,13 @@ static int ripngd_instance_redistribute_delete(enum nb_event event, static void ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode) { + struct ripng *ripng; int type; + ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - ripng_redistribute_conf_update(type); + + ripng_redistribute_conf_update(ripng, type); } /* @@ -365,12 +400,14 @@ ripngd_instance_redistribute_route_map_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; int type; const char *rmap_name; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); rmap_name = yang_dnode_get_string(dnode, NULL); @@ -386,11 +423,13 @@ static int 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); @@ -408,12 +447,14 @@ ripngd_instance_redistribute_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; int type; uint8_t metric; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); metric = yang_dnode_get_uint8(dnode, NULL); @@ -427,11 +468,13 @@ static int 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; @@ -447,16 +490,18 @@ static int ripngd_instance_static_route_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; struct prefix_ipv6 p; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv6p(&p, dnode, NULL); apply_mask_ipv6(&p); - ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, - NULL, 0); + ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, + 0, NULL, 0); return NB_OK; } @@ -464,15 +509,18 @@ static int ripngd_instance_static_route_create(enum nb_event event, 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; } @@ -485,15 +533,17 @@ ripngd_instance_aggregate_address_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; struct prefix_ipv6 p; if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv6p(&p, dnode, NULL); apply_mask_ipv6(&p); - ripng_aggregate_add((struct prefix *)&p); + ripng_aggregate_add(ripng, (struct prefix *)&p); return NB_OK; } @@ -502,15 +552,17 @@ static int 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; } @@ -520,8 +572,12 @@ ripngd_instance_aggregate_address_delete(enum nb_event event, */ static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode) { + struct ripng *ripng; + + ripng = yang_dnode_get_entry(dnode, true); + /* Reset update timer thread. */ - ripng_event(RIPNG_UPDATE_EVENT, 0); + ripng_event(ripng, RIPNG_UPDATE_EVENT, 0); } /* @@ -532,9 +588,12 @@ ripngd_instance_timers_flush_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; + if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL); return NB_OK; @@ -548,9 +607,12 @@ ripngd_instance_timers_holddown_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; + if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL); return NB_OK; @@ -564,9 +626,12 @@ ripngd_instance_timers_update_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct ripng *ripng; + if (event != NB_EV_APPLY) return NB_OK; + ripng = yang_dnode_get_entry(dnode, true); ripng->update_time = yang_dnode_get_uint16(dnode, NULL); return NB_OK; @@ -579,8 +644,10 @@ static const void * 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; @@ -609,12 +676,14 @@ static const void * 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; @@ -683,8 +752,10 @@ static const void * 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; @@ -713,11 +784,16 @@ static const void * 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; @@ -786,11 +862,13 @@ ripngd_state_routes_route_metric_get_elem(const char *xpath, 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; @@ -805,7 +883,7 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input, continue; if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete(rp); + ripng_zebra_ipv6_delete(ripng, rp); break; } diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c index 25233f80a..41ba2360b 100644 --- a/ripngd/ripng_offset.c +++ b/ripngd/ripng_offset.c @@ -39,12 +39,14 @@ #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); @@ -53,7 +55,7 @@ struct ripng_offset_list *ripng_offset_list_new(const char *ifname) 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)) @@ -62,7 +64,8 @@ void ripng_offset_list_del(struct ripng_offset_list *offset) XFREE(MTYPE_RIPNG_OFFSET_LIST, offset); } -struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname) +struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng, + const char *ifname) { struct ripng_offset_list *offset; struct listnode *node, *nnode; @@ -76,14 +79,14 @@ struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname) } /* If metric is modifed return 1. */ -int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, - uint8_t *metric) +int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p, + struct interface *ifp, uint8_t *metric) { struct ripng_offset_list *offset; struct access_list *alist; /* Look up offset-list with interface name. */ - offset = ripng_offset_list_lookup(ifp->name); + offset = ripng_offset_list_lookup(ripng, ifp->name); if (offset && OFFSET_LIST_IN_NAME(offset)) { alist = access_list_lookup(AFI_IP6, OFFSET_LIST_IN_NAME(offset)); @@ -97,7 +100,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, return 0; } /* Look up offset-list without interface name. */ - offset = ripng_offset_list_lookup("*"); + offset = ripng_offset_list_lookup(ripng, "*"); if (offset && OFFSET_LIST_IN_NAME(offset)) { alist = access_list_lookup(AFI_IP6, OFFSET_LIST_IN_NAME(offset)); @@ -114,14 +117,14 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, } /* If metric is modifed return 1. */ -int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, - uint8_t *metric) +int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p, + struct interface *ifp, uint8_t *metric) { struct ripng_offset_list *offset; struct access_list *alist; /* Look up offset-list with interface name. */ - offset = ripng_offset_list_lookup(ifp->name); + offset = ripng_offset_list_lookup(ripng, ifp->name); if (offset && OFFSET_LIST_OUT_NAME(offset)) { alist = access_list_lookup(AFI_IP6, OFFSET_LIST_OUT_NAME(offset)); @@ -136,7 +139,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, } /* Look up offset-list without interface name. */ - offset = ripng_offset_list_lookup("*"); + offset = ripng_offset_list_lookup(ripng, "*"); if (offset && OFFSET_LIST_OUT_NAME(offset)) { alist = access_list_lookup(AFI_IP6, OFFSET_LIST_OUT_NAME(offset)); diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index 36c701b86..537600774 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -45,7 +45,7 @@ static void ripng_peer_free(struct ripng_peer *peer) XFREE(MTYPE_RIPNG_PEER, peer); } -struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr) +struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr) { struct ripng_peer *peer; struct listnode *node, *nnode; @@ -57,7 +57,8 @@ struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr) 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; @@ -77,25 +78,27 @@ static int ripng_peer_timeout(struct thread *t) 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); } @@ -110,24 +113,25 @@ static struct ripng_peer *ripng_peer_get(struct in6_addr *addr) return peer; } -void ripng_peer_update(struct sockaddr_in6 *from, uint8_t version) +void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from, + uint8_t version) { struct ripng_peer *peer; - peer = ripng_peer_get(&from->sin6_addr); + peer = ripng_peer_get(ripng, &from->sin6_addr); peer->version = version; } -void ripng_peer_bad_route(struct sockaddr_in6 *from) +void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from) { struct ripng_peer *peer; - peer = ripng_peer_get(&from->sin6_addr); + peer = ripng_peer_get(ripng, &from->sin6_addr); peer->recv_badroutes++; } -void ripng_peer_bad_packet(struct sockaddr_in6 *from) +void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from) { struct ripng_peer *peer; - peer = ripng_peer_get(&from->sin6_addr); + peer = ripng_peer_get(ripng, &from->sin6_addr); peer->recv_badpackets++; } @@ -160,7 +164,7 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len) return buf; } -void ripng_peer_display(struct vty *vty) +void ripng_peer_display(struct vty *vty, struct ripng *ripng) { struct ripng_peer *peer; struct listnode *node, *nnode; diff --git a/ripngd/ripng_route.c b/ripngd/ripng_route.c index f66a0b952..1bf1007fe 100644 --- a/ripngd/ripng_route.c +++ b/ripngd/ripng_route.c @@ -86,7 +86,7 @@ void ripng_aggregate_decrement_list(struct agg_node *child, struct list *list) } /* RIPng routes treatment. */ -int ripng_aggregate_add(struct prefix *p) +int ripng_aggregate_add(struct ripng *ripng, struct prefix *p) { struct agg_node *top; struct agg_node *rp; @@ -124,7 +124,7 @@ int ripng_aggregate_add(struct prefix *p) } /* Delete RIPng static route. */ -int ripng_aggregate_delete(struct prefix *p) +int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p) { struct agg_node *top; struct agg_node *rp; diff --git a/ripngd/ripng_route.h b/ripngd/ripng_route.h index e402f4a66..afc1d1cbc 100644 --- a/ripngd/ripng_route.h +++ b/ripngd/ripng_route.h @@ -48,8 +48,8 @@ extern void ripng_aggregate_decrement(struct agg_node *rp, struct ripng_info *rinfo); extern void ripng_aggregate_decrement_list(struct agg_node *rp, struct list *list); -extern int ripng_aggregate_add(struct prefix *p); -extern int ripng_aggregate_delete(struct prefix *p); +extern int ripng_aggregate_add(struct ripng *ripng, struct prefix *p); +extern int ripng_aggregate_delete(struct ripng *ripng, struct prefix *p); extern void ripng_aggregate_free(struct ripng_aggregate *aggregate); #endif /* _ZEBRA_RIPNG_ROUTE_H */ diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 7b7456197..9e8dd03cb 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -37,7 +37,8 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ -static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd) +static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp, + uint8_t cmd) { struct list *list = (struct list *)rp->info; struct zapi_route api; @@ -47,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd) int count = 0; memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = ripng->vrf_id; api.type = ZEBRA_ROUTE_RIPNG; api.safi = SAFI_UNICAST; api.prefix = rp->p; @@ -57,7 +58,7 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd) if (count >= MULTIPATH_NUM) break; api_nh = &api.nexthops[count]; - api_nh->vrf_id = VRF_DEFAULT; + api_nh->vrf_id = ripng->vrf_id; api_nh->gate.ipv6 = rinfo->nexthop; api_nh->ifindex = rinfo->ifindex; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; @@ -100,25 +101,30 @@ static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd) } /* Add/update ECMP routes to zebra. */ -void ripng_zebra_ipv6_add(struct agg_node *rp) +void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp) { - ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD); + ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ -void ripng_zebra_ipv6_delete(struct agg_node *rp) +void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp) { - ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE); + ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ static int ripng_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { + struct ripng *ripng; struct zapi_route api; struct in6_addr nexthop; unsigned long ifindex; + ripng = ripng_lookup_by_vrf_id(vrf_id); + if (!ripng) + return 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) return -1; @@ -130,60 +136,62 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient, ifindex = api.nexthops[0].ifindex; if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) - ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, + ripng_redistribute_add(ripng, api.type, + RIPNG_ROUTE_REDISTRIBUTE, (struct prefix_ipv6 *)&api.prefix, ifindex, &nexthop, api.tag); else - ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE, - (struct prefix_ipv6 *)&api.prefix, - ifindex); + ripng_redistribute_delete( + ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE, + (struct prefix_ipv6 *)&api.prefix, ifindex); return 0; } -void ripng_redistribute_conf_update(int type) +void ripng_redistribute_conf_update(struct ripng *ripng, int type) { zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, - VRF_DEFAULT); + ripng->vrf_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)); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index fab04a3a1..292b3da6a 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -43,11 +43,6 @@ #include "ripngd/ripng_debug.h" #include "ripngd/ripng_nexthop.h" -/* RIPng structure which includes many parameters related to RIPng - protocol. If ripng couldn't active or ripng doesn't configured, - ripng->fd must be negative value. */ -struct ripng *ripng = NULL; - enum { ripng_all_route, ripng_changed_route, }; @@ -90,6 +85,11 @@ void ripng_info_free(struct ripng_info *rinfo) XFREE(MTYPE_RIPNG_ROUTE, rinfo); } +struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo) +{ + return agg_get_table_info(agg_get_table(rinfo->rp)); +} + /* Create ripng socket. */ int ripng_make_socket(void) { @@ -148,6 +148,8 @@ error: int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to, struct interface *ifp) { + struct ripng_interface *ri = ifp->info; + struct ripng *ripng = ri->ripng; int ret; struct msghdr msg; struct iovec iov; @@ -421,13 +423,14 @@ static int ripng_garbage_collect(struct thread *t) return 0; } -static void ripng_timeout_update(struct ripng_info *rinfo); +static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) +struct ripng_info *ripng_ecmp_add(struct ripng *ripng, + struct ripng_info *rinfo_new) { struct agg_node *rp = rinfo_new->rp; struct ripng_info *rinfo = NULL; @@ -447,8 +450,8 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) listnode_add(list, rinfo); if (ripng_route_rte(rinfo)) { - ripng_timeout_update(rinfo); - ripng_zebra_ipv6_add(rp); + ripng_timeout_update(ripng, rinfo); + ripng_zebra_ipv6_add(ripng, rp); } ripng_aggregate_increment(rp, rinfo); @@ -458,7 +461,7 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); /* Signal the output process to trigger an update. */ - ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); return rinfo; } @@ -466,7 +469,8 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) +struct ripng_info *ripng_ecmp_replace(struct ripng *ripng, + struct ripng_info *rinfo_new) { struct agg_node *rp = rinfo_new->rp; struct list *list = (struct list *)rp->info; @@ -474,7 +478,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) struct listnode *node = NULL, *nextnode = NULL; if (list == NULL || listcount(list) == 0) - return ripng_ecmp_add(rinfo_new); + return ripng_ecmp_add(ripng, rinfo_new); /* Get the first entry */ rinfo = listgetdata(listhead(list)); @@ -482,7 +486,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) /* Learnt route replaced by a local one. Delete it from zebra. */ if (ripng_route_rte(rinfo) && !ripng_route_rte(rinfo_new)) if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete(rp); + ripng_zebra_ipv6_delete(ripng, rp); if (rinfo->metric != RIPNG_METRIC_INFINITY) ripng_aggregate_decrement_list(rp, list); @@ -501,9 +505,9 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) memcpy(rinfo, rinfo_new, sizeof(struct ripng_info)); if (ripng_route_rte(rinfo)) { - ripng_timeout_update(rinfo); + ripng_timeout_update(ripng, rinfo); /* The ADD message implies an update. */ - ripng_zebra_ipv6_add(rp); + ripng_zebra_ipv6_add(ripng, rp); } ripng_aggregate_increment(rp, rinfo); @@ -512,7 +516,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); /* Signal the output process to trigger an update. */ - ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); return rinfo; } @@ -523,7 +527,8 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) +struct ripng_info *ripng_ecmp_delete(struct ripng *ripng, + struct ripng_info *rinfo) { struct agg_node *rp = rinfo->rp; struct list *list = (struct list *)rp->info; @@ -541,7 +546,7 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) if (ripng_route_rte(rinfo) && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) /* The ADD message implies the update. */ - ripng_zebra_ipv6_add(rp); + ripng_zebra_ipv6_add(ripng, rp); ripng_info_free(rinfo); rinfo = NULL; } else { @@ -557,7 +562,7 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) if (ripng_route_rte(rinfo) && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete(rp); + ripng_zebra_ipv6_delete(ripng, rp); } /* Set the route change flag on the first entry. */ @@ -565,7 +570,7 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); /* Signal the output process to trigger an update. */ - ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); return rinfo; } @@ -573,16 +578,20 @@ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) /* Timeout RIPng routes. */ static int ripng_timeout(struct thread *t) { - ripng_ecmp_delete((struct ripng_info *)THREAD_ARG(t)); + struct ripng_info *rinfo = THREAD_ARG(t); + struct ripng *ripng = ripng_info_get_instance(rinfo); + + ripng_ecmp_delete(ripng, rinfo); + return 0; } -static void ripng_timeout_update(struct ripng_info *rinfo) +static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo) { if (rinfo->metric != RIPNG_METRIC_INFINITY) { RIPNG_TIMER_OFF(rinfo->t_timeout); - RIPNG_TIMER_ON(rinfo->t_timeout, ripng_timeout, - ripng->timeout_time); + thread_add_timer(master, ripng_timeout, rinfo, + ripng->timeout_time, &rinfo->t_timeout); } } @@ -670,6 +679,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, struct agg_node *rp; struct ripng_info *rinfo = NULL, newinfo; struct ripng_interface *ri; + struct ripng *ripng; struct in6_addr *nexthop; int same = 0; struct list *list = NULL; @@ -687,9 +697,10 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, apply_mask_ipv6. */ apply_mask_ipv6(&p); - /* Apply input filters. */ ri = ifp->info; + ripng = ri->ripng; + /* Apply input filters. */ ret = ripng_filter(RIPNG_FILTER_IN, &p, ri); if (ret < 0) return; @@ -757,7 +768,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, **/ /* Zebra ripngd can handle offset-list in. */ - ret = ripng_offset_list_apply_in(&p, ifp, &rte->metric); + ret = ripng_offset_list_apply_in(ripng, &p, ifp, &rte->metric); /* If offset-list does not modify the metric use interface's * one. */ @@ -843,7 +854,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, infinity (there is no point in adding a route which unusable). */ if (rte->metric != RIPNG_METRIC_INFINITY) - ripng_ecmp_add(&newinfo); + ripng_ecmp_add(ripng, &newinfo); else agg_unlock_node(rp); } else { @@ -868,7 +879,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, && rinfo->t_timeout && (thread_timer_remain_second(rinfo->t_timeout) < (ripng->timeout_time / 2))) { - ripng_ecmp_replace(&newinfo); + ripng_ecmp_replace(ripng, &newinfo); } /* Next, compare the metrics. If the datagram is from the same router as the existing route, and the new metric is different @@ -878,17 +889,17 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, || rte->metric < rinfo->metric) { if (listcount(list) == 1) { if (newinfo.metric != RIPNG_METRIC_INFINITY) - ripng_ecmp_replace(&newinfo); + ripng_ecmp_replace(ripng, &newinfo); else - ripng_ecmp_delete(rinfo); + ripng_ecmp_delete(ripng, rinfo); } else { if (newinfo.metric < rinfo->metric) - ripng_ecmp_replace(&newinfo); + ripng_ecmp_replace(ripng, &newinfo); else /* newinfo.metric > rinfo->metric */ - ripng_ecmp_delete(rinfo); + ripng_ecmp_delete(ripng, rinfo); } } else /* same & no change */ - ripng_timeout_update(rinfo); + ripng_timeout_update(ripng, rinfo); /* Unlock tempolary lock of the route. */ agg_unlock_node(rp); @@ -896,9 +907,9 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, } /* Add redistributed route to RIPng table. */ -void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, - ifindex_t ifindex, struct in6_addr *nexthop, - route_tag_t tag) +void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type, + struct prefix_ipv6 *p, ifindex_t ifindex, + struct in6_addr *nexthop, route_tag_t tag) { struct agg_node *rp; struct ripng_info *rinfo = NULL, newinfo; @@ -947,31 +958,31 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, } } - ripng_ecmp_replace(&newinfo); + ripng_ecmp_replace(ripng, &newinfo); agg_unlock_node(rp); } else - ripng_ecmp_add(&newinfo); + ripng_ecmp_add(ripng, &newinfo); if (IS_RIPNG_DEBUG_EVENT) { if (!nexthop) zlog_debug( "Redistribute new prefix %s/%d on the interface %s", inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); + ifindex2ifname(ifindex, ripng->vrf_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; @@ -1010,9 +1021,9 @@ void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, 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); @@ -1020,7 +1031,7 @@ void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, } /* Withdraw redistributed route. */ -void ripng_redistribute_withdraw(int type) +void ripng_redistribute_withdraw(struct ripng *ripng, int type) { struct agg_node *rp; struct ripng_info *rinfo = NULL; @@ -1052,10 +1063,10 @@ void ripng_redistribute_withdraw(int type) 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); } } } @@ -1065,6 +1076,8 @@ static void ripng_response_process(struct ripng_packet *packet, int size, struct sockaddr_in6 *from, struct interface *ifp, int hoplimit) { + struct ripng_interface *ri = ifp->info; + struct ripng *ripng = ri->ripng; caddr_t lim; struct rte *rte; struct ripng_nexthop nexthop; @@ -1074,7 +1087,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, if (ntohs(from->sin6_port) != RIPNG_PORT_DEFAULT) { zlog_warn("RIPng packet comes from non RIPng port %d from %s", ntohs(from->sin6_port), inet6_ntoa(from->sin6_addr)); - ripng_peer_bad_packet(from); + ripng_peer_bad_packet(ripng, from); return; } @@ -1084,7 +1097,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) { zlog_warn("RIPng packet comes from non link local address %s", inet6_ntoa(from->sin6_addr)); - ripng_peer_bad_packet(from); + ripng_peer_bad_packet(ripng, from); return; } @@ -1097,7 +1110,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, zlog_warn( "RIPng packet comes from my own link local address %s", inet6_ntoa(from->sin6_addr)); - ripng_peer_bad_packet(from); + ripng_peer_bad_packet(ripng, from); return; } @@ -1109,12 +1122,12 @@ static void ripng_response_process(struct ripng_packet *packet, int size, zlog_warn( "RIPng packet comes with non 255 hop count %d from %s", hoplimit, inet6_ntoa(from->sin6_addr)); - ripng_peer_bad_packet(from); + ripng_peer_bad_packet(ripng, from); return; } /* Update RIPng peer. */ - ripng_peer_update(from, packet->version); + ripng_peer_update(ripng, from, packet->version); /* Reset nexthop. */ memset(&nexthop, 0, sizeof(struct ripng_nexthop)); @@ -1142,7 +1155,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, "Destination prefix is a multicast address %s/%d [%d]", inet6_ntoa(rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route(from); + ripng_peer_bad_route(ripng, from); continue; } if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) { @@ -1150,7 +1163,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, "Destination prefix is a link-local address %s/%d [%d]", inet6_ntoa(rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route(from); + ripng_peer_bad_route(ripng, from); continue; } if (IN6_IS_ADDR_LOOPBACK(&rte->addr)) { @@ -1158,7 +1171,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, "Destination prefix is a loopback address %s/%d [%d]", inet6_ntoa(rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route(from); + ripng_peer_bad_route(ripng, from); continue; } @@ -1168,7 +1181,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, zlog_warn("Invalid prefix length %s/%d from %s%%%s", inet6_ntoa(rte->addr), rte->prefixlen, inet6_ntoa(from->sin6_addr), ifp->name); - ripng_peer_bad_route(from); + ripng_peer_bad_route(ripng, from); continue; } @@ -1176,7 +1189,7 @@ static void ripng_response_process(struct ripng_packet *packet, int size, if (!(rte->metric >= 1 && rte->metric <= 16)) { zlog_warn("Invalid metric %d from %s%%%s", rte->metric, inet6_ntoa(from->sin6_addr), ifp->name); - ripng_peer_bad_route(from); + ripng_peer_bad_route(ripng, from); continue; } @@ -1194,6 +1207,7 @@ static void ripng_request_process(struct ripng_packet *packet, int size, struct sockaddr_in6 *from, struct interface *ifp) { + struct ripng *ripng; caddr_t lim; struct rte *rte; struct prefix_ipv6 p; @@ -1209,13 +1223,14 @@ static void ripng_request_process(struct ripng_packet *packet, int size, ri = ifp->info; if (!ri->running) return; + ripng = ri->ripng; /* When passive interface is specified, suppress responses */ if (ri->passive) return; /* RIPng peer update. */ - ripng_peer_update(from, packet->version); + ripng_peer_update(ripng, from, packet->version); lim = ((caddr_t)packet) + size; rte = packet->rte; @@ -1272,6 +1287,7 @@ static void ripng_request_process(struct ripng_packet *packet, int size, /* First entry point of reading RIPng packet. */ static int ripng_read(struct thread *thread) { + struct ripng *ripng = THREAD_ARG(thread); int len; int sock; struct sockaddr_in6 from; @@ -1290,7 +1306,7 @@ static int ripng_read(struct thread *thread) ripng->t_read = NULL; /* Add myself to the next event. */ - ripng_event(RIPNG_READ, sock); + ripng_event(ripng, RIPNG_READ, sock); /* Read RIPng packet. */ len = ripng_recv_packet(sock, STREAM_DATA(ripng->ibuf), @@ -1306,12 +1322,12 @@ static int ripng_read(struct thread *thread) 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) @@ -1335,7 +1351,7 @@ static int ripng_read(struct thread *thread) 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; } @@ -1349,14 +1365,14 @@ static int ripng_read(struct thread *thread) 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; @@ -1377,7 +1393,8 @@ static void ripng_clear_changed_flag(void) enabled interface. */ static int ripng_update(struct thread *t) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct ripng *ripng = THREAD_ARG(t); + struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; struct ripng_interface *ri; @@ -1425,7 +1442,7 @@ static int ripng_update(struct thread *t) ripng->trigger = 0; /* Reset flush event. */ - ripng_event(RIPNG_UPDATE_EVENT, 0); + ripng_event(ripng, RIPNG_UPDATE_EVENT, 0); return 0; } @@ -1433,6 +1450,8 @@ static int ripng_update(struct thread *t) /* Triggered update interval timer. */ static int ripng_triggered_interval(struct thread *t) { + struct ripng *ripng = THREAD_ARG(t); + ripng->t_triggered_interval = NULL; if (ripng->trigger) { @@ -1445,7 +1464,8 @@ static int ripng_triggered_interval(struct thread *t) /* Execute triggered update. */ int ripng_triggered_update(struct thread *t) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct ripng *ripng = THREAD_ARG(t); + struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; struct ripng_interface *ri; int interval; @@ -1484,7 +1504,7 @@ int ripng_triggered_update(struct thread *t) /* Once all of the triggered updates have been generated, the route change flags should be cleared. */ - ripng_clear_changed_flag(); + ripng_clear_changed_flag(ripng); /* After a triggered update is sent, a timer should be set for a random interval between 1 and 5 seconds. If other changes that @@ -1493,7 +1513,7 @@ int ripng_triggered_update(struct thread *t) interval = (random() % 5) + 1; ripng->t_triggered_interval = NULL; - thread_add_timer(master, ripng_triggered_interval, NULL, interval, + thread_add_timer(master, ripng_triggered_interval, ripng, interval, &ripng->t_triggered_interval); return 0; @@ -1531,6 +1551,7 @@ int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p, void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, int route_type) { + struct ripng *ripng; int ret; struct agg_node *rp; struct ripng_info *rinfo; @@ -1550,8 +1571,9 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, ifp->name); } - /* Get RIPng interface. */ + /* Get RIPng interface and instance. */ ri = ifp->info; + ripng = ri->ripng; ripng_rte_list = ripng_rte_new(); @@ -1670,7 +1692,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, /* Apply offset-list */ if (rinfo->metric_out != RIPNG_METRIC_INFINITY) - ripng_offset_list_apply_out(p, ifp, + ripng_offset_list_apply_out(ripng, p, ifp, &rinfo->metric_out); if (rinfo->metric_out > RIPNG_METRIC_INFINITY) @@ -1763,7 +1785,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, /* Apply offset-list */ if (aggregate->metric_out != RIPNG_METRIC_INFINITY) ripng_offset_list_apply_out( - p, ifp, &aggregate->metric_out); + ripng, p, ifp, &aggregate->metric_out); if (aggregate->metric_out > RIPNG_METRIC_INFINITY) aggregate->metric_out = RIPNG_METRIC_INFINITY; @@ -1778,11 +1800,22 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, ripng_rte_free(ripng_rte_list); } +struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id) +{ + struct vrf *vrf; + + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) + return NULL; + + return vrf->info; +} + /* 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)); @@ -1805,6 +1838,7 @@ int ripng_create(int socket) /* 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; @@ -1828,10 +1862,20 @@ int ripng_create(int socket) 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. */ @@ -1868,13 +1912,14 @@ static int ripng_update_jitter(int time) return ((random() % (time + 1)) - (time / 2)); } -void ripng_event(enum ripng_event event, int sock) +void ripng_event(struct ripng *ripng, enum ripng_event event, int sock) { int jitter = 0; switch (event) { case RIPNG_READ: - thread_add_read(master, ripng_read, NULL, sock, &ripng->t_read); + thread_add_read(master, ripng_read, ripng, sock, + &ripng->t_read); break; case RIPNG_UPDATE_EVENT: if (ripng->t_update) { @@ -1885,7 +1930,7 @@ void ripng_event(enum ripng_event event, int sock) jitter = ripng_update_jitter(ripng->update_time); ripng->t_update = NULL; - thread_add_timer(master, ripng_update, NULL, + thread_add_timer(master, ripng_update, ripng, sock ? 2 : ripng->update_time + jitter, &ripng->t_update); break; @@ -1893,7 +1938,7 @@ void ripng_event(enum ripng_event event, int sock) if (ripng->t_triggered_interval) ripng->trigger = 1; else - thread_add_event(master, ripng_triggered_update, NULL, + thread_add_event(master, ripng_triggered_update, ripng, 0, &ripng->t_triggered_update); break; default: @@ -1963,6 +2008,7 @@ DEFUN (show_ipv6_ripng, IPV6_STR "Show RIPng routes\n") { + struct ripng *ripng; struct agg_node *rp; struct ripng_info *rinfo; struct ripng_aggregate *aggregate; @@ -1971,6 +2017,7 @@ DEFUN (show_ipv6_ripng, struct listnode *listnode = NULL; int len; + ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT); if (!ripng) return CMD_SUCCESS; @@ -2033,7 +2080,7 @@ DEFUN (show_ipv6_ripng, 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"); @@ -2073,9 +2120,11 @@ DEFUN (show_ipv6_ripng_status, "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; @@ -2097,7 +2146,7 @@ DEFUN (show_ipv6_ripng_status, /* Redistribute information. */ vty_out(vty, " Redistributing:"); - ripng_redistribute_write(vty); + ripng_redistribute_write(vty, ripng); vty_out(vty, "\n"); vty_out(vty, " Default version control: send version %d,", @@ -2106,6 +2155,7 @@ DEFUN (show_ipv6_ripng_status, vty_out(vty, " Interface Send Recv\n"); + vrf = vrf_lookup_by_id(ripng->vrf_id); FOR_ALL_INTERFACES (vrf, ifp) { struct ripng_interface *ri; @@ -2119,12 +2169,12 @@ DEFUN (show_ipv6_ripng_status, } vty_out(vty, " Routing for Networks:\n"); - ripng_network_write(vty); + ripng_network_write(vty, ripng); vty_out(vty, " Routing Information Sources:\n"); vty_out(vty, " Gateway BadPackets BadRoutes Distance Last Update\n"); - ripng_peer_display(vty); + ripng_peer_display(vty, ripng); return CMD_SUCCESS; } @@ -2260,7 +2310,7 @@ DEFUN (show_ipv6_protocols, #endif /* Update ECMP routes to zebra when ECMP is disabled. */ -void ripng_ecmp_disable(void) +void ripng_ecmp_disable(struct ripng *ripng) { struct agg_node *rp; struct ripng_info *rinfo, *tmp_rinfo; @@ -2287,13 +2337,13 @@ void ripng_ecmp_disable(void) } /* Update zebra. */ - ripng_zebra_ipv6_add(rp); + ripng_zebra_ipv6_add(ripng, rp); /* Set the route change flag. */ SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); /* Signal the output process to trigger an update. */ - ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); } } @@ -2306,12 +2356,15 @@ static int ripng_config_write(struct vty *vty) 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; } @@ -2409,8 +2462,10 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused) } /* 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 */ @@ -2424,7 +2479,7 @@ void ripng_clean() 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); @@ -2471,14 +2526,24 @@ void ripng_clean() 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); } @@ -2523,29 +2588,27 @@ void ripng_if_rmap_update_interface(struct interface *ifp) 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. */ diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 164fb3782..95039bf57 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -89,6 +89,9 @@ /* RIPng structure. */ struct ripng { + /* VRF ID. */ + vrf_id_t vrf_id; + /* RIPng socket. */ int sock; @@ -247,6 +250,9 @@ typedef enum { /* RIPng specific interface configuration. */ struct ripng_interface { + /* Parent routing instance. */ + struct ripng *ripng; + /* RIPng is enabled on this interface. */ int enable_network; int enable_interface; @@ -293,6 +299,9 @@ struct ripng_interface { /* RIPng peer information. */ struct ripng_peer { + /* Parent routing instance. */ + struct ripng *ripng; + /* Peer address. */ struct in6_addr addr; @@ -338,6 +347,9 @@ enum ripng_event { #define RIPNG_OFFSET_LIST_MAX 2 struct ripng_offset_list { + /* Parent routing instance. */ + struct ripng *ripng; + char *ifname; struct { @@ -348,72 +360,83 @@ struct ripng_offset_list { }; /* 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, @@ -437,13 +460,17 @@ extern int ripng_interface_address_add(int command, struct zclient *, 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); |