*/
extern struct list *yang_data_list_new(void);
+/*
+ * Find the yang_data structure corresponding to an XPath in a list.
+ *
+ * list
+ * list of yang_data structures to operate on.
+ *
+ * xpath_fmt
+ * XPath to search for (format string).
+ *
+ * Returns:
+ * Pointer to yang_data if found, NULL otherwise.
+ */
+extern struct yang_data *yang_data_list_find(const struct list *list,
+ const char *xpath_fmt, ...);
+
+ /*
+ * Create and set up a libyang context (for use by the translator)
+ */
+ extern struct ly_ctx *yang_ctx_new_setup(void);
+
/*
* Initialize the YANG subsystem. Should be called only once during the
* daemon initialization process.
DEFPY (no_router_rip,
no_router_rip_cmd,
- "no router rip",
+ "no router rip [vrf NAME]",
NO_STR
"Enable a routing process\n"
- "Routing Information Protocol (RIP)\n")
+ "Routing Information Protocol (RIP)\n"
+ VRF_CMD_HELP_STR)
{
- nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_DESTROY,
- NULL);
+ char xpath[XPATH_MAXLEN];
+
+ /* Build RIP instance XPath. */
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
+ snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
+ vrf);
+
- nb_cli_enqueue_change(vty, xpath, NB_OP_DELETE, NULL);
++ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
"Authentication string\n"
"Authentication string\n")
{
- nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DELETE,
- nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
++ nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
#include "sigevent.h"
#include "zclient.h"
#include "vrf.h"
++#include "if_rmap.h"
#include "libfrr.h"
#include "ripd/ripd.h"
{
zlog_notice("Terminating on signal");
- rip_clean();
-
+ rip_vrf_terminate();
++ if_rmap_terminate();
rip_zclient_stop();
frr_fini();
{
.xpath = "/frr-ripd:ripd/instance",
.cbs.create = ripd_instance_create,
- .cbs.delete = ripd_instance_delete,
+ .cbs.destroy = ripd_instance_delete,
+ .cbs.get_next = ripd_instance_get_next,
+ .cbs.get_keys = ripd_instance_get_keys,
+ .cbs.lookup_entry = ripd_instance_lookup_entry,
.cbs.cli_show = cli_show_router_rip,
},
{
rip->version_recv =
yang_get_default_enum("%s/version/receive", RIP_INSTANCE);
- /* Initialize RIP routig table. */
+ /* Initialize RIP data structures. */
rip->table = route_table_init();
+ route_table_set_info(rip->table, rip);
rip->neighbor = route_table_init();
+ rip->peer_list = list_new();
+ rip->peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp;
+ rip->peer_list->del = rip_peer_list_del;
+ rip->distance_table = route_table_init();
+ rip->distance_table->cleanup = rip_distance_table_node_cleanup;
+ rip->enable_interface = vector_init(1);
+ rip->enable_network = route_table_init();
+ rip->passive_nondefault = vector_init(1);
+ rip->offset_list_master = list_new();
+ rip->offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
+ rip->offset_list_master->del = (void (*)(void *))offset_list_del;
- /* Make output stream. */
- rip->obuf = stream_new(1500);
-
- /* Set socket. */
- rip->sock = socket;
-
- /* Create read and timer thread. */
- rip_event(RIP_READ, rip->sock);
- rip_event(RIP_UPDATE_EVENT, 1);
/* Distribute list install. */
- rip->distribute_ctx = distribute_list_ctx_create(
- vrf_lookup_by_id(VRF_DEFAULT));
- distribute_list_add_hook(rip->distribute_ctx,
- rip_distribute_update);
- distribute_list_delete_hook(rip->distribute_ctx,
- rip_distribute_update);
+ rip->distribute_ctx = distribute_list_ctx_create(vrf);
+ distribute_list_add_hook(rip->distribute_ctx, rip_distribute_update);
+ distribute_list_delete_hook(rip->distribute_ctx, rip_distribute_update);
- rip->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ /* if rmap install. */
- return 0;
++ rip->if_rmap_ctx = if_rmap_ctx_create(vrf_name);
+ if_rmap_hook_add(rip->if_rmap_ctx, rip_if_rmap_update);
+ if_rmap_hook_delete(rip->if_rmap_ctx, rip_if_rmap_update);
+
+ /* Make output stream. */
+ rip->obuf = stream_new(1500);
+
+ /* Enable the routing instance if possible. */
+ if (vrf && vrf_is_enabled(vrf))
+ rip_instance_enable(rip, vrf, socket);
+ else {
+ rip->vrf = NULL;
+ rip->sock = -1;
+ }
+
+ RB_INSERT(rip_instance_head, &rip_instances, rip);
+
+ return rip;
}
/* Sned RIP request to the destination. */
nb_cli_show_dnode_cmds(vty, dnode, false);
/* Distribute configuration. */
- write += config_write_distribute(vty,
- rip->distribute_ctx);
+ config_write_distribute(vty, rip->distribute_ctx);
/* Interface routemap configuration */
- if (strmatch(rip->vrf_name, VRF_DEFAULT_NAME))
- config_write_if_rmap(vty);
- write += config_write_if_rmap(vty, rip->if_rmap_ctx);
++ config_write_if_rmap(vty, rip->if_rmap_ctx);
+
+ write = 1;
}
+
return write;
}
}
/* Delete all added rip route. */
-void rip_clean(void)
+void rip_clean(struct rip *rip)
{
- int i;
- struct route_node *rp;
- struct rip_info *rinfo = NULL;
- struct list *list = NULL;
- struct listnode *listnode = NULL;
-
- if (rip) {
- /* Clear RIP routes */
- for (rp = route_top(rip->table); rp; rp = route_next(rp))
- if ((list = rp->info) != NULL) {
- rinfo = listgetdata(listhead(list));
- if (rip_route_rte(rinfo))
- rip_zebra_ipv4_delete(rp);
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode,
- rinfo)) {
- RIP_TIMER_OFF(rinfo->t_timeout);
- RIP_TIMER_OFF(rinfo->t_garbage_collect);
- rip_info_free(rinfo);
- }
- list_delete(&list);
- rp->info = NULL;
- route_unlock_node(rp);
- }
-
- /* Cancel RIP related timers. */
- RIP_TIMER_OFF(rip->t_update);
- RIP_TIMER_OFF(rip->t_triggered_update);
- RIP_TIMER_OFF(rip->t_triggered_interval);
-
- /* Cancel read thread. */
- THREAD_READ_OFF(rip->t_read);
-
- /* Close RIP socket. */
- if (rip->sock >= 0) {
- close(rip->sock);
- rip->sock = -1;
- }
-
- stream_free(rip->obuf);
-
- /* RIP neighbor configuration. */
- for (rp = route_top(rip->neighbor); rp; rp = route_next(rp))
- if (rp->info) {
- rp->info = NULL;
- route_unlock_node(rp);
- }
+ if (rip->enabled)
+ rip_instance_disable(rip);
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (rip->route_map[i].name)
- free(rip->route_map[i].name);
+ stream_free(rip->obuf);
- route_table_finish(rip->table);
- route_table_finish(rip->neighbor);
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (rip->redist[i].route_map.name)
+ free(rip->redist[i].route_map.name);
- distribute_list_delete(&rip->distribute_ctx);
+ route_table_finish(rip->table);
+ route_table_finish(rip->neighbor);
+ list_delete(&rip->peer_list);
+ distribute_list_delete(&rip->distribute_ctx);
++ if_rmap_ctx_delete(rip->if_rmap_ctx);
- if_rmap_ctx_delete(rip->if_rmap_ctx);
+ rip_clean_network(rip);
+ rip_passive_nondefault_clean(rip);
+ vector_free(rip->enable_interface);
+ route_table_finish(rip->enable_network);
+ vector_free(rip->passive_nondefault);
+ list_delete(&rip->offset_list_master);
+ rip_interfaces_clean(rip);
+ route_table_finish(rip->distance_table);
- XFREE(MTYPE_RIP, rip);
- rip = NULL;
- }
- rip_clean_network();
- rip_passive_nondefault_clean();
- rip_offset_clean();
- rip_interfaces_clean();
- rip_distance_reset();
- rip_redistribute_clean();
- if_rmap_terminate();
+ RB_REMOVE(rip_instance_head, &rip_instances, rip);
+ XFREE(MTYPE_RIP_VRF_NAME, rip->vrf_name);
+ XFREE(MTYPE_RIP, rip);
}
- static void rip_if_rmap_update(struct if_rmap *if_rmap)
+ static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct rip_interface *ri;
struct route_map *rmap;
+ struct vrf *vrf = NULL;
- ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+ if (ctx->name)
+ vrf = vrf_lookup_by_name(ctx->name);
+ if (vrf)
+ ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
if (ifp == NULL)
return;
void rip_if_rmap_update_interface(struct interface *ifp)
{
++ struct rip_interface *ri = ifp->info;
++ struct rip *rip = ri->rip;
struct if_rmap *if_rmap;
+ struct if_rmap_ctx *ctx;
- if_rmap = if_rmap_lookup(ifp->name);
+ if (!rip)
+ return;
- if (ifp->vrf_id != VRF_DEFAULT)
- return;
+ ctx = rip->if_rmap_ctx;
+ if (!ctx)
+ return;
+ if_rmap = if_rmap_lookup(ctx, ifp->name);
if (if_rmap)
- rip_if_rmap_update(if_rmap);
+ rip_if_rmap_update(ctx, if_rmap);
}
-static void rip_routemap_update_redistribute(void)
+static void rip_routemap_update_redistribute(struct rip *rip)
{
- int i;
-
- if (rip) {
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (rip->route_map[i].name) {
- rip->route_map[i].map =
- route_map_lookup_by_name(
- rip->route_map[i].name);
- route_map_counter_increment(
- rip->route_map[i].map);
- }
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (rip->redist[i].route_map.name)
++ if (rip->redist[i].route_map.name) {
+ rip->redist[i].route_map.map = route_map_lookup_by_name(
+ rip->redist[i].route_map.name);
++ route_map_counter_increment(
++ rip->redist[i].route_map.map);
+ }
}
}
route_map_delete_hook(rip_routemap_update);
if_rmap_init(RIP_NODE);
- if_rmap_hook_add(rip_if_rmap_update);
- if_rmap_hook_delete(rip_if_rmap_update);
-
- /* Distance control. */
- rip_distance_table = route_table_init();
}
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
+ /* For if_rmap container */
+ struct if_rmap_ctx *if_rmap_ctx;
++
+ /* Counters for SNMP. */
+ struct {
+ /* RIP route changes. */
+ long route_changes;
+
+ /* RIP queries. */
+ long queries;
+ } counters;
};
+RB_HEAD(rip_instance_head, rip);
+RB_PROTOTYPE(rip_instance_head, rip, entry, rip_instance_compare)
/* RIP routing table entry which belong to rip_packet. */
struct rte {
extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
struct connected *);
-extern int rip_neighbor_lookup(struct sockaddr_in *);
-extern int rip_neighbor_add(struct prefix_ipv4 *p);
-extern int rip_neighbor_delete(struct prefix_ipv4 *p);
-
-extern int rip_enable_network_add(struct prefix *p);
-extern int rip_enable_network_delete(struct prefix *p);
-extern int rip_enable_if_add(const char *ifname);
-extern int rip_enable_if_delete(const char *ifname);
-
-extern void rip_event(enum rip_event, int);
-extern void rip_ecmp_disable(void);
-
-extern int rip_create_socket(void);
-
-extern int rip_redistribute_check(int);
-extern void rip_redistribute_conf_update(int type);
-extern void rip_redistribute_conf_delete(int type);
-extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
- struct nexthop *nh, unsigned int metric,
- unsigned char distance, route_tag_t tag);
-extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t);
-extern void rip_redistribute_withdraw(int);
-extern void rip_zebra_ipv4_add(struct route_node *);
-extern void rip_zebra_ipv4_delete(struct route_node *);
+extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from);
+extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p);
+extern int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p);
+
+extern int rip_enable_network_add(struct rip *rip, struct prefix *p);
+extern int rip_enable_network_delete(struct rip *rip, struct prefix *p);
+extern int rip_enable_if_add(struct rip *rip, const char *ifname);
+extern int rip_enable_if_delete(struct rip *rip, const char *ifname);
+
+extern void rip_event(struct rip *rip, enum rip_event event, int sock);
+extern void rip_ecmp_disable(struct rip *rip);
+
+extern int rip_create_socket(struct vrf *vrf);
+
+extern int rip_redistribute_check(struct rip *rip, int type);
+extern void rip_redistribute_conf_update(struct rip *rip, int type);
+extern void rip_redistribute_conf_delete(struct rip *rip, int type);
+extern void rip_redistribute_add(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, struct nexthop *nh,
+ unsigned int metric, unsigned char distance,
+ route_tag_t tag);
+extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
+ struct prefix_ipv4 *p, ifindex_t ifindex);
+extern void rip_redistribute_withdraw(struct rip *rip, int type);
+extern void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp);
+extern void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp);
extern void rip_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *);
- extern void rip_if_rmap_update_interface(struct interface *);
+ extern void rip_if_rmap_update_interface(struct interface *ifp);
-extern int rip_show_network_config(struct vty *);
-extern void rip_show_redistribute_config(struct vty *);
-extern void rip_peer_init(void);
-extern void rip_peer_update(struct sockaddr_in *, uint8_t);
-extern void rip_peer_bad_route(struct sockaddr_in *);
-extern void rip_peer_bad_packet(struct sockaddr_in *);
-extern void rip_peer_display(struct vty *);
-extern struct rip_peer *rip_peer_lookup(struct in_addr *);
-extern struct rip_peer *rip_peer_lookup_next(struct in_addr *);
+extern int rip_show_network_config(struct vty *vty, struct rip *rip);
+extern void rip_show_redistribute_config(struct vty *vty, struct rip *rip);
+
+extern void rip_peer_update(struct rip *rip, struct sockaddr_in *from,
+ uint8_t version);
+extern void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from);
+extern void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from);
+extern void rip_peer_display(struct vty *vty, struct rip *rip);
+extern struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr);
+extern struct rip_peer *rip_peer_lookup_next(struct rip *rip,
+ struct in_addr *addr);
+extern int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2);
+extern void rip_peer_list_del(void *arg);
extern void rip_info_free(struct rip_info *);
+extern struct rip *rip_info_get_instance(const struct rip_info *rinfo);
extern struct rip_distance *rip_distance_new(void);
extern void rip_distance_free(struct rip_distance *rdistance);
-extern uint8_t rip_distance_apply(struct rip_info *);
-extern void rip_redistribute_clean(void);
+extern uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo);
+extern void rip_redistribute_enable(struct rip *rip);
+extern void rip_redistribute_disable(struct rip *rip);
extern int rip_route_rte(struct rip_info *rinfo);
-extern struct rip_info *rip_ecmp_add(struct rip_info *);
-extern struct rip_info *rip_ecmp_replace(struct rip_info *);
-extern struct rip_info *rip_ecmp_delete(struct rip_info *);
-
-extern struct rip_offset_list *rip_offset_list_new(const char *ifname);
+extern struct rip_info *rip_ecmp_add(struct rip *rip,
+ struct rip_info *rinfo_new);
+extern struct rip_info *rip_ecmp_replace(struct rip *rip,
+ struct rip_info *rinfo_new);
+extern struct rip_info *rip_ecmp_delete(struct rip *rip,
+ struct rip_info *rinfo);
+
+extern struct rip_offset_list *rip_offset_list_new(struct rip *rip,
+ const char *ifname);
extern void offset_list_del(struct rip_offset_list *offset);
-extern struct rip_offset_list *rip_offset_list_lookup(const char *ifname);
+extern struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
+ const char *ifname);
extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *,
uint32_t *);
extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *,
DEFPY (no_router_ripng,
no_router_ripng_cmd,
- "no router ripng",
+ "no router ripng [vrf NAME]",
NO_STR
"Enable a routing process\n"
- "Make RIPng instance command\n")
+ "Make RIPng instance command\n"
+ VRF_CMD_HELP_STR)
{
- nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DESTROY,
- NULL);
+ char xpath[XPATH_MAXLEN];
+
+ /* Build RIPng instance XPath. */
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
+ snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
+ vrf);
+
- nb_cli_enqueue_change(vty, xpath, NB_OP_DELETE, NULL);
++ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
#include "privs.h"
#include "sigevent.h"
#include "vrf.h"
++#include "if_rmap.h"
#include "libfrr.h"
#include "ripngd/ripngd.h"
{
zlog_notice("Terminating on signal");
- ripng_clean();
-
+ ripng_vrf_terminate();
++ if_rmap_terminate();
ripng_zebra_stop();
frr_fini();
exit(0);
{
.xpath = "/frr-ripngd:ripngd/instance",
.cbs.create = ripngd_instance_create,
- .cbs.delete = ripngd_instance_delete,
+ .cbs.destroy = ripngd_instance_delete,
+ .cbs.get_next = ripngd_instance_get_next,
+ .cbs.get_keys = ripngd_instance_get_keys,
+ .cbs.lookup_entry = ripngd_instance_lookup_entry,
.cbs.cli_show = cli_show_router_ripng,
},
{
/* Prototypes. */
void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
-
+static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
+ int sock);
+static void ripng_instance_disable(struct ripng *ripng);
-
int ripng_triggered_update(struct thread *);
-
+ static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap);
+/* Generate rb-tree of RIPng instances. */
+static inline int ripng_instance_compare(const struct ripng *a,
+ const struct ripng *b)
+{
+ return strcmp(a->vrf_name, b->vrf_name);
+}
+RB_GENERATE(ripng_instance_head, ripng, entry, ripng_instance_compare)
+
+struct ripng_instance_head ripng_instances = RB_INITIALIZER(&ripng_instances);
+
/* RIPng next hop specification. */
struct ripng_nexthop {
enum ripng_nexthop_type {
distribute_list_delete_hook(ripng->distribute_ctx,
ripng_distribute_update);
- ripng->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ /* if rmap install. */
++ ripng->if_rmap_ctx = if_rmap_ctx_create(vrf_name);
+ if_rmap_hook_add(ripng->if_rmap_ctx, ripng_if_rmap_update);
+ if_rmap_hook_delete(ripng->if_rmap_ctx, ripng_if_rmap_update);
- /* Make socket. */
- ripng->sock = socket;
+ /* Enable the routing instance if possible. */
+ if (vrf && vrf_is_enabled(vrf))
+ ripng_instance_enable(ripng, vrf, socket);
+ else {
+ ripng->vrf = NULL;
+ ripng->sock = -1;
+ }
- /* Threads. */
- ripng_event(RIPNG_READ, ripng->sock);
- ripng_event(RIPNG_UPDATE_EVENT, 1);
+ RB_INSERT(ripng_instance_head, &ripng_instances, ripng);
- return 0;
+ return ripng;
}
/* Send RIPng request to the interface. */
/* RIPng configuration write function. */
static int ripng_config_write(struct vty *vty)
{
- struct lyd_node *dnode;
+ struct ripng *ripng;
int write = 0;
- dnode = yang_dnode_get(running_config->dnode,
- "/frr-ripngd:ripngd/instance");
- if (dnode) {
- nb_cli_show_dnode_cmds(vty, dnode, false);
+ RB_FOREACH(ripng, ripng_instance_head, &ripng_instances) {
+ char xpath[XPATH_MAXLEN];
+ struct lyd_node *dnode;
- config_write_distribute(vty,
- ripng->distribute_ctx);
+ snprintf(xpath, sizeof(xpath),
+ "/frr-ripngd:ripngd/instance[vrf='%s']",
+ ripng->vrf_name);
- if (strmatch(ripng->vrf_name, VRF_DEFAULT_NAME))
- config_write_if_rmap(vty);
+ dnode = yang_dnode_get(running_config->dnode, xpath);
+ assert(dnode);
+
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+
+ config_write_distribute(vty, ripng->distribute_ctx);
+ config_write_if_rmap(vty, ripng->if_rmap_ctx);
write = 1;
}
}
/* delete all the added ripng routes. */
-void ripng_clean(void)
+void ripng_clean(struct ripng *ripng)
{
- int i;
- struct agg_node *rp;
- struct ripng_info *rinfo;
- struct ripng_aggregate *aggregate;
- struct list *list = NULL;
- struct listnode *listnode = NULL;
-
- if (ripng) {
- /* Clear RIPng routes */
- for (rp = agg_route_top(ripng->table); rp;
- rp = agg_route_next(rp)) {
- if ((list = rp->info) != NULL) {
- rinfo = listgetdata(listhead(list));
- if (ripng_route_rte(rinfo))
- ripng_zebra_ipv6_delete(rp);
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode,
- rinfo)) {
- RIPNG_TIMER_OFF(rinfo->t_timeout);
- RIPNG_TIMER_OFF(
- rinfo->t_garbage_collect);
- ripng_info_free(rinfo);
- }
- list_delete(&list);
- rp->info = NULL;
- agg_unlock_node(rp);
- }
-
- if ((aggregate = rp->aggregate) != NULL) {
- ripng_aggregate_free(aggregate);
- rp->aggregate = NULL;
- agg_unlock_node(rp);
- }
- }
-
- /* Cancel the RIPng timers */
- RIPNG_TIMER_OFF(ripng->t_update);
- RIPNG_TIMER_OFF(ripng->t_triggered_update);
- RIPNG_TIMER_OFF(ripng->t_triggered_interval);
-
- /* Cancel the read thread */
- if (ripng->t_read) {
- thread_cancel(ripng->t_read);
- ripng->t_read = NULL;
- }
-
- /* Close the RIPng socket */
- if (ripng->sock >= 0) {
- close(ripng->sock);
- ripng->sock = -1;
- }
-
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (ripng->route_map[i].name)
- free(ripng->route_map[i].name);
-
- agg_table_finish(ripng->table);
-
- stream_free(ripng->ibuf);
- stream_free(ripng->obuf);
-
- distribute_list_delete(&ripng->distribute_ctx);
- XFREE(MTYPE_RIPNG, ripng);
- ripng = NULL;
- } /* if (ripng) */
-
- ripng_clean_network();
- ripng_passive_interface_clean();
- ripng_offset_clean();
- ripng_interface_clean();
- ripng_redistribute_clean();
- if_rmap_terminate();
+ if (ripng->enabled)
+ ripng_instance_disable(ripng);
+
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (ripng->redist[i].route_map.name)
+ free(ripng->redist[i].route_map.name);
+
+ agg_table_finish(ripng->table);
+ list_delete(&ripng->peer_list);
+ distribute_list_delete(&ripng->distribute_ctx);
++ if_rmap_ctx_delete(ripng->if_rmap_ctx);
+
+ stream_free(ripng->ibuf);
+ stream_free(ripng->obuf);
+
+ ripng_clean_network(ripng);
+ ripng_passive_interface_clean(ripng);
+ vector_free(ripng->enable_if);
+ agg_table_finish(ripng->enable_network);
+ vector_free(ripng->passive_interface);
+ list_delete(&ripng->offset_list_master);
+ ripng_interface_clean(ripng);
+
+ RB_REMOVE(ripng_instance_head, &ripng_instances, ripng);
+ XFREE(MTYPE_RIPNG_VRF_NAME, ripng->vrf_name);
+ XFREE(MTYPE_RIPNG, ripng);
}
- static void ripng_if_rmap_update(struct if_rmap *if_rmap)
+ static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct ripng_interface *ri;
struct route_map *rmap;
+ struct vrf *vrf = NULL;
- ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+ if (ctx->name)
+ vrf = vrf_lookup_by_name(ctx->name);
+ if (vrf)
+ ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
if (ifp == NULL)
return;
void ripng_if_rmap_update_interface(struct interface *ifp)
{
++ struct ripng_interface *ri = ifp->info;
++ struct ripng *ripng = ri->ripng;
struct if_rmap *if_rmap;
+ struct if_rmap_ctx *ctx;
- if_rmap = if_rmap_lookup(ifp->name);
- if (ifp->vrf_id != VRF_DEFAULT)
- return;
+ if (!ripng)
+ return;
+ ctx = ripng->if_rmap_ctx;
+ if (!ctx)
+ return;
+ if_rmap = if_rmap_lookup(ctx, ifp->name);
if (if_rmap)
- ripng_if_rmap_update(if_rmap);
+ ripng_if_rmap_update(ctx, if_rmap);
}
-static void ripng_routemap_update_redistribute(void)
+static void ripng_routemap_update_redistribute(struct ripng *ripng)
{
- int i;
-
- if (ripng) {
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (ripng->route_map[i].name) {
- ripng->route_map[i].map =
- route_map_lookup_by_name(
- ripng->route_map[i].name);
- route_map_counter_increment(
- ripng->route_map[i].map);
- }
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (ripng->redist[i].route_map.name)
++ if (ripng->redist[i].route_map.name) {
+ ripng->redist[i].route_map.map =
+ route_map_lookup_by_name(
+ ripng->redist[i].route_map.name);
++ route_map_counter_increment(
++ ripng->redist[i].route_map.map);
+ }
}
}
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
+
+ /* For if_rmap container */
+ struct if_rmap_ctx *if_rmap_ctx;
};
+RB_HEAD(ripng_instance_head, ripng);
+RB_PROTOTYPE(ripng_instance_head, ripng, entry, ripng_instance_compare)
/* Routing table entry. */
struct rte {