From bb5d09c90c277ed12aa41c84f8f9026b47694c60 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 11:55:15 -0200 Subject: [PATCH 01/36] ripd, ripngd: fix null pointer dereference in YANG RPCs These RPCs should do nothing when RIP/RIPng aren't configured. Signed-off-by: Renato Westphal --- ripd/rip_northbound.c | 3 +++ ripngd/ripng_northbound.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 4e445bd46d..49bf90198a 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -1228,6 +1228,9 @@ static int clear_rip_route_rpc(const char *xpath, const struct list *input, struct list *list; struct listnode *listnode; + if (!rip) + return NB_OK; + /* Clear received RIP routes */ for (rp = route_top(rip->table); rp; rp = route_next(rp)) { list = rp->info; diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index 7993714e8d..69e207f443 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -785,6 +785,9 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input, struct list *list; struct listnode *listnode; + if (!ripng) + return NB_OK; + /* Clear received RIPng routes */ for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { list = rp->info; From 2ae9e38fa7d1a29ba39875b28f0135335c0e2329 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:09 -0200 Subject: [PATCH 02/36] ripngd: fix valgrind warning about uninitialized memory usage Fixes the following warning when running ripngd with valgrind: ==38== Syscall param sendmsg(msg.msg_control) points to uninitialised byte(s) ==38== at 0x5EA1E47: sendmsg (sendmsg.c:28) ==38== by 0x118C48: ripng_send_packet (ripngd.c:226) ==38== by 0x11D1D6: ripng_request (ripngd.c:1924) ==38== by 0x120BD8: ripng_interface_wakeup (ripng_interface.c:666) ==38== by 0x4ECB4B4: thread_call (thread.c:1601) ==38== by 0x4E8D9CE: frr_run (libfrr.c:1011) ==38== by 0x1121C8: main (ripng_main.c:180) ==38== Address 0xffefffc34 is on thread 1's stack ==38== in frame #1, created by ripng_send_packet (ripngd.c:172) Signed-off-by: Renato Westphal --- ripngd/ripngd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index ae8e8ab7d9..03383bc26d 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -152,7 +152,7 @@ int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to, struct msghdr msg; struct iovec iov; struct cmsghdr *cmsgptr; - char adata[256]; + char adata[256] = {}; struct in6_pktinfo *pkt; struct sockaddr_in6 addr; From 2d2eaa136601068130b028b274316edc19ade5c6 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 03/36] ripd: simplify cleaning up of routing instance * Call rip_clean() only when RIP is configured, this way we can remove one indentation level from this function. * rip_redistribute_clean() is only called on shutdown, so there's no need to call rip_redistribute_withdraw() there since the RIP table is already cleaned up elsewhere. * There's no need to clean up the "rip->neighbor" nodes manually before calling route_table_finish(). * Deallocate the rip structure only at the end of the function. This prepares the ground for the next commits where all global variables will be moved to the rip structure. Signed-off-by: Renato Westphal --- ripd/rip_main.c | 3 +- ripd/rip_zebra.c | 3 -- ripd/ripd.c | 112 +++++++++++++++++++++-------------------------- 3 files changed, 52 insertions(+), 66 deletions(-) diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 5db9c4b7e9..e6373664bf 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -81,7 +81,8 @@ static void sigint(void) { zlog_notice("Terminating on signal"); - rip_clean(); + if (rip) + rip_clean(); rip_zclient_stop(); frr_fini(); diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index fff8681775..684614fb47 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -180,9 +180,6 @@ void rip_redistribute_clean(void) VRF_DEFAULT); vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT); - - /* Remove the routes from RIP table. */ - rip_redistribute_withdraw(i); } } diff --git a/ripd/ripd.c b/ripd/ripd.c index 0ce5324057..f1c92ac7b9 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2634,9 +2634,6 @@ void rip_redistribute_withdraw(int type) struct rip_info *rinfo = NULL; struct list *list = NULL; - if (!rip) - return; - for (rp = route_top(rip->table); rp; rp = route_next(rp)) if ((list = rp->info) != NULL) { rinfo = listgetdata(listhead(list)); @@ -2696,6 +2693,12 @@ int rip_create(int socket) rip->table = route_table_init(); rip->neighbor = route_table_init(); + /* 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); + /* Make output stream. */ rip->obuf = stream_new(1500); @@ -2705,13 +2708,7 @@ int rip_create(int 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); + return 0; } @@ -3325,72 +3322,63 @@ static void rip_distribute_update_all_wrapper(struct access_list *notused) /* Delete all added rip route. */ void rip_clean(void) { - 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); + /* Clear RIP routes */ + for (rp = route_top(rip->table); rp; rp = route_next(rp)) { + struct rip_info *rinfo; + struct list *list; + struct listnode *listnode; - 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); - } + if ((list = rp->info) == NULL) + continue; - /* Cancel RIP related timers. */ - RIP_TIMER_OFF(rip->t_update); - RIP_TIMER_OFF(rip->t_triggered_update); - RIP_TIMER_OFF(rip->t_triggered_interval); + rinfo = listgetdata(listhead(list)); + if (rip_route_rte(rinfo)) + rip_zebra_ipv4_delete(rp); - /* Cancel read thread. */ - THREAD_READ_OFF(rip->t_read); - - /* Close RIP socket. */ - if (rip->sock >= 0) { - close(rip->sock); - rip->sock = -1; + 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); } - - 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); - } - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (rip->route_map[i].name) - free(rip->route_map[i].name); - - route_table_finish(rip->table); - route_table_finish(rip->neighbor); - - distribute_list_delete(&rip->distribute_ctx); - XFREE(MTYPE_RIP, rip); - rip = NULL; + 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); + + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (rip->route_map[i].name) + free(rip->route_map[i].name); + + route_table_finish(rip->table); + route_table_finish(rip->neighbor); + distribute_list_delete(&rip->distribute_ctx); + rip_clean_network(); rip_passive_nondefault_clean(); rip_offset_clean(); rip_interfaces_clean(); rip_distance_reset(); rip_redistribute_clean(); + + XFREE(MTYPE_RIP, rip); } static void rip_if_rmap_update(struct if_rmap *if_rmap) From ca04690261bda71898ce34ee719df4f5161ea145 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 04/36] ripd: move "rip_enable_interface" to the rip structure Signed-off-by: Renato Westphal --- ripd/rip_interface.c | 29 ++++++++++++++--------------- ripd/ripd.c | 4 +++- ripd/ripd.h | 3 +++ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 96b1cd8938..7b7faacc26 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -60,9 +60,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_NONE, "none"}, {0}}; -/* RIP enabled network vector. */ -vector rip_enable_interface; - /* RIP enabled interface table. */ struct route_table *rip_enable_network; @@ -794,8 +791,11 @@ static int rip_enable_if_lookup(const char *ifname) unsigned int i; char *str; - for (i = 0; i < vector_active(rip_enable_interface); i++) - if ((str = vector_slot(rip_enable_interface, i)) != NULL) + if (!rip) + return -1; + + for (i = 0; i < vector_active(rip->enable_interface); i++) + if ((str = vector_slot(rip->enable_interface, i)) != NULL) if (strcmp(str, ifname) == 0) return i; return -1; @@ -810,7 +810,7 @@ int rip_enable_if_add(const char *ifname) if (ret >= 0) return NB_ERR_INCONSISTENCY; - vector_set(rip_enable_interface, + vector_set(rip->enable_interface, XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname)); rip_enable_apply_all(); /* TODOVJ */ @@ -828,9 +828,9 @@ int rip_enable_if_delete(const char *ifname) if (index < 0) return NB_ERR_INCONSISTENCY; - str = vector_slot(rip_enable_interface, index); + str = vector_slot(rip->enable_interface, index); XFREE(MTYPE_RIP_INTERFACE_STRING, str); - vector_unset(rip_enable_interface, index); + vector_unset(rip->enable_interface, index); rip_enable_apply_all(); /* TODOVJ */ @@ -1042,11 +1042,11 @@ void rip_clean_network() route_unlock_node(rn); } - /* rip_enable_interface. */ - for (i = 0; i < vector_active(rip_enable_interface); i++) - if ((str = vector_slot(rip_enable_interface, i)) != NULL) { + /* rip->enable_interface. */ + for (i = 0; i < vector_active(rip->enable_interface); i++) + if ((str = vector_slot(rip->enable_interface, i)) != NULL) { XFREE(MTYPE_RIP_INTERFACE_STRING, str); - vector_slot(rip_enable_interface, i) = NULL; + vector_slot(rip->enable_interface, i) = NULL; } } @@ -1183,8 +1183,8 @@ int rip_show_network_config(struct vty *vty) node->p.prefixlen); /* Interface name RIP enable statement. */ - for (i = 0; i < vector_active(rip_enable_interface); i++) - if ((ifname = vector_slot(rip_enable_interface, i)) != NULL) + for (i = 0; i < vector_active(rip->enable_interface); i++) + if ((ifname = vector_slot(rip->enable_interface, i)) != NULL) vty_out(vty, " %s\n", ifname); /* RIP neighbors listing. */ @@ -1223,7 +1223,6 @@ void rip_if_init(void) hook_register_prio(if_del, 0, rip_interface_delete_hook); /* RIP network init. */ - rip_enable_interface = vector_init(1); rip_enable_network = route_table_init(); /* RIP passive interface. */ diff --git a/ripd/ripd.c b/ripd/ripd.c index f1c92ac7b9..752328888b 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2689,9 +2689,10 @@ int rip_create(int socket) rip->version_recv = yang_get_default_enum("%s/version/receive", RIP_INSTANCE); - /* Initialize RIP routig table. */ + /* Initialize RIP data structures. */ rip->table = route_table_init(); rip->neighbor = route_table_init(); + rip->enable_interface = vector_init(1); /* Distribute list install. */ rip->distribute_ctx = @@ -3373,6 +3374,7 @@ void rip_clean(void) rip_clean_network(); rip_passive_nondefault_clean(); + vector_free(rip->enable_interface); rip_offset_clean(); rip_interfaces_clean(); rip_distance_reset(); diff --git a/ripd/ripd.h b/ripd/ripd.h index 7b8fe3a906..a1edbed5e3 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -144,6 +144,9 @@ struct rip { /* Are we in passive-interface default mode? */ bool passive_default; + /* RIP enabled interfaces. */ + vector enable_interface; + /* For redistribute route map. */ struct { char *name; From 1205fdc482e8c2977fbbe491824a718d22624de1 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 05/36] ripd: move "rip_enable_network" to the rip structure Signed-off-by: Renato Westphal --- ripd/rip_interface.c | 25 +++++++++++-------------- ripd/ripd.c | 2 ++ ripd/ripd.h | 3 +++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 7b7faacc26..86a144318a 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -60,9 +60,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_NONE, "none"}, {0}}; -/* RIP enabled interface table. */ -struct route_table *rip_enable_network; - /* Vector to store passive-interface name. */ vector Vrip_passive_nondefault; @@ -692,6 +689,9 @@ static int rip_enable_network_lookup_if(struct interface *ifp) struct connected *connected; struct prefix_ipv4 address; + if (!rip) + return -1; + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { struct prefix *p; struct route_node *n; @@ -703,7 +703,7 @@ static int rip_enable_network_lookup_if(struct interface *ifp) address.prefix = p->u.prefix4; address.prefixlen = IPV4_MAX_BITLEN; - n = route_node_match(rip_enable_network, + n = route_node_match(rip->enable_network, (struct prefix *)&address); if (n) { route_unlock_node(n); @@ -730,8 +730,8 @@ int rip_enable_network_lookup2(struct connected *connected) address.prefixlen = IPV4_MAX_BITLEN; /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within - * rip_enable_network */ - node = route_node_match(rip_enable_network, + * rip->enable_network */ + node = route_node_match(rip->enable_network, (struct prefix *)&address); if (node) { @@ -747,7 +747,7 @@ int rip_enable_network_add(struct prefix *p) { struct route_node *node; - node = route_node_get(rip_enable_network, p); + node = route_node_get(rip->enable_network, p); if (node->info) { route_unlock_node(node); @@ -766,7 +766,7 @@ int rip_enable_network_delete(struct prefix *p) { struct route_node *node; - node = route_node_lookup(rip_enable_network, p); + node = route_node_lookup(rip->enable_network, p); if (node) { node->info = NULL; @@ -1035,8 +1035,8 @@ void rip_clean_network() char *str; struct route_node *rn; - /* rip_enable_network. */ - for (rn = route_top(rip_enable_network); rn; rn = route_next(rn)) + /* rip->enable_network. */ + for (rn = route_top(rip->enable_network); rn; rn = route_next(rn)) if (rn->info) { rn->info = NULL; route_unlock_node(rn); @@ -1175,7 +1175,7 @@ int rip_show_network_config(struct vty *vty) struct route_node *node; /* Network type RIP enable interface statement. */ - for (node = route_top(rip_enable_network); node; + for (node = route_top(rip->enable_network); node; node = route_next(node)) if (node->info) vty_out(vty, " %s/%u\n", @@ -1222,9 +1222,6 @@ void rip_if_init(void) hook_register_prio(if_add, 0, rip_interface_new_hook); hook_register_prio(if_del, 0, rip_interface_delete_hook); - /* RIP network init. */ - rip_enable_network = route_table_init(); - /* RIP passive interface. */ Vrip_passive_nondefault = vector_init(1); diff --git a/ripd/ripd.c b/ripd/ripd.c index 752328888b..d099f9664a 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2693,6 +2693,7 @@ int rip_create(int socket) rip->table = route_table_init(); rip->neighbor = route_table_init(); rip->enable_interface = vector_init(1); + rip->enable_network = route_table_init(); /* Distribute list install. */ rip->distribute_ctx = @@ -3375,6 +3376,7 @@ void rip_clean(void) rip_clean_network(); rip_passive_nondefault_clean(); vector_free(rip->enable_interface); + route_table_finish(rip->enable_network); rip_offset_clean(); rip_interfaces_clean(); rip_distance_reset(); diff --git a/ripd/ripd.h b/ripd/ripd.h index a1edbed5e3..1f3b41e5fe 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -147,6 +147,9 @@ struct rip { /* RIP enabled interfaces. */ vector enable_interface; + /* RIP enabled networks. */ + struct route_table *enable_network; + /* For redistribute route map. */ struct { char *name; From 5a29c0d5c4e0529a1e721b4acfcd2463d371414d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 06/36] ripd: move "Vrip_passive_nondefault" to the rip structure Signed-off-by: Renato Westphal --- ripd/rip_interface.c | 22 ++++++++-------------- ripd/ripd.c | 2 ++ ripd/ripd.h | 4 +++- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 86a144318a..ca2fa24e43 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -60,9 +60,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_NONE, "none"}, {0}}; -/* Vector to store passive-interface name. */ -vector Vrip_passive_nondefault; - /* Join to the RIP version 2 multicast group. */ static int ipv4_multicast_join(int sock, struct in_addr group, struct in_addr ifa, ifindex_t ifindex) @@ -1056,8 +1053,8 @@ static int rip_passive_nondefault_lookup(const char *ifname) unsigned int i; char *str; - for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) - if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) + for (i = 0; i < vector_active(rip->passive_nondefault); i++) + if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) if (strcmp(str, ifname) == 0) return i; return -1; @@ -1100,7 +1097,7 @@ int rip_passive_nondefault_set(const char *ifname) */ return NB_OK; - vector_set(Vrip_passive_nondefault, + vector_set(rip->passive_nondefault, XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname)); rip_passive_interface_apply_all(); @@ -1121,9 +1118,9 @@ int rip_passive_nondefault_unset(const char *ifname) */ return NB_OK; - str = vector_slot(Vrip_passive_nondefault, i); + str = vector_slot(rip->passive_nondefault, i); XFREE(MTYPE_RIP_INTERFACE_STRING, str); - vector_unset(Vrip_passive_nondefault, i); + vector_unset(rip->passive_nondefault, i); rip_passive_interface_apply_all(); @@ -1136,10 +1133,10 @@ void rip_passive_nondefault_clean(void) unsigned int i; char *str; - for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) - if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) { + for (i = 0; i < vector_active(rip->passive_nondefault); i++) + if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) { XFREE(MTYPE_RIP_INTERFACE_STRING, str); - vector_slot(Vrip_passive_nondefault, i) = NULL; + vector_slot(rip->passive_nondefault, i) = NULL; } rip_passive_interface_apply_all(); } @@ -1222,9 +1219,6 @@ void rip_if_init(void) hook_register_prio(if_add, 0, rip_interface_new_hook); hook_register_prio(if_del, 0, rip_interface_delete_hook); - /* RIP passive interface. */ - Vrip_passive_nondefault = vector_init(1); - /* Install interface node. */ install_node(&interface_node, rip_interface_config_write); if_cmd_init(); diff --git a/ripd/ripd.c b/ripd/ripd.c index d099f9664a..c7e2d6a241 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2694,6 +2694,7 @@ int rip_create(int socket) rip->neighbor = route_table_init(); rip->enable_interface = vector_init(1); rip->enable_network = route_table_init(); + rip->passive_nondefault = vector_init(1); /* Distribute list install. */ rip->distribute_ctx = @@ -3377,6 +3378,7 @@ void rip_clean(void) rip_passive_nondefault_clean(); vector_free(rip->enable_interface); route_table_finish(rip->enable_network); + vector_free(rip->passive_nondefault); rip_offset_clean(); rip_interfaces_clean(); rip_distance_reset(); diff --git a/ripd/ripd.h b/ripd/ripd.h index 1f3b41e5fe..97ad1fb08e 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -150,6 +150,9 @@ struct rip { /* RIP enabled networks. */ struct route_table *enable_network; + /* Vector to store passive-interface name. */ + vector passive_nondefault; + /* For redistribute route map. */ struct { char *name; @@ -480,7 +483,6 @@ DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) extern struct list *peer_list; extern struct route_table *rip_distance_table; -extern vector Vrip_passive_nondefault; /* Northbound. */ extern void rip_cli_init(void); From 29e897ad333790601929c09904a7e2ff146bcf55 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 07/36] ripd: move "peer_list" to the rip structure Signed-off-by: Renato Westphal --- ripd/rip_main.c | 1 - ripd/rip_northbound.c | 10 ++++++++-- ripd/rip_peer.c | 21 ++++++--------------- ripd/rip_snmp.c | 3 +++ ripd/ripd.c | 2 ++ ripd/ripd.h | 8 +++++--- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/ripd/rip_main.c b/ripd/rip_main.c index e6373664bf..8c6340f6c7 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -179,7 +179,6 @@ int main(int argc, char **argv) rip_if_init(); rip_cli_init(); rip_zclient_init(master); - rip_peer_init(); frr_config_fork(); frr_run(master); diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 49bf90198a..17ba672614 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -1012,8 +1012,11 @@ ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry, { struct listnode *node; + if (rip == NULL) + return NULL; + if (list_entry == NULL) - node = listhead(peer_list); + node = listhead(rip->peer_list); else node = listnextnode((struct listnode *)list_entry); @@ -1043,7 +1046,10 @@ ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, yang_str2ipv4(keys->key[0], &address); - for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) { + if (rip == NULL) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) { if (IPV4_ADDR_SAME(&peer->addr, &address)) return node; } diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 21317915d4..ca3f25e949 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -29,9 +29,6 @@ #include "ripd/ripd.h" -/* Linked list of RIP peer. */ -struct list *peer_list; - static struct rip_peer *rip_peer_new(void) { return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer)); @@ -47,7 +44,7 @@ struct rip_peer *rip_peer_lookup(struct in_addr *addr) struct rip_peer *peer; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) { if (IPV4_ADDR_SAME(&peer->addr, addr)) return peer; } @@ -59,7 +56,7 @@ struct rip_peer *rip_peer_lookup_next(struct in_addr *addr) struct rip_peer *peer; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) { if (htonl(peer->addr.s_addr) > htonl(addr->s_addr)) return peer; } @@ -72,7 +69,7 @@ static int rip_peer_timeout(struct thread *t) struct rip_peer *peer; peer = THREAD_ARG(t); - listnode_delete(peer_list, peer); + listnode_delete(rip->peer_list, peer); rip_peer_free(peer); return 0; @@ -91,7 +88,7 @@ static struct rip_peer *rip_peer_get(struct in_addr *addr) } else { peer = rip_peer_new(); peer->addr = *addr; - listnode_add_sort(peer_list, peer); + listnode_add_sort(rip->peer_list, peer); } /* Update timeout thread. */ @@ -162,7 +159,7 @@ void rip_peer_display(struct vty *vty) #define RIP_UPTIME_LEN 25 char timebuf[RIP_UPTIME_LEN]; - for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + for (ALL_LIST_ELEMENTS(rip->peer_list, node, nnode, peer)) { vty_out(vty, " %-16s %9d %9d %9d %s\n", inet_ntoa(peer->addr), peer->recv_badpackets, peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT, @@ -170,16 +167,10 @@ void rip_peer_display(struct vty *vty) } } -static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2) +int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2) { if (p2->addr.s_addr == p1->addr.s_addr) return 0; return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1; } - -void rip_peer_init(void) -{ - peer_list = list_new(); - peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp; -} diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 19367638cc..9acc825c0a 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -284,6 +284,9 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], int len; struct rip_peer *peer; + if (!rip) + return NULL; + if (exact) { /* Check the length. */ if (*length - v->namelen != sizeof(struct in_addr) + 1) diff --git a/ripd/ripd.c b/ripd/ripd.c index c7e2d6a241..e00b453f9f 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2692,6 +2692,8 @@ int rip_create(int socket) /* Initialize RIP data structures. */ rip->table = route_table_init(); rip->neighbor = route_table_init(); + rip->peer_list = list_new(); + rip->peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp; rip->enable_interface = vector_init(1); rip->enable_network = route_table_init(); rip->passive_nondefault = vector_init(1); diff --git a/ripd/ripd.h b/ripd/ripd.h index 97ad1fb08e..100c9d14b1 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -112,9 +112,12 @@ struct rip { /* RIP routing information base. */ struct route_table *table; - /* RIP neighbor. */ + /* RIP static neighbors. */ struct route_table *neighbor; + /* Linked list of RIP peers. */ + struct list *peer_list; + /* RIP threads. */ struct thread *t_read; @@ -433,13 +436,13 @@ extern void rip_if_rmap_update_interface(struct interface *); extern int rip_show_network_config(struct vty *); extern void rip_show_redistribute_config(struct vty *); -extern void rip_peer_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_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2); extern void rip_info_free(struct rip_info *); extern struct rip_distance *rip_distance_new(void); @@ -481,7 +484,6 @@ extern long rip_global_queries; DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) -extern struct list *peer_list; extern struct route_table *rip_distance_table; /* Northbound. */ From 3f21c8c4cb57a1c3f645be77dfa8e860019daf6c Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 08/36] ripd: move "rip_offset_list_master" to the rip structure Signed-off-by: Renato Westphal --- ripd/rip_offset.c | 27 ++++----------------------- ripd/ripd.c | 6 ++++-- ripd/ripd.h | 7 +++++-- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index 418ec3fc7b..94dc175d14 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -29,8 +29,6 @@ #include "ripd/ripd.h" -static struct list *rip_offset_list_master; - #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name) #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric) @@ -43,14 +41,14 @@ struct rip_offset_list *rip_offset_list_new(const char *ifname) offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); offset->ifname = strdup(ifname); - listnode_add_sort(rip_offset_list_master, offset); + listnode_add_sort(rip->offset_list_master, offset); return offset; } void offset_list_del(struct rip_offset_list *offset) { - listnode_delete(rip_offset_list_master, offset); + listnode_delete(rip->offset_list_master, offset); if (OFFSET_LIST_IN_NAME(offset)) free(OFFSET_LIST_IN_NAME(offset)); if (OFFSET_LIST_OUT_NAME(offset)) @@ -64,7 +62,7 @@ struct rip_offset_list *rip_offset_list_lookup(const char *ifname) struct rip_offset_list *offset; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { + for (ALL_LIST_ELEMENTS(rip->offset_list_master, node, nnode, offset)) { if (strcmp(offset->ifname, ifname) == 0) return offset; } @@ -146,24 +144,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, return 0; } -static int offset_list_cmp(struct rip_offset_list *o1, - struct rip_offset_list *o2) +int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2) { return strcmp(o1->ifname, o2->ifname); } - -void rip_offset_init() -{ - rip_offset_list_master = list_new(); - rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; - rip_offset_list_master->del = (void (*)(void *))offset_list_del; -} - -void rip_offset_clean() -{ - list_delete(&rip_offset_list_master); - - rip_offset_list_master = list_new(); - rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; - rip_offset_list_master->del = (void (*)(void *))offset_list_del; -} diff --git a/ripd/ripd.c b/ripd/ripd.c index e00b453f9f..79ec807702 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2697,6 +2697,9 @@ int rip_create(int socket) 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; /* Distribute list install. */ rip->distribute_ctx = @@ -3381,7 +3384,7 @@ void rip_clean(void) vector_free(rip->enable_interface); route_table_finish(rip->enable_network); vector_free(rip->passive_nondefault); - rip_offset_clean(); + list_delete(&rip->offset_list_master); rip_interfaces_clean(); rip_distance_reset(); rip_redistribute_clean(); @@ -3484,7 +3487,6 @@ void rip_init(void) /* Route-map */ rip_route_map_init(); - rip_offset_init(); route_map_add_hook(rip_routemap_update); route_map_delete_hook(rip_routemap_update); diff --git a/ripd/ripd.h b/ripd/ripd.h index 100c9d14b1..858c8d4f60 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -156,6 +156,9 @@ struct rip { /* Vector to store passive-interface name. */ vector passive_nondefault; + /* RIP offset-lists. */ + struct list *offset_list_master; + /* For redistribute route map. */ struct { char *name; @@ -462,8 +465,8 @@ extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *, uint32_t *); extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, uint32_t *); -extern void rip_offset_init(void); -extern void rip_offset_clean(void); +extern int offset_list_cmp(struct rip_offset_list *o1, + struct rip_offset_list *o2); /* YANG notifications */ extern void ripd_notif_send_auth_type_failure(const char *ifname); From 241987a816b8a2bb1d2973f33624fdea62718208 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 09/36] ripd: remove dead code None of these variables or functions were being used since the initial revision ~16 years ago. It's safe to say we can remove them now. Signed-off-by: Renato Westphal --- ripd/rip_interface.c | 10 ------ ripd/ripd.c | 81 -------------------------------------------- ripd/ripd.h | 6 ---- 3 files changed, 97 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index ca2fa24e43..2e432ec79c 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -553,16 +553,6 @@ int rip_if_down(struct interface *ifp) return 0; } -/* Needed for stop RIP process. */ -void rip_if_down_all() -{ - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct interface *ifp; - - FOR_ALL_INTERFACES (vrf, ifp) - rip_if_down(ifp); -} - static void rip_apply_address_add(struct connected *ifc) { struct prefix_ipv4 address; diff --git a/ripd/ripd.c b/ripd/ripd.c index 79ec807702..35ad4d818a 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -53,9 +53,6 @@ /* RIP Structure. */ struct rip *rip = NULL; -/* RIP neighbor address table. */ -struct route_table *rip_neighbor_table; - /* RIP route changes. */ long rip_global_route_changes = 0; @@ -1350,9 +1347,6 @@ int rip_create_socket(void) sockopt_reuseaddr(sock); sockopt_reuseport(sock); setsockopt_ipv4_multicast_loop(sock, 0); -#ifdef RIP_RECVMSG - setsockopt_pktinfo(sock); -#endif /* RIP_RECVMSG */ #ifdef IPTOS_PREC_INTERNETCONTROL setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL); #endif @@ -1642,81 +1636,6 @@ static void rip_request_process(struct rip_packet *packet, int size, rip_global_queries++; } -#if RIP_RECVMSG -/* Set IPv6 packet info to the socket. */ -static int setsockopt_pktinfo(int sock) -{ - int ret; - int val = 1; - - ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)); - if (ret < 0) - zlog_warn("Can't setsockopt IP_PKTINFO : %s", - safe_strerror(errno)); - return ret; -} - -/* Read RIP packet by recvmsg function. */ -int rip_recvmsg(int sock, uint8_t *buf, int size, struct sockaddr_in *from, - ifindex_t *ifindex) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *ptr; - char adata[1024]; - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = (void *)from; - msg.msg_namelen = sizeof(struct sockaddr_in); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *)adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = size; - - ret = recvmsg(sock, &msg, 0); - if (ret < 0) - return ret; - - for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; - ptr = CMSG_NXTHDR(&msg, ptr)) - if (ptr->cmsg_level == IPPROTO_IP - && ptr->cmsg_type == IP_PKTINFO) { - struct in_pktinfo *pktinfo; - int i; - - pktinfo = (struct in_pktinfo *)CMSG_DATA(ptr); - i = pktinfo->ipi_ifindex; - } - return ret; -} - -/* RIP packet read function. */ -int rip_read_new(struct thread *t) -{ - int ret; - int sock; - char buf[RIP_PACKET_MAXSIZ]; - struct sockaddr_in from; - ifindex_t ifindex; - - /* Fetch socket then register myself. */ - sock = THREAD_FD(t); - rip_event(RIP_READ, sock); - - /* Read RIP packet. */ - ret = rip_recvmsg(sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex); - if (ret < 0) { - zlog_warn("Can't read RIP packet: %s", safe_strerror(errno)); - return ret; - } - - return ret; -} -#endif /* RIP_RECVMSG */ - /* First entry point of RIP packet. */ static int rip_read(struct thread *t) { diff --git a/ripd/ripd.h b/ripd/ripd.h index 858c8d4f60..bc0451d88f 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -237,11 +237,6 @@ struct rip_info { struct route_node *rp; uint8_t distance; - -#ifdef NEW_RIP_TABLE - struct rip_info *next; - struct rip_info *prev; -#endif /* NEW_RIP_TABLE */ }; typedef enum { @@ -399,7 +394,6 @@ extern int rip_passive_nondefault_set(const char *ifname); extern int rip_passive_nondefault_unset(const char *ifname); extern void rip_passive_nondefault_clean(void); extern void rip_if_init(void); -extern void rip_if_down_all(void); extern void rip_route_map_init(void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_stop(void); From c08a21077faa595a76f87cc4b67d76623f045e0f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 10/36] ripd: move global counters to the rip structure The only sideeffect of this change is that these counters will be reset when RIP is deconfigured and then configured again, but this shouldn't be a problem as the RIP MIB isn't specific about this. Signed-off-by: Renato Westphal --- ripd/rip_snmp.c | 7 +++++-- ripd/rip_zebra.c | 2 +- ripd/ripd.c | 8 +------- ripd/ripd.h | 13 +++++++++---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 9acc825c0a..54c8a2eb8c 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -160,13 +160,16 @@ static uint8_t *rip2Globals(struct variable *v, oid name[], size_t *length, == MATCH_FAILED) return NULL; + if (!rip) + return NULL; + /* Retrun global counter. */ switch (v->magic) { case RIP2GLOBALROUTECHANGES: - return SNMP_INTEGER(rip_global_route_changes); + return SNMP_INTEGER(rip->counters.route_changes); break; case RIP2GLOBALQUERIES: - return SNMP_INTEGER(rip_global_queries); + return SNMP_INTEGER(rip->counters.queries); break; default: return NULL; diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 684614fb47..607dc168f4 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -101,7 +101,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd) inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen); } - rip_global_route_changes++; + rip->counters.route_changes++; } /* Add/update ECMP routes to zebra. */ diff --git a/ripd/ripd.c b/ripd/ripd.c index 35ad4d818a..1e92fedb63 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -53,12 +53,6 @@ /* RIP Structure. */ struct rip *rip = NULL; -/* RIP route changes. */ -long rip_global_route_changes = 0; - -/* RIP queries. */ -long rip_global_queries = 0; - /* Prototypes. */ static void rip_output_process(struct connected *, struct sockaddr_in *, int, uint8_t); @@ -1633,7 +1627,7 @@ static void rip_request_process(struct rip_packet *packet, int size, (void)rip_send_packet((uint8_t *)packet, size, from, ifc); } - rip_global_queries++; + rip->counters.queries++; } /* First entry point of RIP packet. */ diff --git a/ripd/ripd.h b/ripd/ripd.h index bc0451d88f..a75e43d5df 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -169,6 +169,15 @@ struct rip { /* For distribute-list container */ struct distribute_ctx *distribute_ctx; + + /* Counters for SNMP. */ + struct { + /* RIP route changes. */ + long route_changes; + + /* RIP queries. */ + long queries; + } counters; }; /* RIP routing table entry which belong to rip_packet. */ @@ -474,10 +483,6 @@ extern struct zebra_privs_t ripd_privs; /* Master thread strucutre. */ extern struct thread_master *master; -/* RIP statistics for SNMP. */ -extern long rip_global_route_changes; -extern long rip_global_queries; - DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) From 2826309c11e8b2af4593f3460a21e44f906a55a4 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 11/36] ripd: move "rip_distance_table" to the rip structure Signed-off-by: Renato Westphal --- ripd/rip_northbound.c | 5 +---- ripd/ripd.c | 33 ++++++++++++++------------------- ripd/ripd.h | 2 -- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 17ba672614..b0f2b62a5d 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -173,7 +173,7 @@ static int ripd_instance_distance_source_create(enum nb_event event, apply_mask_ipv4(&prefix); /* Get RIP distance node. */ - rn = route_node_get(rip_distance_table, (struct prefix *)&prefix); + rn = route_node_get(rip->distance_table, (struct prefix *)&prefix); rn->info = rip_distance_new(); yang_dnode_set_entry(dnode, rn); @@ -191,10 +191,7 @@ static int ripd_instance_distance_source_delete(enum nb_event event, rn = yang_dnode_get_entry(dnode, true); rdistance = rn->info; - if (rdistance->access_list) - free(rdistance->access_list); rip_distance_free(rdistance); - rn->info = NULL; route_unlock_node(rn); diff --git a/ripd/ripd.c b/ripd/ripd.c index 1e92fedb63..49787db2bb 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -58,6 +58,8 @@ static void rip_output_process(struct connected *, struct sockaddr_in *, int, uint8_t); static int rip_triggered_update(struct thread *); static int rip_update_jitter(unsigned long); +static void rip_distance_table_node_cleanup(struct route_table *table, + struct route_node *node); static void rip_distribute_update(struct distribute_ctx *ctx, struct distribute *dist); @@ -2607,6 +2609,8 @@ int rip_create(int socket) rip->neighbor = route_table_init(); rip->peer_list = list_new(); rip->peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp; + 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); @@ -2744,9 +2748,6 @@ rip_update_default_metric (void) } #endif - -struct route_table *rip_distance_table; - struct rip_distance *rip_distance_new(void) { return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance)); @@ -2754,22 +2755,19 @@ struct rip_distance *rip_distance_new(void) void rip_distance_free(struct rip_distance *rdistance) { + if (rdistance->access_list) + free(rdistance->access_list); XFREE(MTYPE_RIP_DISTANCE, rdistance); } -static void rip_distance_reset(void) +static void rip_distance_table_node_cleanup(struct route_table *table, + struct route_node *node) { - struct route_node *rn; struct rip_distance *rdistance; - for (rn = route_top(rip_distance_table); rn; rn = route_next(rn)) - if ((rdistance = rn->info) != NULL) { - if (rdistance->access_list) - free(rdistance->access_list); - rip_distance_free(rdistance); - rn->info = NULL; - route_unlock_node(rn); - } + rdistance = node->info; + if (rdistance) + rip_distance_free(rdistance); } /* Apply RIP information to distance method. */ @@ -2789,7 +2787,7 @@ uint8_t rip_distance_apply(struct rip_info *rinfo) p.prefixlen = IPV4_MAX_BITLEN; /* Check source address. */ - rn = route_node_match(rip_distance_table, (struct prefix *)&p); + rn = route_node_match(rip->distance_table, (struct prefix *)&p); if (rn) { rdistance = rn->info; route_unlock_node(rn); @@ -2824,7 +2822,7 @@ static void rip_distance_show(struct vty *vty) vty_out(vty, " Distance: (default is %u)\n", rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT); - for (rn = route_top(rip_distance_table); rn; rn = route_next(rn)) + for (rn = route_top(rip->distance_table); rn; rn = route_next(rn)) if ((rdistance = rn->info) != NULL) { if (header) { vty_out(vty, @@ -3299,7 +3297,7 @@ void rip_clean(void) vector_free(rip->passive_nondefault); list_delete(&rip->offset_list_master); rip_interfaces_clean(); - rip_distance_reset(); + route_table_finish(rip->distance_table); rip_redistribute_clean(); XFREE(MTYPE_RIP, rip); @@ -3407,7 +3405,4 @@ void rip_init(void) 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(); } diff --git a/ripd/ripd.h b/ripd/ripd.h index a75e43d5df..6936ad1237 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -486,8 +486,6 @@ extern struct thread_master *master; DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) -extern struct route_table *rip_distance_table; - /* Northbound. */ extern void rip_cli_init(void); extern const struct frr_yang_module_info frr_ripd_info; From 711915d2cdef4dcf41c6921f98de29946cab500e Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 12/36] ripd: clear list of peers when RIP is deconfigured This is an old standing bug where the list of RIP peers wasn't cleared after deconfiguring RIP, which caused the existing peers to still be present on a newly configured RIP instance (except when the timed out after ~3 minutes). Fix this. Signed-off-by: Renato Westphal --- ripd/rip_peer.c | 6 ++++++ ripd/ripd.c | 2 ++ ripd/ripd.h | 1 + 3 files changed, 9 insertions(+) diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index ca3f25e949..07b295030e 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -36,6 +36,7 @@ static struct rip_peer *rip_peer_new(void) static void rip_peer_free(struct rip_peer *peer) { + RIP_TIMER_OFF(peer->t_timeout); XFREE(MTYPE_RIP_PEER, peer); } @@ -174,3 +175,8 @@ int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2) return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1; } + +void rip_peer_list_del(void *arg) +{ + rip_peer_free(arg); +} diff --git a/ripd/ripd.c b/ripd/ripd.c index 49787db2bb..a6cfd9b151 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2609,6 +2609,7 @@ int rip_create(int socket) 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); @@ -3288,6 +3289,7 @@ void rip_clean(void) route_table_finish(rip->table); route_table_finish(rip->neighbor); + list_delete(&rip->peer_list); distribute_list_delete(&rip->distribute_ctx); rip_clean_network(); diff --git a/ripd/ripd.h b/ripd/ripd.h index 6936ad1237..af0d3021a6 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -449,6 +449,7 @@ 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_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_distance *rip_distance_new(void); From 045c5389c26347d47b2af6020c3a122398f13efb Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 13/36] ripd: remove the rip global variable This is the last step to make ripd ready for multi-instance support. Remove the rip global variable and add a "rip" parameter to all functions that need to know the RIP instance they are working on. On some functions, retrieve the RIP instance from the interface variable when it exists (this assumes interfaces can pertain to one RIP instance at most, which is ok for VRF support). In preparation for the next commits (VRF support), add a "vrd_id" member to the rip structure, and use rip->vrf_id instead of VRF_DEFAULT wherever possible. Signed-off-by: Renato Westphal --- ripd/rip_interface.c | 134 +++++++++------- ripd/rip_main.c | 11 +- ripd/rip_northbound.c | 146 ++++++++++++++---- ripd/rip_offset.c | 18 ++- ripd/rip_peer.c | 25 +-- ripd/rip_snmp.c | 19 ++- ripd/rip_zebra.c | 47 +++--- ripd/ripd.c | 345 +++++++++++++++++++++++++----------------- ripd/ripd.h | 110 ++++++++------ 9 files changed, 537 insertions(+), 318 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 2e432ec79c..ca6dea1b37 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -50,9 +50,9 @@ DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) static void rip_enable_apply(struct interface *); static void rip_passive_interface_apply(struct interface *); static int rip_if_down(struct interface *ifp); -static int rip_enable_if_lookup(const char *ifname); +static int rip_enable_if_lookup(struct rip *rip, const char *ifname); static int rip_enable_network_lookup2(struct connected *connected); -static void rip_enable_apply_all(void); +static void rip_enable_apply_all(struct rip *rip); const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_2, "2"}, @@ -94,12 +94,17 @@ static int ipv4_multicast_leave(int sock, struct in_addr group, static void rip_interface_reset(struct rip_interface *); /* Allocate new RIP's interface configuration. */ -static struct rip_interface *rip_interface_new(void) +static struct rip_interface *rip_interface_new(struct interface *ifp) { + struct vrf *vrf; struct rip_interface *ri; ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface)); + vrf = vrf_lookup_by_id(ifp->vrf_id); + if (vrf) + ri->rip = vrf->info; + rip_interface_reset(ri); return ri; @@ -199,7 +204,7 @@ static void rip_request_interface(struct interface *ifp) /* If there is no version configuration in the interface, use rip's version setting. */ - vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send + vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send : ri->ri_send); if (vsend & RIPv1) rip_request_interface_send(ifp, RIPv1); @@ -320,9 +325,9 @@ static int rip_if_ipv4_address_check(struct interface *ifp) /* Does this address belongs to me ? */ -int if_check_address(struct in_addr addr) +int if_check_address(struct rip *rip, struct in_addr addr) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) { @@ -474,9 +479,9 @@ static void rip_interface_clean(struct rip_interface *ri) } } -void rip_interfaces_clean(void) +void rip_interfaces_clean(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) @@ -524,20 +529,22 @@ static void rip_interface_reset(struct rip_interface *ri) int rip_if_down(struct interface *ifp) { + struct rip *rip; struct route_node *rp; struct rip_info *rinfo; struct rip_interface *ri = NULL; struct list *list = NULL; struct listnode *listnode = NULL, *nextnode = NULL; + + ri = ifp->info; + rip = ri->rip; if (rip) { for (rp = route_top(rip->table); rp; rp = route_next(rp)) if ((list = rp->info) != NULL) for (ALL_LIST_ELEMENTS(list, listnode, nextnode, rinfo)) if (rinfo->nh.ifindex == ifp->ifindex) - rip_ecmp_delete(rinfo); - - ri = ifp->info; + rip_ecmp_delete(rip, rinfo); if (ri->running) { if (IS_RIP_DEBUG_EVENT) @@ -555,6 +562,8 @@ int rip_if_down(struct interface *ifp) static void rip_apply_address_add(struct connected *ifc) { + struct rip_interface *ri = ifc->ifp->info; + struct rip *rip = ri->rip; struct prefix_ipv4 address; struct nexthop nh; struct prefix *p; @@ -580,10 +589,11 @@ static void rip_apply_address_add(struct connected *ifc) /* Check if this interface is RIP enabled or not or Check if this address's prefix is RIP enabled */ - if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) + if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0) || (rip_enable_network_lookup2(ifc) >= 0)) - rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, &nh, 0, 0, 0); + rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_INTERFACE, &address, &nh, 0, 0, + 0); } int rip_interface_address_add(int command, struct zclient *zclient, @@ -617,6 +627,8 @@ int rip_interface_address_add(int command, struct zclient *zclient, static void rip_apply_address_del(struct connected *ifc) { + struct rip_interface *ri = ifc->ifp->info; + struct rip *rip = ri->rip; struct prefix_ipv4 address; struct prefix *p; @@ -634,7 +646,7 @@ static void rip_apply_address_del(struct connected *ifc) address.prefixlen = p->prefixlen; apply_mask_ipv4(&address); - rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, + rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, ifc->ifp->ifindex); } @@ -672,6 +684,8 @@ int rip_interface_address_delete(int command, struct zclient *zclient, * is within the ripng_enable_network table. */ static int rip_enable_network_lookup_if(struct interface *ifp) { + struct rip_interface *ri = ifp->info; + struct rip *rip = ri->rip; struct listnode *node, *nnode; struct connected *connected; struct prefix_ipv4 address; @@ -702,8 +716,10 @@ static int rip_enable_network_lookup_if(struct interface *ifp) } /* Check wether connected is within the ripng_enable_network table. */ -int rip_enable_network_lookup2(struct connected *connected) +static int rip_enable_network_lookup2(struct connected *connected) { + struct rip_interface *ri = connected->ifp->info; + struct rip *rip = ri->rip; struct prefix_ipv4 address; struct prefix *p; @@ -730,7 +746,7 @@ int rip_enable_network_lookup2(struct connected *connected) return -1; } /* Add RIP enable network. */ -int rip_enable_network_add(struct prefix *p) +int rip_enable_network_add(struct rip *rip, struct prefix *p) { struct route_node *node; @@ -743,13 +759,13 @@ int rip_enable_network_add(struct prefix *p) node->info = (void *)1; /* XXX: One should find a better solution than a generic one */ - rip_enable_apply_all(); + rip_enable_apply_all(rip); return NB_OK; } /* Delete RIP enable network. */ -int rip_enable_network_delete(struct prefix *p) +int rip_enable_network_delete(struct rip *rip, struct prefix *p) { struct route_node *node; @@ -764,7 +780,7 @@ int rip_enable_network_delete(struct prefix *p) route_unlock_node(node); /* XXX: One should find a better solution than a generic one */ - rip_enable_apply_all(); + rip_enable_apply_all(rip); return NB_OK; } @@ -773,7 +789,7 @@ int rip_enable_network_delete(struct prefix *p) } /* Check interface is enabled by ifname statement. */ -static int rip_enable_if_lookup(const char *ifname) +static int rip_enable_if_lookup(struct rip *rip, const char *ifname) { unsigned int i; char *str; @@ -789,29 +805,29 @@ static int rip_enable_if_lookup(const char *ifname) } /* Add interface to rip_enable_if. */ -int rip_enable_if_add(const char *ifname) +int rip_enable_if_add(struct rip *rip, const char *ifname) { int ret; - ret = rip_enable_if_lookup(ifname); + ret = rip_enable_if_lookup(rip, ifname); if (ret >= 0) return NB_ERR_INCONSISTENCY; vector_set(rip->enable_interface, XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname)); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(rip); /* TODOVJ */ return NB_OK; } /* Delete interface from rip_enable_if. */ -int rip_enable_if_delete(const char *ifname) +int rip_enable_if_delete(struct rip *rip, const char *ifname) { int index; char *str; - index = rip_enable_if_lookup(ifname); + index = rip_enable_if_lookup(rip, ifname); if (index < 0) return NB_ERR_INCONSISTENCY; @@ -819,7 +835,7 @@ int rip_enable_if_delete(const char *ifname) XFREE(MTYPE_RIP_INTERFACE_STRING, str); vector_unset(rip->enable_interface, index); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(rip); /* TODOVJ */ return NB_OK; } @@ -837,7 +853,7 @@ static int rip_interface_wakeup(struct thread *t) ri->t_wakeup = NULL; /* Join to multicast group. */ - if (rip_multicast_join(ifp, rip->sock) < 0) { + if (rip_multicast_join(ifp, ri->rip->sock) < 0) { flog_err_sys(EC_LIB_SOCKET, "multicast join failed, interface %s not running", ifp->name); @@ -855,6 +871,8 @@ static int rip_interface_wakeup(struct thread *t) static void rip_connect_set(struct interface *ifp, int set) { + struct rip_interface *ri = ifp->info; + struct rip *rip = ri->rip; struct listnode *node, *nnode; struct connected *connected; struct prefix_ipv4 address; @@ -879,17 +897,18 @@ static void rip_connect_set(struct interface *ifp, int set) if (set) { /* Check once more wether this prefix is within a * "network IF_OR_PREF" one */ - if ((rip_enable_if_lookup(connected->ifp->name) >= 0) + if ((rip_enable_if_lookup(rip, connected->ifp->name) + >= 0) || (rip_enable_network_lookup2(connected) >= 0)) - rip_redistribute_add(ZEBRA_ROUTE_CONNECT, + rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, &nh, 0, 0, 0); } else { - rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, + rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, &address, connected->ifp->ifindex); - if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT)) - rip_redistribute_add(ZEBRA_ROUTE_CONNECT, + if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT)) + rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE, &address, &nh, 0, 0, 0); } @@ -918,7 +937,7 @@ void rip_enable_apply(struct interface *ifp) ri->enable_network = 0; /* Check interface name configuration. */ - ret = rip_enable_if_lookup(ifp->name); + ret = rip_enable_if_lookup(ri->rip, ifp->name); if (ret >= 0) ri->enable_interface = 1; else @@ -951,9 +970,9 @@ void rip_enable_apply(struct interface *ifp) } /* Apply network configuration to all interface. */ -void rip_enable_apply_all() +static void rip_enable_apply_all(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; /* Check each interface. */ @@ -961,7 +980,7 @@ void rip_enable_apply_all() rip_enable_apply(ifp); } -int rip_neighbor_lookup(struct sockaddr_in *from) +int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from) { struct prefix_ipv4 p; struct route_node *node; @@ -980,7 +999,7 @@ int rip_neighbor_lookup(struct sockaddr_in *from) } /* Add new RIP neighbor to the neighbor tree. */ -int rip_neighbor_add(struct prefix_ipv4 *p) +int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p) { struct route_node *node; @@ -995,7 +1014,7 @@ int rip_neighbor_add(struct prefix_ipv4 *p) } /* Delete RIP neighbor from the neighbor tree. */ -int rip_neighbor_delete(struct prefix_ipv4 *p) +int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p) { struct route_node *node; @@ -1016,7 +1035,7 @@ int rip_neighbor_delete(struct prefix_ipv4 *p) } /* Clear all network and neighbor configuration. */ -void rip_clean_network() +void rip_clean_network(struct rip *rip) { unsigned int i; char *str; @@ -1038,7 +1057,7 @@ void rip_clean_network() } /* Utility function for looking up passive interface settings. */ -static int rip_passive_nondefault_lookup(const char *ifname) +static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname) { unsigned int i; char *str; @@ -1050,16 +1069,17 @@ static int rip_passive_nondefault_lookup(const char *ifname) return -1; } -void rip_passive_interface_apply(struct interface *ifp) +static void rip_passive_interface_apply(struct interface *ifp) { + struct rip *rip; struct rip_interface *ri; + ri = ifp->info; + rip = ri->rip; if (rip == NULL) return; - ri = ifp->info; - - ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0) + ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0) ? rip->passive_default : !rip->passive_default); @@ -1068,9 +1088,9 @@ void rip_passive_interface_apply(struct interface *ifp) ri->passive); } -static void rip_passive_interface_apply_all(void) +static void rip_passive_interface_apply_all(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) @@ -1078,9 +1098,9 @@ static void rip_passive_interface_apply_all(void) } /* Passive interface. */ -int rip_passive_nondefault_set(const char *ifname) +int rip_passive_nondefault_set(struct rip *rip, const char *ifname) { - if (rip_passive_nondefault_lookup(ifname) >= 0) + if (rip_passive_nondefault_lookup(rip, ifname) >= 0) /* * Don't return an error, this can happen after changing * 'passive-default'. @@ -1090,17 +1110,17 @@ int rip_passive_nondefault_set(const char *ifname) vector_set(rip->passive_nondefault, XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname)); - rip_passive_interface_apply_all(); + rip_passive_interface_apply_all(rip); return NB_OK; } -int rip_passive_nondefault_unset(const char *ifname) +int rip_passive_nondefault_unset(struct rip *rip, const char *ifname) { int i; char *str; - i = rip_passive_nondefault_lookup(ifname); + i = rip_passive_nondefault_lookup(rip, ifname); if (i < 0) /* * Don't return an error, this can happen after changing @@ -1112,13 +1132,13 @@ int rip_passive_nondefault_unset(const char *ifname) XFREE(MTYPE_RIP_INTERFACE_STRING, str); vector_unset(rip->passive_nondefault, i); - rip_passive_interface_apply_all(); + rip_passive_interface_apply_all(rip); return NB_OK; } /* Free all configured RIP passive-interface settings. */ -void rip_passive_nondefault_clean(void) +void rip_passive_nondefault_clean(struct rip *rip) { unsigned int i; char *str; @@ -1128,7 +1148,7 @@ void rip_passive_nondefault_clean(void) XFREE(MTYPE_RIP_INTERFACE_STRING, str); vector_slot(rip->passive_nondefault, i) = NULL; } - rip_passive_interface_apply_all(); + rip_passive_interface_apply_all(rip); } /* Write rip configuration of each interface. */ @@ -1155,7 +1175,7 @@ static int rip_interface_config_write(struct vty *vty) return write; } -int rip_show_network_config(struct vty *vty) +int rip_show_network_config(struct vty *vty, struct rip *rip) { unsigned int i; char *ifname; @@ -1189,7 +1209,7 @@ static struct cmd_node interface_node = { /* Called when interface structure allocated. */ static int rip_interface_new_hook(struct interface *ifp) { - ifp->info = rip_interface_new(); + ifp->info = rip_interface_new(ifp); return 0; } diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 8c6340f6c7..46babe2e0b 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -79,10 +79,17 @@ static void sighup(void) /* SIGINT handler. */ static void sigint(void) { + struct vrf *vrf; + zlog_notice("Terminating on signal"); - if (rip) - rip_clean(); + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + struct rip *rip; + + rip = vrf->info; + if (rip) + rip_clean(rip); + } rip_zclient_stop(); frr_fini(); diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index b0f2b62a5d..f5a75707e8 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -40,6 +40,8 @@ static int ripd_instance_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + struct vrf *vrf; int socket; switch (event) { @@ -56,8 +58,10 @@ static int ripd_instance_create(enum nb_event event, close(socket); break; case NB_EV_APPLY: + vrf = vrf_lookup_by_id(VRF_DEFAULT); socket = resource->fd; - rip_create(socket); + rip = rip_create(vrf, socket); + yang_dnode_set_entry(dnode, rip); break; } @@ -67,10 +71,13 @@ static int ripd_instance_create(enum nb_event event, static int ripd_instance_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; - rip_clean(); + rip = yang_dnode_get_entry(dnode, true); + rip_clean(rip); return NB_OK; } @@ -82,12 +89,15 @@ static int ripd_instance_allow_ecmp_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->ecmp = yang_dnode_get_bool(dnode, NULL); if (!rip->ecmp) - rip_ecmp_disable(); + rip_ecmp_disable(rip); return NB_OK; } @@ -100,12 +110,14 @@ ripd_instance_default_information_originate_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; bool default_information; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); default_information = yang_dnode_get_bool(dnode, NULL); memset(&p, 0, sizeof(struct prefix_ipv4)); @@ -115,11 +127,11 @@ ripd_instance_default_information_originate_modify(enum nb_event event, memset(&nh, 0, sizeof(nh)); nh.type = NEXTHOP_TYPE_IPV4; - rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, - &nh, 0, 0, 0); + rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, + &p, &nh, 0, 0, 0); } else { - rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, - 0); + rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, + &p, 0); } return NB_OK; @@ -132,9 +144,12 @@ static int ripd_instance_default_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->default_metric = yang_dnode_get_uint8(dnode, NULL); /* rip_update_default_metric (); */ @@ -148,9 +163,12 @@ static int ripd_instance_distance_default_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->distance = yang_dnode_get_uint8(dnode, NULL); return NB_OK; @@ -163,6 +181,7 @@ static int ripd_instance_distance_source_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct prefix_ipv4 prefix; struct route_node *rn; @@ -173,6 +192,7 @@ static int ripd_instance_distance_source_create(enum nb_event event, apply_mask_ipv4(&prefix); /* Get RIP distance node. */ + rip = yang_dnode_get_entry(dnode, true); rn = route_node_get(rip->distance_table, (struct prefix *)&prefix); rn->info = rip_distance_new(); yang_dnode_set_entry(dnode, rn); @@ -275,31 +295,35 @@ static int ripd_instance_explicit_neighbor_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; yang_dnode_get_ipv4(&p.prefix, dnode, NULL); - return rip_neighbor_add(&p); + return rip_neighbor_add(rip, &p); } static int ripd_instance_explicit_neighbor_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; yang_dnode_get_ipv4(&p.prefix, dnode, NULL); - return rip_neighbor_delete(&p); + return rip_neighbor_delete(rip, &p); } /* @@ -309,29 +333,33 @@ static int ripd_instance_network_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct prefix p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4((struct prefix_ipv4 *)&p); - return rip_enable_network_add(&p); + return rip_enable_network_add(rip, &p); } static int ripd_instance_network_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; struct prefix p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4((struct prefix_ipv4 *)&p); - return rip_enable_network_delete(&p); + return rip_enable_network_delete(rip, &p); } /* @@ -341,27 +369,31 @@ static int ripd_instance_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_enable_if_add(ifname); + return rip_enable_if_add(rip, ifname); } static int ripd_instance_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_enable_if_delete(ifname); + return rip_enable_if_delete(rip, ifname); } /* @@ -371,15 +403,17 @@ static int ripd_instance_offset_list_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; struct rip_offset_list *offset; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, "./interface"); - offset = rip_offset_list_new(ifname); + offset = rip_offset_list_new(rip, ifname); yang_dnode_set_entry(dnode, offset); return NB_OK; @@ -464,11 +498,14 @@ static int ripd_instance_passive_default_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->passive_default = yang_dnode_get_bool(dnode, NULL); - rip_passive_nondefault_clean(); + rip_passive_nondefault_clean(rip); return NB_OK; } @@ -480,27 +517,31 @@ static int ripd_instance_passive_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_set(ifname); + return rip_passive_nondefault_set(rip, ifname); } static int ripd_instance_passive_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_unset(ifname); + return rip_passive_nondefault_unset(rip, ifname); } /* @@ -511,28 +552,32 @@ ripd_instance_non_passive_interface_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_unset(ifname); + return rip_passive_nondefault_unset(rip, ifname); } static int ripd_instance_non_passive_interface_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; const char *ifname; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); ifname = yang_dnode_get_string(dnode, NULL); - return rip_passive_nondefault_set(ifname); + return rip_passive_nondefault_set(rip, ifname); } /* @@ -548,14 +593,16 @@ static int ripd_instance_redistribute_create(enum nb_event event, static int ripd_instance_redistribute_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; int type; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - rip_redistribute_conf_delete(type); + rip_redistribute_conf_delete(rip, type); return NB_OK; } @@ -563,10 +610,13 @@ static int ripd_instance_redistribute_delete(enum nb_event event, static void ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode) { + struct rip *rip; int type; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - rip_redistribute_conf_update(type); + + rip_redistribute_conf_update(rip, type); } /* @@ -577,12 +627,14 @@ ripd_instance_redistribute_route_map_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; int type; const char *rmap_name; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); rmap_name = yang_dnode_get_string(dnode, NULL); @@ -598,11 +650,13 @@ static int ripd_instance_redistribute_route_map_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; int type; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); free(rip->route_map[type].name); @@ -620,12 +674,14 @@ ripd_instance_redistribute_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; int type; uint8_t metric; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); metric = yang_dnode_get_uint8(dnode, NULL); @@ -639,11 +695,13 @@ static int ripd_instance_redistribute_metric_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; int type; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); rip->route_map[type].metric_config = false; @@ -659,19 +717,21 @@ static int ripd_instance_static_route_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; struct nexthop nh; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4(&p); memset(&nh, 0, sizeof(nh)); nh.type = NEXTHOP_TYPE_IPV4; - rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, 0, - 0); + rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, + 0, 0); return NB_OK; } @@ -679,15 +739,17 @@ static int ripd_instance_static_route_create(enum nb_event event, static int ripd_instance_static_route_delete(enum nb_event event, const struct lyd_node *dnode) { + struct rip *rip; struct prefix_ipv4 p; if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); yang_dnode_get_ipv4p(&p, dnode, NULL); apply_mask_ipv4(&p); - rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); + rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); return NB_OK; } @@ -697,8 +759,12 @@ static int ripd_instance_static_route_delete(enum nb_event event, */ static void ripd_instance_timers_apply_finish(const struct lyd_node *dnode) { + struct rip *rip; + + rip = yang_dnode_get_entry(dnode, true); + /* Reset update timer thread. */ - rip_event(RIP_UPDATE_EVENT, 0); + rip_event(rip, RIP_UPDATE_EVENT, 0); } /* @@ -709,9 +775,12 @@ ripd_instance_timers_flush_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->garbage_time = yang_dnode_get_uint32(dnode, NULL); return NB_OK; @@ -725,9 +794,12 @@ ripd_instance_timers_holddown_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->timeout_time = yang_dnode_get_uint32(dnode, NULL); return NB_OK; @@ -741,9 +813,12 @@ ripd_instance_timers_update_interval_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->update_time = yang_dnode_get_uint32(dnode, NULL); return NB_OK; @@ -756,9 +831,12 @@ static int ripd_instance_version_receive_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->version_recv = yang_dnode_get_enum(dnode, NULL); return NB_OK; @@ -771,9 +849,12 @@ static int ripd_instance_version_send_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + if (event != NB_EV_APPLY) return NB_OK; + rip = yang_dnode_get_entry(dnode, true); rip->version_send = yang_dnode_get_enum(dnode, NULL); return NB_OK; @@ -1007,8 +1088,10 @@ static const void * ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry, const void *list_entry) { + struct rip *rip; struct listnode *node; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (rip == NULL) return NULL; @@ -1037,12 +1120,14 @@ static const void * ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, const struct yang_list_keys *keys) { + struct rip *rip; struct in_addr address; struct rip_peer *peer; struct listnode *node; yang_str2ipv4(keys->key[0], &address); + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (rip == NULL) return NULL; @@ -1111,8 +1196,10 @@ static const void * ripd_state_routes_route_get_next(const void *parent_list_entry, const void *list_entry) { + struct rip *rip; struct route_node *rn; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (rip == NULL) return NULL; @@ -1141,11 +1228,16 @@ static const void * ripd_state_routes_route_lookup_entry(const void *parent_list_entry, const struct yang_list_keys *keys) { + struct rip *rip; struct prefix prefix; struct route_node *rn; yang_str2ipv4p(keys->key[0], &prefix); + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); + if (rip == NULL) + return NULL; + rn = route_node_lookup(rip->table, &prefix); if (!rn || !rn->info) return NULL; @@ -1226,11 +1318,13 @@ ripd_state_routes_route_metric_get_elem(const char *xpath, static int clear_rip_route_rpc(const char *xpath, const struct list *input, struct list *output) { + struct rip *rip; struct route_node *rp; struct rip_info *rinfo; struct list *list; struct listnode *listnode; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return NB_OK; @@ -1245,7 +1339,7 @@ static int clear_rip_route_rpc(const char *xpath, const struct list *input, continue; if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); break; } diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index 94dc175d14..b3f84fe50f 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -35,11 +35,12 @@ #define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name) #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) -struct rip_offset_list *rip_offset_list_new(const char *ifname) +struct rip_offset_list *rip_offset_list_new(struct rip *rip, const char *ifname) { struct rip_offset_list *offset; offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); + offset->rip = rip; offset->ifname = strdup(ifname); listnode_add_sort(rip->offset_list_master, offset); @@ -48,7 +49,7 @@ struct rip_offset_list *rip_offset_list_new(const char *ifname) void offset_list_del(struct rip_offset_list *offset) { - listnode_delete(rip->offset_list_master, offset); + listnode_delete(offset->rip->offset_list_master, offset); if (OFFSET_LIST_IN_NAME(offset)) free(OFFSET_LIST_IN_NAME(offset)); if (OFFSET_LIST_OUT_NAME(offset)) @@ -57,7 +58,8 @@ void offset_list_del(struct rip_offset_list *offset) XFREE(MTYPE_RIP_OFFSET_LIST, offset); } -struct rip_offset_list *rip_offset_list_lookup(const char *ifname) +struct rip_offset_list *rip_offset_list_lookup(struct rip *rip, + const char *ifname) { struct rip_offset_list *offset; struct listnode *node, *nnode; @@ -73,11 +75,12 @@ struct rip_offset_list *rip_offset_list_lookup(const char *ifname) int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, uint32_t *metric) { + struct rip_interface *ri = ifp->info; struct rip_offset_list *offset; struct access_list *alist; /* Look up offset-list with interface name. */ - offset = rip_offset_list_lookup(ifp->name); + offset = rip_offset_list_lookup(ri->rip, ifp->name); if (offset && OFFSET_LIST_IN_NAME(offset)) { alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); @@ -90,7 +93,7 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, return 0; } /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup("*"); + offset = rip_offset_list_lookup(ri->rip, "*"); if (offset && OFFSET_LIST_IN_NAME(offset)) { alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); @@ -109,11 +112,12 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, uint32_t *metric) { + struct rip_interface *ri = ifp->info; struct rip_offset_list *offset; struct access_list *alist; /* Look up offset-list with interface name. */ - offset = rip_offset_list_lookup(ifp->name); + offset = rip_offset_list_lookup(ri->rip, ifp->name); if (offset && OFFSET_LIST_OUT_NAME(offset)) { alist = access_list_lookup(AFI_IP, OFFSET_LIST_OUT_NAME(offset)); @@ -128,7 +132,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, } /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup("*"); + offset = rip_offset_list_lookup(ri->rip, "*"); if (offset && OFFSET_LIST_OUT_NAME(offset)) { alist = access_list_lookup(AFI_IP, OFFSET_LIST_OUT_NAME(offset)); diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 07b295030e..08aa61257d 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -40,7 +40,7 @@ static void rip_peer_free(struct rip_peer *peer) XFREE(MTYPE_RIP_PEER, peer); } -struct rip_peer *rip_peer_lookup(struct in_addr *addr) +struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr) { struct rip_peer *peer; struct listnode *node, *nnode; @@ -52,7 +52,7 @@ struct rip_peer *rip_peer_lookup(struct in_addr *addr) return NULL; } -struct rip_peer *rip_peer_lookup_next(struct in_addr *addr) +struct rip_peer *rip_peer_lookup_next(struct rip *rip, struct in_addr *addr) { struct rip_peer *peer; struct listnode *node, *nnode; @@ -70,24 +70,25 @@ static int rip_peer_timeout(struct thread *t) struct rip_peer *peer; peer = THREAD_ARG(t); - listnode_delete(rip->peer_list, peer); + listnode_delete(peer->rip->peer_list, peer); rip_peer_free(peer); return 0; } /* Get RIP peer. At the same time update timeout thread. */ -static struct rip_peer *rip_peer_get(struct in_addr *addr) +static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr) { struct rip_peer *peer; - peer = rip_peer_lookup(addr); + peer = rip_peer_lookup(rip, addr); if (peer) { if (peer->t_timeout) thread_cancel(peer->t_timeout); } else { peer = rip_peer_new(); + peer->rip = rip; peer->addr = *addr; listnode_add_sort(rip->peer_list, peer); } @@ -103,24 +104,24 @@ static struct rip_peer *rip_peer_get(struct in_addr *addr) return peer; } -void rip_peer_update(struct sockaddr_in *from, uint8_t version) +void rip_peer_update(struct rip *rip, struct sockaddr_in *from, uint8_t version) { struct rip_peer *peer; - peer = rip_peer_get(&from->sin_addr); + peer = rip_peer_get(rip, &from->sin_addr); peer->version = version; } -void rip_peer_bad_route(struct sockaddr_in *from) +void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from) { struct rip_peer *peer; - peer = rip_peer_get(&from->sin_addr); + peer = rip_peer_get(rip, &from->sin_addr); peer->recv_badroutes++; } -void rip_peer_bad_packet(struct sockaddr_in *from) +void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from) { struct rip_peer *peer; - peer = rip_peer_get(&from->sin_addr); + peer = rip_peer_get(rip, &from->sin_addr); peer->recv_badpackets++; } @@ -153,7 +154,7 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len) return buf; } -void rip_peer_display(struct vty *vty) +void rip_peer_display(struct vty *vty, struct rip *rip) { struct rip_peer *peer; struct listnode *node, *nnode; diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 54c8a2eb8c..5a6b71fbaa 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -156,10 +156,13 @@ static uint8_t *rip2Globals(struct variable *v, oid name[], size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { + struct rip *rip; + if (smux_header_generic(v, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return NULL; @@ -284,9 +287,11 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], size_t *length, struct in_addr *addr, int exact) { + struct rip *rip; int len; struct rip_peer *peer; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return NULL; @@ -297,7 +302,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); - peer = rip_peer_lookup(addr); + peer = rip_peer_lookup(rip, addr); if (peer->domain == (int)name[v->namelen + sizeof(struct in_addr)]) @@ -312,7 +317,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], oid2in_addr(name + v->namelen, len, addr); len = *length - v->namelen; - peer = rip_peer_lookup(addr); + peer = rip_peer_lookup(rip, addr); if (peer) { if ((len < (int)sizeof(struct in_addr) + 1) || (peer->domain @@ -327,7 +332,7 @@ static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], return peer; } } - peer = rip_peer_lookup_next(addr); + peer = rip_peer_lookup_next(rip, addr); if (!peer) return NULL; @@ -408,10 +413,10 @@ static long rip2IfConfSend(struct rip_interface *ri) return ripVersion2; else if (ri->ri_send & RIPv1) return ripVersion1; - else if (rip) { - if (rip->version_send == RIPv2) + else if (ri->rip) { + if (ri->rip->version_send == RIPv2) return ripVersion2; - else if (rip->version_send == RIPv1) + else if (ri->rip->version_send == RIPv1) return ripVersion1; } return doNotSend; @@ -429,7 +434,7 @@ static long rip2IfConfReceive(struct rip_interface *ri) if (!ri->running) return doNotReceive; - recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv + recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? ri->rip->version_recv : ri->ri_receive; if (recvv == RI_RIP_VERSION_1_AND_2) return rip1OrRip2; diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 607dc168f4..6fbc170cb9 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -36,7 +36,8 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ -static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd) +static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp, + uint8_t cmd) { struct list *list = (struct list *)rp->info; struct zapi_route api; @@ -46,7 +47,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd) int count = 0; memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = rip->vrf_id; api.type = ZEBRA_ROUTE_RIP; api.safi = SAFI_UNICAST; @@ -55,7 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd) if (count >= MULTIPATH_NUM) break; api_nh = &api.nexthops[count]; - api_nh->vrf_id = VRF_DEFAULT; + api_nh->vrf_id = rip->vrf_id; api_nh->gate = rinfo->nh.gate; api_nh->type = NEXTHOP_TYPE_IPV4; if (cmd == ZEBRA_ROUTE_ADD) @@ -105,24 +106,26 @@ static void rip_zebra_ipv4_send(struct route_node *rp, uint8_t cmd) } /* Add/update ECMP routes to zebra. */ -void rip_zebra_ipv4_add(struct route_node *rp) +void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp) { - rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD); + rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ -void rip_zebra_ipv4_delete(struct route_node *rp) +void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp) { - rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE); + rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ static int rip_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { + struct rip *rip; struct zapi_route api; struct nexthop nh; + rip = rip_lookup_by_vrf_id(vrf_id); if (!rip) return 0; @@ -136,59 +139,59 @@ static int rip_zebra_read_route(int command, struct zclient *zclient, /* Then fetch IPv4 prefixes. */ if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) - rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, + rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE, (struct prefix_ipv4 *)&api.prefix, &nh, api.metric, api.distance, api.tag); else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) - rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, + rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE, (struct prefix_ipv4 *)&api.prefix, nh.ifindex); return 0; } -void rip_redistribute_conf_update(int type) +void rip_redistribute_conf_update(struct rip *rip, int type) { zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, - 0, VRF_DEFAULT); + 0, rip->vrf_id); } -void rip_redistribute_conf_delete(int type) +void rip_redistribute_conf_delete(struct rip *rip, int type) { if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, - AFI_IP, type, 0, VRF_DEFAULT); + AFI_IP, type, 0, rip->vrf_id); /* Remove the routes from RIP table. */ - rip_redistribute_withdraw(type); + rip_redistribute_withdraw(rip, type); } -int rip_redistribute_check(int type) +int rip_redistribute_check(struct rip *rip, int type) { - return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT); + return vrf_bitmap_check(zclient->redist[AFI_IP][type], rip->vrf_id); } -void rip_redistribute_clean(void) +void rip_redistribute_clean(struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], VRF_DEFAULT)) + if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], rip->vrf_id)) continue; if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, i, 0, - VRF_DEFAULT); + rip->vrf_id); - vrf_bitmap_unset(zclient->redist[AFI_IP][i], VRF_DEFAULT); + vrf_bitmap_unset(zclient->redist[AFI_IP][i], rip->vrf_id); } } -void rip_show_redistribute_config(struct vty *vty) +void rip_show_redistribute_config(struct vty *vty, struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == zclient->redist_default || !vrf_bitmap_check(zclient->redist[AFI_IP][i], - VRF_DEFAULT)) + rip->vrf_id)) continue; vty_out(vty, " %s", zebra_route_string(i)); diff --git a/ripd/ripd.c b/ripd/ripd.c index a6cfd9b151..6b9c5fe886 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -50,9 +50,6 @@ /* UDP receive buffer size */ #define RIP_UDP_RCV_BUF 41600 -/* RIP Structure. */ -struct rip *rip = NULL; - /* Prototypes. */ static void rip_output_process(struct connected *, struct sockaddr_in *, int, uint8_t); @@ -107,6 +104,11 @@ void rip_info_free(struct rip_info *rinfo) XFREE(MTYPE_RIP_INFO, rinfo); } +struct rip *rip_info_get_instance(const struct rip_info *rinfo) +{ + return route_table_get_info(rinfo->rp->table); +} + /* RIP route garbage collect timer. */ static int rip_garbage_collect(struct thread *t) { @@ -135,13 +137,13 @@ static int rip_garbage_collect(struct thread *t) return 0; } -static void rip_timeout_update(struct rip_info *rinfo); +static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) +struct rip_info *rip_ecmp_add(struct rip *rip, struct rip_info *rinfo_new) { struct route_node *rp = rinfo_new->rp; struct rip_info *rinfo = NULL; @@ -161,8 +163,8 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) listnode_add(list, rinfo); if (rip_route_rte(rinfo)) { - rip_timeout_update(rinfo); - rip_zebra_ipv4_add(rp); + rip_timeout_update(rip, rinfo); + rip_zebra_ipv4_add(rip, rp); } /* Set the route change flag on the first entry. */ @@ -170,7 +172,7 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update (see section 2.5). */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); return rinfo; } @@ -178,7 +180,7 @@ struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) +struct rip_info *rip_ecmp_replace(struct rip *rip, struct rip_info *rinfo_new) { struct route_node *rp = rinfo_new->rp; struct list *list = (struct list *)rp->info; @@ -186,7 +188,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) struct listnode *node = NULL, *nextnode = NULL; if (list == NULL || listcount(list) == 0) - return rip_ecmp_add(rinfo_new); + return rip_ecmp_add(rip, rinfo_new); /* Get the first entry */ rinfo = listgetdata(listhead(list)); @@ -194,7 +196,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) /* Learnt route replaced by a local one. Delete it from zebra. */ if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new)) if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); /* Re-use the first entry, and delete the others. */ for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) @@ -210,16 +212,16 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) memcpy(rinfo, rinfo_new, sizeof(struct rip_info)); if (rip_route_rte(rinfo)) { - rip_timeout_update(rinfo); + rip_timeout_update(rip, rinfo); /* The ADD message implies an update. */ - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); } /* Set the route change flag. */ SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update (see section 2.5). */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); return rinfo; } @@ -230,7 +232,7 @@ struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) +struct rip_info *rip_ecmp_delete(struct rip *rip, struct rip_info *rinfo) { struct route_node *rp = rinfo->rp; struct list *list = (struct list *)rp->info; @@ -245,7 +247,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) if (rip_route_rte(rinfo) && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) /* The ADD message implies the update. */ - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); rip_info_free(rinfo); rinfo = NULL; } else { @@ -261,7 +263,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) if (rip_route_rte(rinfo) && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); } /* Set the route change flag on the first entry. */ @@ -269,7 +271,7 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update (see section 2.5). */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); return rinfo; } @@ -277,15 +279,20 @@ struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) /* Timeout RIP routes. */ static int rip_timeout(struct thread *t) { - rip_ecmp_delete((struct rip_info *)THREAD_ARG(t)); + struct rip_info *rinfo = THREAD_ARG(t); + struct rip *rip = rip_info_get_instance(rinfo); + + rip_ecmp_delete(rip, rinfo); + return 0; } -static void rip_timeout_update(struct rip_info *rinfo) +static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo) { if (rinfo->metric != RIP_METRIC_INFINITY) { RIP_TIMER_OFF(rinfo->t_timeout); - RIP_TIMER_ON(rinfo->t_timeout, rip_timeout, rip->timeout_time); + thread_add_timer(master, rip_timeout, rinfo, rip->timeout_time, + &rinfo->t_timeout); } } @@ -324,7 +331,7 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, } /* All interface filter check. */ - dist = distribute_lookup(rip->distribute_ctx, NULL); + dist = distribute_lookup(ri->rip->distribute_ctx, NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup(AFI_IP, @@ -363,9 +370,9 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, } /* Check nexthop address validity. */ -static int rip_nexthop_check(struct in_addr *addr) +static int rip_nexthop_check(struct rip *rip, struct in_addr *addr) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; struct listnode *cnode; struct connected *ifc; @@ -390,6 +397,7 @@ static int rip_nexthop_check(struct in_addr *addr) static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, struct interface *ifp) { + struct rip *rip; int ret; struct prefix_ipv4 p; struct route_node *rp; @@ -410,9 +418,10 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, /* Make sure mask is applied. */ apply_mask_ipv4(&p); - /* Apply input filters. */ ri = ifp->info; + rip = ri->rip; + /* Apply input filters. */ ret = rip_filter(RIP_FILTER_IN, &p, ri); if (ret < 0) return; @@ -471,7 +480,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, nexthop = &rte->nexthop; /* Check if nexthop address is myself, then do nothing. */ - if (rip_nexthop_check(nexthop) < 0) { + if (rip_nexthop_check(rip, nexthop) < 0) { if (IS_RIP_DEBUG_PACKET) zlog_debug("Nexthop address %s is myself", inet_ntoa(*nexthop)); @@ -486,7 +495,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, newinfo.nh.type = NEXTHOP_TYPE_IPV4; newinfo.metric = rte->metric; newinfo.tag = ntohs(rte->tag); - newinfo.distance = rip_distance_apply(&newinfo); + newinfo.distance = rip_distance_apply(rip, &newinfo); new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT; @@ -570,7 +579,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, mark it as a ghost */ if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); route_unlock_node(rp); return; @@ -587,7 +596,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, infinity (there is no point in adding a route which unusable). */ if (rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_add(&newinfo); + rip_ecmp_add(rip, &newinfo); } else { /* Route is there but we are not sure the route is RIP or not. */ @@ -616,18 +625,18 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, || ((old_dist != new_dist) && same)) { if (listcount(list) == 1) { if (newinfo.metric != RIP_METRIC_INFINITY) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); else - rip_ecmp_delete(rinfo); + rip_ecmp_delete(rip, rinfo); } else { if (newinfo.metric < rinfo->metric) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); else if (newinfo.metric > rinfo->metric) - rip_ecmp_delete(rinfo); + rip_ecmp_delete(rip, rinfo); else if (new_dist < old_dist) - rip_ecmp_replace(&newinfo); + rip_ecmp_replace(rip, &newinfo); else if (new_dist > old_dist) - rip_ecmp_delete(rinfo); + rip_ecmp_delete(rip, rinfo); else { int update = CHECK_FLAG(rinfo->flags, RIP_RTF_FIB) @@ -641,20 +650,20 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, RIP_TIMER_OFF(rinfo->t_garbage_collect); memcpy(rinfo, &newinfo, sizeof(struct rip_info)); - rip_timeout_update(rinfo); + rip_timeout_update(rip, rinfo); if (update) - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); /* - Set the route change flag on the * first entry. */ rinfo = listgetdata(listhead(list)); SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } } else /* same & no change */ - rip_timeout_update(rinfo); + rip_timeout_update(rip, rinfo); /* Unlock tempolary lock of the route. */ route_unlock_node(rp); @@ -1080,6 +1089,8 @@ static void rip_response_process(struct rip_packet *packet, int size, struct sockaddr_in *from, struct connected *ifc) { + struct rip_interface *ri = ifc->ifp->info; + struct rip *rip = ri->rip; caddr_t lim; struct rte *rte; struct prefix_ipv4 ifaddr; @@ -1095,7 +1106,7 @@ static void rip_response_process(struct rip_packet *packet, int size, if (from->sin_port != htons(RIP_PORT_DEFAULT)) { zlog_info("response doesn't come from RIP port: %d", from->sin_port); - rip_peer_bad_packet(from); + rip_peer_bad_packet(rip, from); return; } @@ -1103,12 +1114,12 @@ static void rip_response_process(struct rip_packet *packet, int size, whether the datagram is from a valid neighbor; the source of the datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */ - if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) + if (if_lookup_address((void *)&from->sin_addr, AF_INET, rip->vrf_id) == NULL) { zlog_info( "This datagram doesn't came from a valid neighbor: %s", inet_ntoa(from->sin_addr)); - rip_peer_bad_packet(from); + rip_peer_bad_packet(rip, from); return; } @@ -1118,7 +1129,7 @@ static void rip_response_process(struct rip_packet *packet, int size, ; /* Alredy done in rip_read () */ /* Update RIP peer. */ - rip_peer_update(from, packet->version); + rip_peer_update(rip, from, packet->version); /* Set RTE pointer. */ rte = packet->rte; @@ -1147,7 +1158,7 @@ static void rip_response_process(struct rip_packet *packet, int size, if (!rip_destination_check(rte->prefix)) { zlog_info( "Network is net 0 or net 127 or it is not unicast network"); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1157,7 +1168,7 @@ static void rip_response_process(struct rip_packet *packet, int size, /* - is the metric valid (i.e., between 1 and 16, inclusive) */ if (!(rte->metric >= 1 && rte->metric <= 16)) { zlog_info("Route's metric is not in the 1-16 range."); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1165,7 +1176,7 @@ static void rip_response_process(struct rip_packet *packet, int size, if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) { zlog_info("RIPv1 packet with nexthop value %s", inet_ntoa(rte->nexthop)); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1186,7 +1197,7 @@ static void rip_response_process(struct rip_packet *packet, int size, } if (!if_lookup_address((void *)&rte->nexthop, AF_INET, - VRF_DEFAULT)) { + rip->vrf_id)) { struct route_node *rn; struct rip_info *rinfo; @@ -1297,7 +1308,7 @@ static void rip_response_process(struct rip_packet *packet, int size, zlog_warn( "RIPv2 address %s is not mask /%d applied one", inet_ntoa(rte->prefix), ip_masklen(rte->mask)); - rip_peer_bad_route(from); + rip_peer_bad_route(rip, from); continue; } @@ -1371,10 +1382,14 @@ int rip_create_socket(void) static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, struct connected *ifc) { + struct rip_interface *ri; + struct rip *rip; int ret; struct sockaddr_in sin; assert(ifc != NULL); + ri = ifc->ifp->info; + rip = ri->rip; if (IS_RIP_DEBUG_PACKET) { #define ADDRESS_SIZE 20 @@ -1447,9 +1462,10 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, } /* Add redistributed route to RIP table. */ -void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, - struct nexthop *nh, unsigned int metric, - unsigned char distance, route_tag_t tag) +void rip_redistribute_add(struct rip *rip, int type, int sub_type, + struct prefix_ipv4 *p, struct nexthop *nh, + unsigned int metric, unsigned char distance, + route_tag_t tag) { int ret; struct route_node *rp = NULL; @@ -1496,22 +1512,22 @@ void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, } } - (void)rip_ecmp_replace(&newinfo); + (void)rip_ecmp_replace(rip, &newinfo); route_unlock_node(rp); } else - (void)rip_ecmp_add(&newinfo); + (void)rip_ecmp_add(rip, &newinfo); if (IS_RIP_DEBUG_EVENT) { zlog_debug("Redistribute new prefix %s/%d", inet_ntoa(p->prefix), p->prefixlen); } - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } /* Delete redistributed route from RIP table. */ -void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex) +void rip_redistribute_delete(struct rip *rip, int type, int sub_type, + struct prefix_ipv4 *p, ifindex_t ifindex) { int ret; struct route_node *rp; @@ -1545,9 +1561,9 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, inet_ntoa(p->prefix), p->prefixlen, ifindex2ifname(ifindex, - VRF_DEFAULT)); + rip->vrf_id)); - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } route_unlock_node(rp); @@ -1558,6 +1574,7 @@ void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, static void rip_request_process(struct rip_packet *packet, int size, struct sockaddr_in *from, struct connected *ifc) { + struct rip *rip; caddr_t lim; struct rte *rte; struct prefix_ipv4 p; @@ -1573,13 +1590,14 @@ static void rip_request_process(struct rip_packet *packet, int size, ri = ifc->ifp->info; if (!ri->running) return; + rip = ri->rip; /* When passive interface is specified, suppress responses */ if (ri->passive) return; /* RIP peer update. */ - rip_peer_update(from, packet->version); + rip_peer_update(rip, from, packet->version); lim = ((caddr_t)packet) + size; rte = packet->rte; @@ -1635,6 +1653,7 @@ static void rip_request_process(struct rip_packet *packet, int size, /* First entry point of RIP packet. */ static int rip_read(struct thread *t) { + struct rip *rip = THREAD_ARG(t); int sock; int ret; int rtenum; @@ -1654,7 +1673,7 @@ static int rip_read(struct thread *t) rip->t_read = NULL; /* Add myself to tne next event */ - rip_event(RIP_READ, sock); + rip_event(rip, RIP_READ, sock); /* RIPd manages only IPv4. */ memset(&from, 0, sizeof(struct sockaddr_in)); @@ -1668,14 +1687,14 @@ static int rip_read(struct thread *t) } /* Check is this packet comming from myself? */ - if (if_check_address(from.sin_addr)) { + if (if_check_address(rip, from.sin_addr)) { if (IS_RIP_DEBUG_PACKET) zlog_debug("ignore packet comes from myself"); return -1; } /* Which interface is this packet comes from. */ - ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); + ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, rip->vrf_id); if (ifc) ifp = ifc->ifp; @@ -1712,13 +1731,13 @@ static int rip_read(struct thread *t) if (len < RIP_PACKET_MINSIZ) { zlog_warn("packet size %d is smaller than minimum size %d", len, RIP_PACKET_MINSIZ); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return len; } if (len > RIP_PACKET_MAXSIZ) { zlog_warn("packet size %d is larger than max size %d", len, RIP_PACKET_MAXSIZ); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return len; } @@ -1726,7 +1745,7 @@ static int rip_read(struct thread *t) if ((len - RIP_PACKET_MINSIZ) % 20) { zlog_warn("packet size %d is wrong for RIP packet alignment", len); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return len; } @@ -1740,7 +1759,7 @@ static int rip_read(struct thread *t) if (packet->version == 0) { zlog_info("version 0 with command %d received.", packet->command); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1757,11 +1776,11 @@ static int rip_read(struct thread *t) /* Is RIP running or is this RIP neighbor ?*/ ri = ifp->info; - if (!ri->running && !rip_neighbor_lookup(&from)) { + if (!ri->running && !rip_neighbor_lookup(rip, &from)) { if (IS_RIP_DEBUG_EVENT) zlog_debug("RIP is not enabled on interface %s.", ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1775,7 +1794,7 @@ static int rip_read(struct thread *t) zlog_debug( " packet's v%d doesn't fit to if version spec", packet->version); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1790,7 +1809,7 @@ static int rip_read(struct thread *t) "packet RIPv%d is dropped because authentication disabled", packet->version); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1827,7 +1846,7 @@ static int rip_read(struct thread *t) "RIPv1" " dropped because authentication enabled"); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } } else if (ri->auth_type != RIP_NO_AUTH) { @@ -1840,7 +1859,7 @@ static int rip_read(struct thread *t) zlog_debug( "RIPv2 authentication failed: no auth RTE in packet"); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1851,7 +1870,7 @@ static int rip_read(struct thread *t) "RIPv2" " dropped because authentication enabled"); ripd_notif_send_auth_type_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } @@ -1887,7 +1906,7 @@ static int rip_read(struct thread *t) zlog_debug("RIPv2 %s authentication failure", auth_desc); ripd_notif_send_auth_failure(ifp->name); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); return -1; } } @@ -1906,16 +1925,16 @@ static int rip_read(struct thread *t) zlog_info( "Obsolete command %s received, please sent it to routed", lookup_msg(rip_msg, packet->command, NULL)); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); break; case RIP_POLL_ENTRY: zlog_info("Obsolete command %s received", lookup_msg(rip_msg, packet->command, NULL)); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); break; default: zlog_info("Unknown RIP command %d received", packet->command); - rip_peer_bad_packet(&from); + rip_peer_bad_packet(rip, &from); break; } @@ -1955,6 +1974,7 @@ static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p, void rip_output_process(struct connected *ifc, struct sockaddr_in *to, int route_type, uint8_t version) { + struct rip *rip; int ret; struct stream *s; struct route_node *rp; @@ -1984,6 +2004,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, ifc->ifp->name, ifc->ifp->ifindex); } + /* Get RIP interface. */ + ri = ifc->ifp->info; + rip = ri->rip; + /* Set output stream. */ s = rip->obuf; @@ -1991,9 +2015,6 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, stream_reset(s); rtemax = RIP_MAX_RTE; - /* Get RIP interface. */ - ri = ifc->ifp->info; - /* If output interface is in simple password authentication mode, we need space for authentication data. */ if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) @@ -2366,9 +2387,9 @@ static void rip_update_interface(struct connected *ifc, uint8_t version, } /* Update send to all interface and neighbor. */ -static void rip_update_process(int route_type) +static void rip_update_process(struct rip *rip, int route_type) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct listnode *ifnode, *ifnnode; struct connected *connected; struct interface *ifp; @@ -2431,7 +2452,7 @@ static void rip_update_process(int route_type) p = &rp->p; connected = if_lookup_address(&p->u.prefix4, AF_INET, - VRF_DEFAULT); + rip->vrf_id); if (!connected) { zlog_warn( "Neighbor %s doesn't have connected interface!", @@ -2453,6 +2474,8 @@ static void rip_update_process(int route_type) /* RIP's periodical timer. */ static int rip_update(struct thread *t) { + struct rip *rip = THREAD_ARG(t); + /* Clear timer pointer. */ rip->t_update = NULL; @@ -2460,7 +2483,7 @@ static int rip_update(struct thread *t) zlog_debug("update timer fire!"); /* Process update output. */ - rip_update_process(rip_all_route); + rip_update_process(rip, rip_all_route); /* Triggered updates may be suppressed if a regular update is due by the time the triggered update would be sent. */ @@ -2468,13 +2491,13 @@ static int rip_update(struct thread *t) rip->trigger = 0; /* Register myself. */ - rip_event(RIP_UPDATE_EVENT, 0); + rip_event(rip, RIP_UPDATE_EVENT, 0); return 0; } /* Walk down the RIP routing table then clear changed flag. */ -static void rip_clear_changed_flag(void) +static void rip_clear_changed_flag(struct rip *rip) { struct route_node *rp; struct rip_info *rinfo = NULL; @@ -2494,7 +2517,7 @@ static void rip_clear_changed_flag(void) /* Triggered update interval timer. */ static int rip_triggered_interval(struct thread *t) { - int rip_triggered_update(struct thread *); + struct rip *rip = THREAD_ARG(t); rip->t_triggered_interval = NULL; @@ -2508,6 +2531,7 @@ static int rip_triggered_interval(struct thread *t) /* Execute triggered update. */ static int rip_triggered_update(struct thread *t) { + struct rip *rip = THREAD_ARG(t); int interval; /* Clear thred pointer. */ @@ -2523,11 +2547,11 @@ static int rip_triggered_update(struct thread *t) /* Split Horizon processing is done when generating triggered updates as well as normal updates (see section 2.6). */ - rip_update_process(rip_changed_route); + rip_update_process(rip, rip_changed_route); /* Once all of the triggered updates have been generated, the route change flags should be cleared. */ - rip_clear_changed_flag(); + rip_clear_changed_flag(rip); /* After a triggered update is sent, a timer should be set for a random interval between 1 and 5 seconds. If other changes that @@ -2536,14 +2560,14 @@ static int rip_triggered_update(struct thread *t) interval = (random() % 5) + 1; rip->t_triggered_interval = NULL; - thread_add_timer(master, rip_triggered_interval, NULL, interval, + thread_add_timer(master, rip_triggered_interval, rip, interval, &rip->t_triggered_interval); return 0; } /* Withdraw redistributed route. */ -void rip_redistribute_withdraw(int type) +void rip_redistribute_withdraw(struct rip *rip, int type) { struct route_node *rp; struct rip_info *rinfo = NULL; @@ -2572,17 +2596,31 @@ void rip_redistribute_withdraw(int type) p->prefixlen, ifindex2ifname( rinfo->nh.ifindex, - VRF_DEFAULT)); + rip->vrf_id)); } - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } } -/* Create new RIP instance and set it to global variable. */ -int rip_create(int socket) +struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id) { + struct vrf *vrf; + + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) + return NULL; + + return vrf->info; +} + +/* Create new RIP instance and set it to global variable. */ +struct rip *rip_create(struct vrf *vrf, int socket) +{ + struct rip *rip; + struct interface *ifp; + rip = XCALLOC(MTYPE_RIP, sizeof(struct rip)); /* Set initial value. */ @@ -2606,6 +2644,7 @@ int rip_create(int socket) /* 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; @@ -2632,10 +2671,20 @@ int rip_create(int socket) rip->sock = socket; /* Create read and timer thread. */ - rip_event(RIP_READ, rip->sock); - rip_event(RIP_UPDATE_EVENT, 1); + rip_event(rip, RIP_READ, rip->sock); + rip_event(rip, RIP_UPDATE_EVENT, 1); - return 0; + /* Link RIP instance to VRF. */ + rip->vrf_id = vrf->vrf_id; + vrf->info = rip; + FOR_ALL_INTERFACES (vrf, ifp) { + struct rip_interface *ri; + + ri = ifp->info; + ri->rip = rip; + } + + return rip; } /* Sned RIP request to the destination. */ @@ -2704,19 +2753,19 @@ static int rip_update_jitter(unsigned long time) return jitter / JITTER_BOUND; } -void rip_event(enum rip_event event, int sock) +void rip_event(struct rip *rip, enum rip_event event, int sock) { int jitter = 0; switch (event) { case RIP_READ: rip->t_read = NULL; - thread_add_read(master, rip_read, NULL, sock, &rip->t_read); + thread_add_read(master, rip_read, rip, sock, &rip->t_read); break; case RIP_UPDATE_EVENT: RIP_TIMER_OFF(rip->t_update); jitter = rip_update_jitter(rip->update_time); - thread_add_timer(master, rip_update, NULL, + thread_add_timer(master, rip_update, rip, sock ? 2 : rip->update_time + jitter, &rip->t_update); break; @@ -2724,7 +2773,7 @@ void rip_event(enum rip_event event, int sock) if (rip->t_triggered_interval) rip->trigger = 1; else - thread_add_event(master, rip_triggered_update, NULL, 0, + thread_add_event(master, rip_triggered_update, rip, 0, &rip->t_triggered_update); break; default: @@ -2772,16 +2821,13 @@ static void rip_distance_table_node_cleanup(struct route_table *table, } /* Apply RIP information to distance method. */ -uint8_t rip_distance_apply(struct rip_info *rinfo) +uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo) { struct route_node *rn; struct prefix_ipv4 p; struct rip_distance *rdistance; struct access_list *alist; - if (!rip) - return 0; - memset(&p, 0, sizeof(struct prefix_ipv4)); p.family = AF_INET; p.prefix = rinfo->from; @@ -2813,7 +2859,7 @@ uint8_t rip_distance_apply(struct rip_info *rinfo) return 0; } -static void rip_distance_show(struct vty *vty) +static void rip_distance_show(struct vty *vty, struct rip *rip) { struct route_node *rn; struct rip_distance *rdistance; @@ -2840,16 +2886,13 @@ static void rip_distance_show(struct vty *vty) } /* Update ECMP routes to zebra when ECMP is disabled. */ -void rip_ecmp_disable(void) +void rip_ecmp_disable(struct rip *rip) { struct route_node *rp; struct rip_info *rinfo, *tmp_rinfo; struct list *list; struct listnode *node, *nextnode; - if (!rip) - return; - for (rp = route_top(rip->table); rp; rp = route_next(rp)) if ((list = rp->info) != NULL && listcount(list) > 1) { rinfo = listgetdata(listhead(list)); @@ -2867,13 +2910,13 @@ void rip_ecmp_disable(void) } /* Update zebra. */ - rip_zebra_ipv4_add(rp); + rip_zebra_ipv4_add(rip, rp); /* Set the route change flag. */ SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); /* Signal the output process to trigger an update. */ - rip_event(RIP_TRIGGERED_UPDATE, 0); + rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } } @@ -2924,11 +2967,13 @@ DEFUN (show_ip_rip, IP_STR "Show RIP routes\n") { + struct rip *rip; struct route_node *np; struct rip_info *rinfo = NULL; struct list *list = NULL; struct listnode *listnode = NULL; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return CMD_SUCCESS; @@ -3028,13 +3073,15 @@ DEFUN (show_ip_rip_status, "Show RIP routes\n" "IP routing protocol process parameters and statistics\n") { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct rip *rip; + struct vrf *vrf; struct interface *ifp; struct rip_interface *ri; extern const struct message ri_version_msg[]; const char *send_version; const char *receive_version; + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); if (!rip) return CMD_SUCCESS; @@ -3055,7 +3102,7 @@ DEFUN (show_ip_rip_status, /* Redistribute information. */ vty_out(vty, " Redistributing:"); - rip_show_redistribute_config(vty); + rip_show_redistribute_config(vty, rip); vty_out(vty, "\n"); vty_out(vty, " Default version control: send version %s,", @@ -3068,6 +3115,7 @@ DEFUN (show_ip_rip_status, vty_out(vty, " Interface Send Recv Key-chain\n"); + vrf = vrf_lookup_by_id(rip->vrf_id); FOR_ALL_INTERFACES (vrf, ifp) { ri = ifp->info; @@ -3098,7 +3146,7 @@ DEFUN (show_ip_rip_status, } vty_out(vty, " Routing for Networks:\n"); - rip_show_network_config(vty); + rip_show_network_config(vty, rip); { int found_passive = 0; @@ -3120,9 +3168,9 @@ DEFUN (show_ip_rip_status, vty_out(vty, " Routing Information Sources:\n"); vty_out(vty, " Gateway BadPackets BadRoutes Distance Last Update\n"); - rip_peer_display(vty); + rip_peer_display(vty, rip); - rip_distance_show(vty); + rip_distance_show(vty, rip); return CMD_SUCCESS; } @@ -3136,16 +3184,21 @@ static int config_write_rip(struct vty *vty) dnode = yang_dnode_get(running_config->dnode, "/frr-ripd:ripd/instance"); if (dnode) { + struct rip *rip; + write++; nb_cli_show_dnode_cmds(vty, dnode, false); - /* Distribute configuration. */ - write += config_write_distribute(vty, - rip->distribute_ctx); + rip = rip_lookup_by_vrf_id(VRF_DEFAULT); + if (rip) { + /* Distribute configuration. */ + write += config_write_distribute(vty, + rip->distribute_ctx); - /* Interface routemap configuration */ - write += config_write_if_rmap(vty); + /* Interface routemap configuration */ + write += config_write_if_rmap(vty); + } } return write; } @@ -3214,6 +3267,8 @@ static void rip_distribute_update(struct distribute_ctx *ctx, void rip_distribute_update_interface(struct interface *ifp) { + struct rip_interface *ri = ifp->info; + struct rip *rip = ri->rip; struct distribute *dist; if (!rip) @@ -3240,8 +3295,10 @@ static void rip_distribute_update_all_wrapper(struct access_list *notused) } /* Delete all added rip route. */ -void rip_clean(void) +void rip_clean(struct rip *rip) { + struct vrf *vrf; + struct interface *ifp; struct route_node *rp; /* Clear RIP routes */ @@ -3255,7 +3312,7 @@ void rip_clean(void) rinfo = listgetdata(listhead(list)); if (rip_route_rte(rinfo)) - rip_zebra_ipv4_delete(rp); + rip_zebra_ipv4_delete(rip, rp); for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { RIP_TIMER_OFF(rinfo->t_timeout); @@ -3292,15 +3349,25 @@ void rip_clean(void) list_delete(&rip->peer_list); distribute_list_delete(&rip->distribute_ctx); - rip_clean_network(); - rip_passive_nondefault_clean(); + rip_clean_network(rip); + rip_passive_nondefault_clean(rip); vector_free(rip->enable_interface); route_table_finish(rip->enable_network); vector_free(rip->passive_nondefault); list_delete(&rip->offset_list_master); - rip_interfaces_clean(); + rip_interfaces_clean(rip); route_table_finish(rip->distance_table); - rip_redistribute_clean(); + rip_redistribute_clean(rip); + + vrf = vrf_lookup_by_id(rip->vrf_id); + vrf->info = NULL; + + FOR_ALL_INTERFACES (vrf, ifp) { + struct rip_interface *ri; + + ri = ifp->info; + ri->rip = NULL; + } XFREE(MTYPE_RIP, rip); } @@ -3344,17 +3411,12 @@ void rip_if_rmap_update_interface(struct interface *ifp) rip_if_rmap_update(if_rmap); } -static void rip_routemap_update_redistribute(void) +static void rip_routemap_update_redistribute(struct rip *rip) { - int i; - - if (rip) { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (rip->route_map[i].name) - rip->route_map[i].map = - route_map_lookup_by_name( - rip->route_map[i].name); - } + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rip->route_map[i].name) + rip->route_map[i].map = route_map_lookup_by_name( + rip->route_map[i].name); } } @@ -3362,12 +3424,15 @@ static void rip_routemap_update_redistribute(void) static void rip_routemap_update(const char *notused) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct rip *rip; struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) rip_if_rmap_update_interface(ifp); - rip_routemap_update_redistribute(); + rip = vrf->info; + if (rip) + rip_routemap_update_redistribute(rip); } /* Allocate new rip structure and set default value. */ diff --git a/ripd/ripd.h b/ripd/ripd.h index af0d3021a6..a18a741579 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -99,6 +99,9 @@ /* RIP structure. */ struct rip { + /* VRF ID. */ + vrf_id_t vrf_id; + /* RIP socket. */ int sock; @@ -256,6 +259,9 @@ typedef enum { /* RIP specific interface configuration. */ struct rip_interface { + /* Parent routing instance. */ + struct rip *rip; + /* RIP is enabled on this interface. */ int enable_network; int enable_interface; @@ -313,6 +319,9 @@ struct rip_interface { /* RIP peer information. */ struct rip_peer { + /* Parent routing instance. */ + struct rip *rip; + /* Peer address. */ struct in_addr addr; @@ -385,6 +394,9 @@ enum rip_event { #define RIP_OFFSET_LIST_MAX 2 struct rip_offset_list { + /* Parent routing instance. */ + struct rip *rip; + char *ifname; struct { @@ -396,75 +408,86 @@ struct rip_offset_list { /* Prototypes. */ extern void rip_init(void); -extern void rip_clean(void); -extern void rip_clean_network(void); -extern void rip_interfaces_clean(void); -extern int rip_passive_nondefault_set(const char *ifname); -extern int rip_passive_nondefault_unset(const char *ifname); -extern void rip_passive_nondefault_clean(void); +extern void rip_clean(struct rip *rip); +extern void rip_clean_network(struct rip *rip); +extern void rip_interfaces_clean(struct rip *rip); +extern int rip_passive_nondefault_set(struct rip *rip, const char *ifname); +extern int rip_passive_nondefault_unset(struct rip *rip, const char *ifname); +extern void rip_passive_nondefault_clean(struct rip *rip); extern void rip_if_init(void); extern void rip_route_map_init(void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_stop(void); -extern int if_check_address(struct in_addr addr); -extern int rip_create(int socket); +extern int if_check_address(struct rip *rip, struct in_addr addr); +extern struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id); +extern struct rip *rip_create(struct vrf *vrf, int socket); extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t, struct connected *); -extern int rip_neighbor_lookup(struct sockaddr_in *); -extern int rip_neighbor_add(struct prefix_ipv4 *p); -extern int rip_neighbor_delete(struct prefix_ipv4 *p); +extern int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from); +extern int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p); +extern int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p); -extern int rip_enable_network_add(struct prefix *p); -extern int rip_enable_network_delete(struct prefix *p); -extern int rip_enable_if_add(const char *ifname); -extern int rip_enable_if_delete(const char *ifname); +extern int rip_enable_network_add(struct rip *rip, struct prefix *p); +extern int rip_enable_network_delete(struct rip *rip, struct prefix *p); +extern int rip_enable_if_add(struct rip *rip, const char *ifname); +extern int rip_enable_if_delete(struct rip *rip, const char *ifname); -extern void rip_event(enum rip_event, int); -extern void rip_ecmp_disable(void); +extern void rip_event(struct rip *rip, enum rip_event event, int sock); +extern void rip_ecmp_disable(struct rip *rip); extern int rip_create_socket(void); -extern int rip_redistribute_check(int); -extern void rip_redistribute_conf_update(int type); -extern void rip_redistribute_conf_delete(int type); -extern void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, - struct nexthop *nh, unsigned int metric, - unsigned char distance, route_tag_t tag); -extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t); -extern void rip_redistribute_withdraw(int); -extern void rip_zebra_ipv4_add(struct route_node *); -extern void rip_zebra_ipv4_delete(struct route_node *); +extern int rip_redistribute_check(struct rip *rip, int type); +extern void rip_redistribute_conf_update(struct rip *rip, int type); +extern void rip_redistribute_conf_delete(struct rip *rip, int type); +extern void rip_redistribute_add(struct rip *rip, int type, int sub_type, + struct prefix_ipv4 *p, struct nexthop *nh, + unsigned int metric, unsigned char distance, + route_tag_t tag); +extern void rip_redistribute_delete(struct rip *rip, int type, int sub_type, + struct prefix_ipv4 *p, ifindex_t ifindex); +extern void rip_redistribute_withdraw(struct rip *rip, int type); +extern void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp); +extern void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp); extern void rip_interface_multicast_set(int, struct connected *); extern void rip_distribute_update_interface(struct interface *); extern void rip_if_rmap_update_interface(struct interface *); -extern int rip_show_network_config(struct vty *); -extern void rip_show_redistribute_config(struct vty *); +extern 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 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 void rip_peer_update(struct rip *rip, struct sockaddr_in *from, + uint8_t version); +extern void rip_peer_bad_route(struct rip *rip, struct sockaddr_in *from); +extern void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from); +extern void rip_peer_display(struct vty *vty, struct rip *rip); +extern struct rip_peer *rip_peer_lookup(struct rip *rip, struct in_addr *addr); +extern struct rip_peer *rip_peer_lookup_next(struct rip *rip, + struct in_addr *addr); extern int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2); extern void rip_peer_list_del(void *arg); extern void rip_info_free(struct rip_info *); +extern struct rip *rip_info_get_instance(const struct rip_info *rinfo); extern struct rip_distance *rip_distance_new(void); extern void rip_distance_free(struct rip_distance *rdistance); -extern uint8_t rip_distance_apply(struct rip_info *); -extern void rip_redistribute_clean(void); +extern uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo); +extern void rip_redistribute_clean(struct rip *rip); extern int rip_route_rte(struct rip_info *rinfo); -extern struct rip_info *rip_ecmp_add(struct rip_info *); -extern struct rip_info *rip_ecmp_replace(struct rip_info *); -extern struct rip_info *rip_ecmp_delete(struct rip_info *); +extern struct rip_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(const char *ifname); +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 *, @@ -476,9 +499,6 @@ extern int offset_list_cmp(struct rip_offset_list *o1, extern void ripd_notif_send_auth_type_failure(const char *ifname); extern void ripd_notif_send_auth_failure(const char *ifname); -/* There is only one rip strucutre. */ -extern struct rip *rip; - extern struct zebra_privs_t ripd_privs; /* Master thread strucutre. */ From a9caf6e9399536bfe0383e9ab0a7b6f83972a2e5 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 14/36] ripngd: simplify cleaning up of routing instance * Call ripng_clean() only when RIPng is configured, this way we can remove one indentation level from this function. * ripng_redistribute_clean() is only called on shutdown, so there's no need to call ripng_redistribute_withdraw() there since the RIPng table is already cleaned up elsewhere. * Deallocate the ripng structure only at the end of the function. This prepares the ground for the next commits where all global variables will be moved to the ripng structure. Signed-off-by: Renato Westphal --- ripngd/ripng_main.c | 3 +- ripngd/ripng_zebra.c | 3 -- ripngd/ripngd.c | 104 ++++++++++++++++++++----------------------- 3 files changed, 50 insertions(+), 60 deletions(-) diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index 10e19efe77..b7e5739ed2 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -82,7 +82,8 @@ static void sigint(void) { zlog_notice("Terminating on signal"); - ripng_clean(); + if (ripng) + ripng_clean(); ripng_zebra_stop(); frr_fini(); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index e3f42edf51..7b74561973 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -173,9 +173,6 @@ void ripng_redistribute_clean() VRF_DEFAULT); vrf_bitmap_unset(zclient->redist[AFI_IP6][i], VRF_DEFAULT); - - /* Remove the routes from RIP table. */ - ripng_redistribute_withdraw(i); } } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 03383bc26d..13e3606946 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1026,9 +1026,6 @@ void ripng_redistribute_withdraw(int type) struct ripng_info *rinfo = NULL; struct list *list = NULL; - if (!ripng) - return; - for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) if ((list = rp->info) != NULL) { rinfo = listgetdata(listhead(list)); @@ -2403,77 +2400,72 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused) /* delete all the added ripng routes. */ void ripng_clean() { - 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); + /* Clear RIPng routes */ + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { + struct ripng_aggregate *aggregate; + struct list *list; - 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); + if ((list = rp->info) != NULL) { + struct ripng_info *rinfo; + struct listnode *listnode; + + 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); } - /* 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; + if ((aggregate = rp->aggregate) != NULL) { + ripng_aggregate_free(aggregate); + rp->aggregate = NULL; + agg_unlock_node(rp); } + } - /* Close the RIPng socket */ - if (ripng->sock >= 0) { - close(ripng->sock); - ripng->sock = -1; - } + /* Cancel the RIPng timers */ + RIPNG_TIMER_OFF(ripng->t_update); + RIPNG_TIMER_OFF(ripng->t_triggered_update); + RIPNG_TIMER_OFF(ripng->t_triggered_interval); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (ripng->route_map[i].name) - free(ripng->route_map[i].name); + /* Cancel the read thread */ + if (ripng->t_read) { + thread_cancel(ripng->t_read); + ripng->t_read = NULL; + } - agg_table_finish(ripng->table); + /* Close the RIPng socket */ + if (ripng->sock >= 0) { + close(ripng->sock); + ripng->sock = -1; + } - stream_free(ripng->ibuf); - stream_free(ripng->obuf); + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (ripng->route_map[i].name) + free(ripng->route_map[i].name); - distribute_list_delete(&ripng->distribute_ctx); - XFREE(MTYPE_RIPNG, ripng); - ripng = NULL; - } /* if (ripng) */ + agg_table_finish(ripng->table); + distribute_list_delete(&ripng->distribute_ctx); + + stream_free(ripng->ibuf); + stream_free(ripng->obuf); ripng_clean_network(); ripng_passive_interface_clean(); ripng_offset_clean(); ripng_interface_clean(); ripng_redistribute_clean(); + + XFREE(MTYPE_RIPNG, ripng); } static void ripng_if_rmap_update(struct if_rmap *if_rmap) From b0ba762f66fa18acffc6f3ef3b947e6363a8d017 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 15/36] ripngd: move "ripng_enable_if" to the ripng structure Signed-off-by: Renato Westphal --- ripngd/ripng_interface.c | 33 ++++++++++++++------------------- ripngd/ripngd.c | 4 +++- ripngd/ripngd.h | 4 ++++ 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 4d14fbab64..fff727ffd2 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -446,9 +446,6 @@ int ripng_interface_address_delete(int command, struct zclient *zclient, return 0; } -/* RIPng enable interface vector. */ -vector ripng_enable_if; - /* RIPng enable network table. */ struct agg_table *ripng_enable_network; @@ -558,14 +555,16 @@ static int ripng_enable_if_lookup(const char *ifname) unsigned int i; char *str; - for (i = 0; i < vector_active(ripng_enable_if); i++) - if ((str = vector_slot(ripng_enable_if, i)) != NULL) + if (!ripng) + return -1; + + for (i = 0; i < vector_active(ripng->enable_if); i++) + if ((str = vector_slot(ripng->enable_if, i)) != NULL) if (strcmp(str, ifname) == 0) return i; return -1; } -/* Add interface to ripng_enable_if. */ int ripng_enable_if_add(const char *ifname) { int ret; @@ -574,14 +573,13 @@ int ripng_enable_if_add(const char *ifname) if (ret >= 0) return NB_ERR_INCONSISTENCY; - vector_set(ripng_enable_if, strdup(ifname)); + vector_set(ripng->enable_if, strdup(ifname)); ripng_enable_apply_all(); return NB_OK; } -/* Delete interface from ripng_enable_if. */ int ripng_enable_if_delete(const char *ifname) { int index; @@ -591,9 +589,9 @@ int ripng_enable_if_delete(const char *ifname) if (index < 0) return NB_ERR_INCONSISTENCY; - str = vector_slot(ripng_enable_if, index); + str = vector_slot(ripng->enable_if, index); free(str); - vector_unset(ripng_enable_if, index); + vector_unset(ripng->enable_if, index); ripng_enable_apply_all(); @@ -753,11 +751,11 @@ void ripng_clean_network() agg_unlock_node(rn); } - /* ripng_enable_if */ - for (i = 0; i < vector_active(ripng_enable_if); i++) - if ((str = vector_slot(ripng_enable_if, i)) != NULL) { + /* ripng->enable_if */ + for (i = 0; i < vector_active(ripng->enable_if); i++) + if ((str = vector_slot(ripng->enable_if, i)) != NULL) { free(str); - vector_slot(ripng_enable_if, i) = NULL; + vector_slot(ripng->enable_if, i) = NULL; } } @@ -864,8 +862,8 @@ int ripng_network_write(struct vty *vty) } /* Write enable interface. */ - for (i = 0; i < vector_active(ripng_enable_if); i++) - if ((ifname = vector_slot(ripng_enable_if, i)) != NULL) + for (i = 0; i < vector_active(ripng->enable_if); i++) + if ((ifname = vector_slot(ripng->enable_if, i)) != NULL) vty_out(vty, " %s\n", ifname); return 0; @@ -939,9 +937,6 @@ void ripng_if_init() /* RIPng enable network init. */ ripng_enable_network = agg_table_init(); - /* RIPng enable interface init. */ - ripng_enable_if = vector_init(1); - /* RIPng passive interface. */ Vripng_passive_interface = vector_init(1); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 13e3606946..d54217d121 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1803,8 +1803,9 @@ int ripng_create(int socket) ripng->ibuf = stream_new(RIPNG_MAX_PACKET_SIZE * 5); ripng->obuf = stream_new(RIPNG_MAX_PACKET_SIZE); - /* Initialize RIPng routig table. */ + /* Initialize RIPng data structures. */ ripng->table = agg_table_init(); + ripng->enable_if = vector_init(1); /* Distribute list install. */ ripng->distribute_ctx = distribute_list_ctx_create( @@ -2461,6 +2462,7 @@ void ripng_clean() ripng_clean_network(); ripng_passive_interface_clean(); + vector_free(ripng->enable_if); ripng_offset_clean(); ripng_interface_clean(); ripng_redistribute_clean(); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 1db7a83b11..af2f65eb46 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "ripng_memory.h" @@ -107,6 +108,9 @@ struct ripng { /* RIPng routing information base. */ struct agg_table *table; + /* RIPng enabled interfaces. */ + vector enable_if; + /* RIPng threads. */ struct thread *t_read; struct thread *t_write; From 29b94d588409af3e00b99bee2a3f7a89caf3d57b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 16/36] ripngd: move "ripng_enable_network" to the ripng structure Signed-off-by: Renato Westphal --- ripngd/ripng_interface.c | 32 ++++++++++++++++---------------- ripngd/ripngd.c | 2 ++ ripngd/ripngd.h | 3 +++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index fff727ffd2..dbf9a2c333 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -446,18 +446,18 @@ int ripng_interface_address_delete(int command, struct zclient *zclient, return 0; } -/* RIPng enable network table. */ -struct agg_table *ripng_enable_network; - /* Lookup RIPng enable network. */ /* Check wether the interface has at least a connected prefix that - * is within the ripng_enable_network table. */ + * is within the ripng->enable_network table. */ static int ripng_enable_network_lookup_if(struct interface *ifp) { struct listnode *node; struct connected *connected; struct prefix_ipv6 address; + if (!ripng) + return -1; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { struct prefix *p; struct agg_node *n; @@ -469,7 +469,7 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) address.prefix = p->u.prefix6; address.prefixlen = IPV6_MAX_BITLEN; - n = agg_node_match(ripng_enable_network, + n = agg_node_match(ripng->enable_network, (struct prefix *)&address); if (n) { agg_unlock_node(n); @@ -480,12 +480,15 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) return -1; } -/* Check wether connected is within the ripng_enable_network table. */ +/* Check wether connected is within the ripng->enable_network table. */ static int ripng_enable_network_lookup2(struct connected *connected) { struct prefix_ipv6 address; struct prefix *p; + if (!ripng) + return -1; + p = connected->address; if (p->family == AF_INET6) { @@ -496,8 +499,8 @@ static int ripng_enable_network_lookup2(struct connected *connected) address.prefixlen = IPV6_MAX_BITLEN; /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within - * ripng_enable_network */ - node = agg_node_match(ripng_enable_network, + * ripng->enable_network */ + node = agg_node_match(ripng->enable_network, (struct prefix *)&address); if (node) { @@ -514,7 +517,7 @@ int ripng_enable_network_add(struct prefix *p) { struct agg_node *node; - node = agg_node_get(ripng_enable_network, p); + node = agg_node_get(ripng->enable_network, p); if (node->info) { agg_unlock_node(node); @@ -533,7 +536,7 @@ int ripng_enable_network_delete(struct prefix *p) { struct agg_node *node; - node = agg_node_lookup(ripng_enable_network, p); + node = agg_node_lookup(ripng->enable_network, p); if (node) { node->info = NULL; @@ -743,8 +746,8 @@ void ripng_clean_network() char *str; struct agg_node *rn; - /* ripng_enable_network */ - for (rn = agg_route_top(ripng_enable_network); rn; + /* ripng->enable_network */ + for (rn = agg_route_top(ripng->enable_network); rn; rn = agg_route_next(rn)) if (rn->info) { rn->info = NULL; @@ -852,7 +855,7 @@ int ripng_network_write(struct vty *vty) char buf[BUFSIZ]; /* Write enable network. */ - for (node = agg_route_top(ripng_enable_network); node; + for (node = agg_route_top(ripng->enable_network); node; node = agg_route_next(node)) if (node->info) { struct prefix *p = &node->p; @@ -934,9 +937,6 @@ void ripng_if_init() hook_register_prio(if_add, 0, ripng_if_new_hook); hook_register_prio(if_del, 0, ripng_if_delete_hook); - /* RIPng enable network init. */ - ripng_enable_network = agg_table_init(); - /* RIPng passive interface. */ Vripng_passive_interface = vector_init(1); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index d54217d121..9158cdcd3f 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1806,6 +1806,7 @@ int ripng_create(int socket) /* Initialize RIPng data structures. */ ripng->table = agg_table_init(); ripng->enable_if = vector_init(1); + ripng->enable_network = agg_table_init(); /* Distribute list install. */ ripng->distribute_ctx = distribute_list_ctx_create( @@ -2463,6 +2464,7 @@ void ripng_clean() ripng_clean_network(); ripng_passive_interface_clean(); vector_free(ripng->enable_if); + agg_table_finish(ripng->enable_network); ripng_offset_clean(); ripng_interface_clean(); ripng_redistribute_clean(); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index af2f65eb46..935a9e8591 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -111,6 +111,9 @@ struct ripng { /* RIPng enabled interfaces. */ vector enable_if; + /* RIPng enabled networks. */ + struct agg_table *enable_network; + /* RIPng threads. */ struct thread *t_read; struct thread *t_write; From 0c32404fddcf80034f4fd3d76c7cc12fd71b4e25 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 17/36] ripngd: move "Vripng_passive_interface" to the ripng structure Signed-off-by: Renato Westphal --- ripngd/ripng_interface.c | 25 +++++++++++-------------- ripngd/ripngd.c | 2 ++ ripngd/ripngd.h | 3 +++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index dbf9a2c333..b0a07ab462 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -762,17 +762,17 @@ void ripng_clean_network() } } -/* Vector to store passive-interface name. */ -vector Vripng_passive_interface; - /* Utility function for looking up passive interface settings. */ static int ripng_passive_interface_lookup(const char *ifname) { unsigned int i; char *str; - for (i = 0; i < vector_active(Vripng_passive_interface); i++) - if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) + 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) return i; return -1; @@ -807,7 +807,7 @@ int ripng_passive_interface_set(const char *ifname) if (ripng_passive_interface_lookup(ifname) >= 0) return NB_ERR_INCONSISTENCY; - vector_set(Vripng_passive_interface, strdup(ifname)); + vector_set(ripng->passive_interface, strdup(ifname)); ripng_passive_interface_apply_all(); @@ -823,9 +823,9 @@ int ripng_passive_interface_unset(const char *ifname) if (i < 0) return NB_ERR_INCONSISTENCY; - str = vector_slot(Vripng_passive_interface, i); + str = vector_slot(ripng->passive_interface, i); free(str); - vector_unset(Vripng_passive_interface, i); + vector_unset(ripng->passive_interface, i); ripng_passive_interface_apply_all(); @@ -838,10 +838,10 @@ void ripng_passive_interface_clean(void) unsigned int i; char *str; - for (i = 0; i < vector_active(Vripng_passive_interface); i++) - if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) { + for (i = 0; i < vector_active(ripng->passive_interface); i++) + if ((str = vector_slot(ripng->passive_interface, i)) != NULL) { free(str); - vector_slot(Vripng_passive_interface, i) = NULL; + vector_slot(ripng->passive_interface, i) = NULL; } ripng_passive_interface_apply_all(); } @@ -937,9 +937,6 @@ void ripng_if_init() hook_register_prio(if_add, 0, ripng_if_new_hook); hook_register_prio(if_del, 0, ripng_if_delete_hook); - /* RIPng passive interface. */ - Vripng_passive_interface = vector_init(1); - /* Install interface node. */ install_node(&interface_node, interface_config_write); if_cmd_init(); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 9158cdcd3f..7db8bafd38 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1807,6 +1807,7 @@ int ripng_create(int socket) ripng->table = agg_table_init(); ripng->enable_if = vector_init(1); ripng->enable_network = agg_table_init(); + ripng->passive_interface = vector_init(1); /* Distribute list install. */ ripng->distribute_ctx = distribute_list_ctx_create( @@ -2465,6 +2466,7 @@ void ripng_clean() ripng_passive_interface_clean(); vector_free(ripng->enable_if); agg_table_finish(ripng->enable_network); + vector_free(ripng->passive_interface); ripng_offset_clean(); ripng_interface_clean(); ripng_redistribute_clean(); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 935a9e8591..95b128f4d9 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -114,6 +114,9 @@ struct ripng { /* RIPng enabled networks. */ struct agg_table *enable_network; + /* Vector to store passive-interface name. */ + vector passive_interface; + /* RIPng threads. */ struct thread *t_read; struct thread *t_write; From ecece94cf1be254d89868cec95cc9d4b04264a6b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 18/36] ripngd: move "peer_list" to the ripng structure Signed-off-by: Renato Westphal --- ripngd/ripng_main.c | 1 - ripngd/ripng_northbound.c | 10 ++++++++-- ripngd/ripng_peer.c | 22 ++++++---------------- ripngd/ripngd.c | 2 ++ ripngd/ripngd.h | 6 ++++-- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index b7e5739ed2..26d602e1a5 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -177,7 +177,6 @@ int main(int argc, char **argv) ripng_init(); ripng_cli_init(); zebra_init(master); - ripng_peer_init(); frr_config_fork(); frr_run(master); diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index 69e207f443..ca7a334f4a 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -581,8 +581,11 @@ ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry, { struct listnode *node; + if (!ripng) + return NULL; + if (list_entry == NULL) - node = listhead(peer_list); + node = listhead(ripng->peer_list); else node = listnextnode((struct listnode *)list_entry); @@ -612,7 +615,10 @@ ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, yang_str2ipv6(keys->key[0], &address); - for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) { + if (!ripng) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) { if (IPV6_ADDR_SAME(&peer->addr, &address)) return node; } diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index 6b2a183539..f5590cf823 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -34,10 +34,6 @@ #include "ripngd/ripngd.h" #include "ripngd/ripng_nexthop.h" - -/* Linked list of RIPng peer. */ -struct list *peer_list; - static struct ripng_peer *ripng_peer_new(void) { return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer)); @@ -53,7 +49,7 @@ struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr) struct ripng_peer *peer; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) { if (IPV6_ADDR_SAME(&peer->addr, addr)) return peer; } @@ -65,7 +61,7 @@ struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *addr) struct ripng_peer *peer; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) { if (addr6_cmp(&peer->addr, addr) > 0) return peer; } @@ -80,7 +76,7 @@ static int ripng_peer_timeout(struct thread *t) struct ripng_peer *peer; peer = THREAD_ARG(t); - listnode_delete(peer_list, peer); + listnode_delete(ripng->peer_list, peer); ripng_peer_free(peer); return 0; @@ -99,7 +95,7 @@ static struct ripng_peer *ripng_peer_get(struct in6_addr *addr) } else { peer = ripng_peer_new(); peer->addr = *addr; /* XXX */ - listnode_add_sort(peer_list, peer); + listnode_add_sort(ripng->peer_list, peer); } /* Update timeout thread. */ @@ -170,7 +166,7 @@ void ripng_peer_display(struct vty *vty) #define RIPNG_UPTIME_LEN 25 char timebuf[RIPNG_UPTIME_LEN]; - for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) { vty_out(vty, " %s \n%14s %10d %10d %10d %s\n", inet6_ntoa(peer->addr), " ", peer->recv_badpackets, peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT, @@ -178,13 +174,7 @@ void ripng_peer_display(struct vty *vty) } } -static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) +int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) { return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr)); } - -void ripng_peer_init() -{ - peer_list = list_new(); - peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp; -} diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 7db8bafd38..2cc3bd7f1e 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1805,6 +1805,8 @@ int ripng_create(int socket) /* Initialize RIPng data structures. */ ripng->table = agg_table_init(); + ripng->peer_list = list_new(); + ripng->peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp; ripng->enable_if = vector_init(1); ripng->enable_network = agg_table_init(); ripng->passive_interface = vector_init(1); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 95b128f4d9..3e5ca18ed2 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -108,6 +108,9 @@ struct ripng { /* RIPng routing information base. */ struct agg_table *table; + /* Linked list of RIPng peers. */ + struct list *peer_list; + /* RIPng enabled interfaces. */ vector enable_if; @@ -343,7 +346,6 @@ struct ripng_offset_list { /* Extern variables. */ extern struct ripng *ripng; -extern struct list *peer_list; extern struct zebra_privs_t ripngd_privs; extern struct thread_master *master; @@ -368,13 +370,13 @@ 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_init(void); 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 int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2); extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname); extern void ripng_offset_list_del(struct ripng_offset_list *offset); From 56bf1cb2c3236429ff77e5dd19b04a8d1ff5d158 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 19/36] ripdng: clear list of peers when RIPng is deconfigured This is an old standing bug where the list of RIPng peers wasn't cleared after deconfiguring RIPng, which caused the existing peers to still be present on a newly configured RIPng instance (except when the timed out after ~3 minutes). Fix this. Signed-off-by: Renato Westphal --- ripngd/ripng_peer.c | 6 ++++++ ripngd/ripngd.c | 2 ++ ripngd/ripngd.h | 1 + 3 files changed, 9 insertions(+) diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index f5590cf823..36c701b86b 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -41,6 +41,7 @@ static struct ripng_peer *ripng_peer_new(void) static void ripng_peer_free(struct ripng_peer *peer) { + RIPNG_TIMER_OFF(peer->t_timeout); XFREE(MTYPE_RIPNG_PEER, peer); } @@ -178,3 +179,8 @@ int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) { return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr)); } + +void ripng_peer_list_del(void *arg) +{ + ripng_peer_free(arg); +} diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 2cc3bd7f1e..9456980e87 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1807,6 +1807,7 @@ int ripng_create(int socket) ripng->table = agg_table_init(); ripng->peer_list = list_new(); ripng->peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp; + ripng->peer_list->del = ripng_peer_list_del; ripng->enable_if = vector_init(1); ripng->enable_network = agg_table_init(); ripng->passive_interface = vector_init(1); @@ -2459,6 +2460,7 @@ void ripng_clean() free(ripng->route_map[i].name); agg_table_finish(ripng->table); + list_delete(&ripng->peer_list); distribute_list_delete(&ripng->distribute_ctx); stream_free(ripng->ibuf); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 3e5ca18ed2..26b6c0bb12 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -377,6 +377,7 @@ 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 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 void ripng_offset_list_del(struct ripng_offset_list *offset); From 26c6be9314b4013cedaf0a9f5ff5d65ca4ae685b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 20/36] ripngd: move "ripng_offset_list_master" to the ripng structure Signed-off-by: Renato Westphal --- ripngd/ripng_offset.c | 30 +++++------------------------- ripngd/ripngd.c | 8 ++++++-- ripngd/ripngd.h | 7 +++++-- 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c index 278df75892..25233f80ab 100644 --- a/ripngd/ripng_offset.c +++ b/ripngd/ripng_offset.c @@ -33,8 +33,6 @@ #include "ripngd/ripngd.h" -static struct list *ripng_offset_list_master; - #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name) #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric) @@ -48,14 +46,14 @@ struct ripng_offset_list *ripng_offset_list_new(const char *ifname) new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST, sizeof(struct ripng_offset_list)); new->ifname = strdup(ifname); - listnode_add_sort(ripng_offset_list_master, new); + listnode_add_sort(ripng->offset_list_master, new); return new; } void ripng_offset_list_del(struct ripng_offset_list *offset) { - listnode_delete(ripng_offset_list_master, offset); + listnode_delete(ripng->offset_list_master, offset); if (OFFSET_LIST_IN_NAME(offset)) free(OFFSET_LIST_IN_NAME(offset)); if (OFFSET_LIST_OUT_NAME(offset)) @@ -69,7 +67,8 @@ struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname) struct ripng_offset_list *offset; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) { + for (ALL_LIST_ELEMENTS(ripng->offset_list_master, node, nnode, + offset)) { if (strcmp(offset->ifname, ifname) == 0) return offset; } @@ -153,26 +152,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, return 0; } -static int offset_list_cmp(struct ripng_offset_list *o1, - struct ripng_offset_list *o2) +int offset_list_cmp(struct ripng_offset_list *o1, struct ripng_offset_list *o2) { return strcmp(o1->ifname, o2->ifname); } - -void ripng_offset_init(void) -{ - ripng_offset_list_master = list_new(); - ripng_offset_list_master->cmp = - (int (*)(void *, void *))offset_list_cmp; - ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del; -} - -void ripng_offset_clean(void) -{ - list_delete(&ripng_offset_list_master); - - ripng_offset_list_master = list_new(); - ripng_offset_list_master->cmp = - (int (*)(void *, void *))offset_list_cmp; - ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del; -} diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 9456980e87..fab04a3a12 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1811,6 +1811,11 @@ int ripng_create(int socket) ripng->enable_if = vector_init(1); ripng->enable_network = agg_table_init(); ripng->passive_interface = vector_init(1); + ripng->offset_list_master = list_new(); + ripng->offset_list_master->cmp = + (int (*)(void *, void *))offset_list_cmp; + ripng->offset_list_master->del = + (void (*)(void *))ripng_offset_list_del; /* Distribute list install. */ ripng->distribute_ctx = distribute_list_ctx_create( @@ -2471,7 +2476,7 @@ void ripng_clean() vector_free(ripng->enable_if); agg_table_finish(ripng->enable_network); vector_free(ripng->passive_interface); - ripng_offset_clean(); + list_delete(&ripng->offset_list_master); ripng_interface_clean(); ripng_redistribute_clean(); @@ -2583,7 +2588,6 @@ void ripng_init() /* Route-map for interface. */ ripng_route_map_init(); - ripng_offset_init(); route_map_add_hook(ripng_routemap_update); route_map_delete_hook(ripng_routemap_update); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 26b6c0bb12..164fb3782e 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -120,6 +120,9 @@ struct ripng { /* Vector to store passive-interface name. */ vector passive_interface; + /* RIPng offset-lists. */ + struct list *offset_list_master; + /* RIPng threads. */ struct thread *t_read; struct thread *t_write; @@ -387,8 +390,8 @@ 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 void ripng_offset_init(void); -extern void ripng_offset_clean(void); +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); From 5c84b9a58153f89379e3a99e02173662ea390489 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 21/36] 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 --- ripngd/ripng_interface.c | 136 ++++++++++-------- ripngd/ripng_main.c | 11 +- ripngd/ripng_nexthop.c | 3 +- ripngd/ripng_northbound.c | 122 +++++++++++++--- ripngd/ripng_offset.c | 25 ++-- ripngd/ripng_peer.c | 30 ++-- ripngd/ripng_route.c | 4 +- ripngd/ripng_route.h | 4 +- ripngd/ripng_zebra.c | 56 ++++---- ripngd/ripngd.c | 289 +++++++++++++++++++++++--------------- ripngd/ripngd.h | 113 +++++++++------ 11 files changed, 504 insertions(+), 289 deletions(-) diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index b0a07ab462..af2b1c260a 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 26d602e1a5..e7246efc43 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 74a132aa94..882c2fbc8c 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 ca7a334f4a..a6700c8454 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 25233f80ab..41ba2360ba 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 36c701b86b..5376007747 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 f66a0b9527..1bf1007fec 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 e402f4a66c..afc1d1cbc5 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 7b74561973..9e8dd03cbc 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 fab04a3a12..292b3da6ab 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); } -/* Create new RIPng instance and set it to global variable. */ -int ripng_create(int socket) +struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id) { - /* ripng should be NULL. */ - assert(ripng == NULL); + 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. */ +struct ripng *ripng_create(struct vrf *vrf, int socket) +{ + 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) { + struct ripng *ripng; + nb_cli_show_dnode_cmds(vty, dnode, false); - config_write_distribute(vty, - ripng->distribute_ctx); - - 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 164fb3782e..95039bf579 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_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 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_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_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(void); +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 int ripng_network_write(struct vty *vty, struct ripng *ripng); -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 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); From 02fe07c7b8f2191d1f53b31888e95d6c12c48ad9 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 22/36] lib: constify a few parameters in the VRF code Parameters should be const whenever possible to improve code readability and remove the need to cast away the constness of const arguments. Signed-off-by: Renato Westphal --- lib/vrf.c | 6 +++--- lib/vrf.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/vrf.c b/lib/vrf.c index 0c82f6a3cd..e1f27b7e72 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -572,7 +572,7 @@ static int vrf_default_accepts_vrf(int type) /* Create a socket for the VRF. */ int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, - char *interfacename) + const char *interfacename) { int ret, save_errno, ret2; @@ -947,7 +947,7 @@ vrf_id_t vrf_get_default_id(void) return VRF_DEFAULT_INTERNAL; } -int vrf_bind(vrf_id_t vrf_id, int fd, char *name) +int vrf_bind(vrf_id_t vrf_id, int fd, const char *name) { int ret = 0; @@ -1006,7 +1006,7 @@ int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params) } int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id, - char *interfacename) + const char *interfacename) { int ret, save_errno, ret2; diff --git a/lib/vrf.h b/lib/vrf.h index fe4fc77250..eacbaf542b 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -215,12 +215,12 @@ extern void vrf_terminate(void); /* Create a socket serving for the given VRF */ extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, - char *name); + const char *name); extern int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id, - char *name); + const char *name); -extern int vrf_bind(vrf_id_t vrf_id, int fd, char *name); +extern int vrf_bind(vrf_id_t vrf_id, int fd, const char *name); /* VRF ioctl operations */ extern int vrf_getaddrinfo(const char *node, const char *service, From fcb7bffdda0b122c34978e3f7390b6f26689848a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 23/36] lib: introduce new YANG helper function One use case for the new yang_data_list_find() function is to find input parameters in RPC northbound callbacks easily, without the need to iterate over the input parameters manually. Signed-off-by: Renato Westphal --- lib/yang.c | 19 +++++++++++++++++++ lib/yang.h | 15 +++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/yang.c b/lib/yang.c index 71b41c35d8..4077b29746 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -608,6 +608,25 @@ struct list *yang_data_list_new(void) return list; } +struct yang_data *yang_data_list_find(const struct list *list, + const char *xpath_fmt, ...) +{ + char xpath[XPATH_MAXLEN]; + struct yang_data *data; + struct listnode *node; + va_list ap; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + for (ALL_LIST_ELEMENTS_RO(list, node, data)) + if (strmatch(data->xpath, xpath)) + return data; + + return NULL; +} + static void *ly_dup_cb(const void *priv) { /* Make a shallow copy of the priv pointer. */ diff --git a/lib/yang.h b/lib/yang.h index 3259189e98..09d92cafdd 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -509,6 +509,21 @@ extern void yang_data_free(struct yang_data *data); */ 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, ...); + /* * Initialize the YANG subsystem. Should be called only once during the * daemon initialization process. From 37345802af89567a5238d8894c0ef4e273c9d0c0 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 24/36] lib: peform only partial YANG validation when displaying operational data When lyd_validate() is used with the LYD_OPT_DATA option, full YANG validation is performed. As a side-effect to this, default nodes are created, which is not desirable when displaying operational data since configuration nodes can also be created. Use LYD_OPT_GET option to resolve this problem. Signed-off-by: Renato Westphal --- lib/northbound_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 33035de31b..917b048105 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -1297,7 +1297,7 @@ DEFPY (show_yang_operational_data, yang_dnode_free(dnode); return CMD_WARNING; } - lyd_validate(&dnode, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, ly_ctx); + lyd_validate(&dnode, LYD_OPT_GET, ly_ctx); /* Display the data. */ if (lyd_print_mem(&strp, dnode, format, From e35356af91b72da7f4e7fe03c43babb51e369bc0 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 25/36] ripd: switch from sendto() to sendmsg() For unknown reasons, the IP_MULTICAST_IF sockoption doesn't seem to work when the given socket is bound to a VRF device on Linux. Switch from sendto() to sendmsg() so that we can specify the outgoing interface of multicast packets using IP_PKTINFO ancillary data. This also makes ripd more consistent with ripngd, which also uses sendmsg() to send packets on the wire. Signed-off-by: Renato Westphal --- ripd/ripd.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/ripd/ripd.c b/ripd/ripd.c index 6b9c5fe886..916fba2269 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1386,6 +1386,13 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, struct rip *rip; int ret; struct sockaddr_in sin; + struct msghdr msg; + struct iovec iov; +#ifdef GNU_LINUX + struct cmsghdr *cmsgptr; + char adata[256] = {}; + struct in_pktinfo *pkt; +#endif /* GNU_LINUX */ assert(ifc != NULL); ri = ifc->ifp->info; @@ -1448,8 +1455,27 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, rip_interface_multicast_set(rip->sock, ifc); } - ret = sendto(rip->sock, buf, size, 0, (struct sockaddr *)&sin, - sizeof(struct sockaddr_in)); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (void *)&sin; + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + iov.iov_base = buf; + iov.iov_len = size; + +#ifdef GNU_LINUX + msg.msg_control = (void *)adata; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + + cmsgptr = (struct cmsghdr *)adata; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + pkt = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + pkt->ipi_ifindex = ifc->ifp->ifindex; +#endif /* GNU_LINUX */ + + ret = sendmsg(rip->sock, &msg, 0); if (IS_RIP_DEBUG_EVENT) zlog_debug("SEND to %s.%d", inet_ntoa(sin.sin_addr), From 9852be711c80430004ed9ee0bd718476837896e8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 26/36] ripd: failure to create a socket shouldn't be a fatal error The ripd code can handle this error just fine (e.g. reject the configuration transaction), there's no need to exit when a socket fails to be created. Signed-off-by: Renato Westphal --- ripd/ripd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ripd/ripd.c b/ripd/ripd.c index 916fba2269..c6abfb557d 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1347,7 +1347,7 @@ int rip_create_socket(void) if (sock < 0) { flog_err_sys(EC_LIB_SOCKET, "Cannot create UDP socket: %s", safe_strerror(errno)); - exit(1); + return -1; } sockopt_broadcast(sock); From ae7b826a2338aa1cc61019fa74391da1c3ceb542 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 27/36] ripd: add VRF support * Turn the "instance" YANG presence-container into a YANG list keyed by the new "vrf" leaf. This is a backward incompatible change but this should be ok for now. * RIP VRF instances can be configured even when the corresponding VRF doesn't exist. And a RIP VRF instance isn't deleted when the corresponding VRF is deleted. For this to work, implement the rip_instance_enable() and rip_instance_disable() functions that are called to enable/disable RIP routing instances when necessary. A RIP routing instance can be enabled only when the corresponding VRF is enabled (this information comes from zebra and depends on the underlying VRF backend). Routing instances are stored in the new rip_instances rb-tree (global variable). * Add a vrf pointer to the rip structure instead of storing vrf_id only. This is much more convenient than using vrf_lookup_by_id() every time we need to get the vrf pointer from the VRF ID. The rip->vrf pointer is updated whenever the VRF enable/disable hooks are called. Signed-off-by: Renato Westphal --- ripd/rip_cli.c | 42 ++++- ripd/rip_interface.c | 116 ++++++++---- ripd/rip_interface.h | 5 + ripd/rip_main.c | 17 +- ripd/rip_memory.c | 1 + ripd/rip_memory.h | 1 + ripd/rip_northbound.c | 25 ++- ripd/rip_zebra.c | 45 ++++- ripd/ripd.c | 411 +++++++++++++++++++++++++++++------------ ripd/ripd.h | 25 ++- vtysh/vtysh.c | 4 +- yang/example/ripd.json | 37 ++-- yang/example/ripd.xml | 1 + yang/frr-ripd.yang | 11 +- 14 files changed, 519 insertions(+), 222 deletions(-) diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 5bb81ef157..be24d04ff3 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -39,31 +39,46 @@ */ DEFPY_NOSH (router_rip, router_rip_cmd, - "router rip", + "router rip [vrf NAME]", "Enable a routing process\n" - "Routing Information Protocol (RIP)\n") + "Routing Information Protocol (RIP)\n" + VRF_CMD_HELP_STR) { + char xpath[XPATH_MAXLEN]; int ret; - nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_CREATE, - NULL); + /* Build RIP instance XPath. */ + if (!vrf) + vrf = VRF_DEFAULT_NAME; + snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']", + vrf); + + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); ret = nb_cli_apply_changes(vty, NULL); if (ret == CMD_SUCCESS) - VTY_PUSH_XPATH(RIP_NODE, "/frr-ripd:ripd/instance"); + VTY_PUSH_XPATH(RIP_NODE, xpath); return ret; } DEFPY (no_router_rip, no_router_rip_cmd, - "no router rip", + "no router rip [vrf NAME]", NO_STR "Enable a routing process\n" - "Routing Information Protocol (RIP)\n") + "Routing Information Protocol (RIP)\n" + VRF_CMD_HELP_STR) { - nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_DELETE, - 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); return nb_cli_apply_changes(vty, NULL); } @@ -71,8 +86,15 @@ DEFPY (no_router_rip, void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { + const char *vrf_name; + + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + vty_out(vty, "!\n"); - vty_out(vty, "router rip\n"); + vty_out(vty, "router rip"); + if (!strmatch(vrf_name, VRF_DEFAULT_NAME)) + vty_out(vty, " vrf %s", vrf_name); + vty_out(vty, "\n"); } /* diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index ca6dea1b37..86fb2952dd 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -94,17 +94,12 @@ static int ipv4_multicast_leave(int sock, struct in_addr group, static void rip_interface_reset(struct rip_interface *); /* Allocate new RIP's interface configuration. */ -static struct rip_interface *rip_interface_new(struct interface *ifp) +static struct rip_interface *rip_interface_new(void) { - struct vrf *vrf; struct rip_interface *ri; ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface)); - vrf = vrf_lookup_by_id(ifp->vrf_id); - if (vrf) - ri->rip = vrf->info; - rip_interface_reset(ri); return ri; @@ -327,10 +322,9 @@ static int rip_if_ipv4_address_check(struct interface *ifp) /* Does this address belongs to me ? */ int if_check_address(struct rip *rip, struct in_addr addr) { - struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (rip->vrf, ifp) { struct listnode *cnode; struct connected *connected; @@ -365,13 +359,14 @@ int rip_interface_down(int command, struct zclient *zclient, if (ifp == NULL) return 0; + rip_interface_sync(ifp); rip_if_down(ifp); if (IS_RIP_DEBUG_ZEBRA) zlog_debug( - "interface %s index %d flags %llx metric %d mtu %d is down", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + "interface %s vrf %u index %d flags %llx metric %d mtu %d is down", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); return 0; } @@ -391,9 +386,11 @@ int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length, if (IS_RIP_DEBUG_ZEBRA) zlog_debug( - "interface %s index %d flags %#llx metric %d mtu %d is up", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + "interface %s vrf %u index %d flags %#llx metric %d mtu %d is up", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); + + rip_interface_sync(ifp); /* Check if this interface is RIP enabled or not.*/ rip_enable_apply(ifp); @@ -414,12 +411,13 @@ int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length, struct interface *ifp; ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + rip_interface_sync(ifp); if (IS_RIP_DEBUG_ZEBRA) zlog_debug( - "interface add %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + "interface add %s vrf %u index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); /* Check if this interface is RIP enabled or not.*/ rip_enable_apply(ifp); @@ -452,13 +450,15 @@ int rip_interface_delete(int command, struct zclient *zclient, if (ifp == NULL) return 0; + rip_interface_sync(ifp); if (if_is_up(ifp)) { rip_if_down(ifp); } - zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + zlog_info( + "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); /* To support pseudo interface do not free interface structure. */ /* if_delete(ifp); */ @@ -467,6 +467,28 @@ int rip_interface_delete(int command, struct zclient *zclient, return 0; } +/* VRF update for an interface. */ +int rip_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct interface *ifp; + vrf_id_t new_vrf_id; + + ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, + &new_vrf_id); + if (!ifp) + return 0; + + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("interface %s VRF change vrf_id %u new vrf id %u", + ifp->name, vrf_id, new_vrf_id); + + if_update_to_new_vrf(ifp, new_vrf_id); + rip_interface_sync(ifp); + + return 0; +} + static void rip_interface_clean(struct rip_interface *ri) { ri->enable_network = 0; @@ -481,10 +503,9 @@ static void rip_interface_clean(struct rip_interface *ri) void rip_interfaces_clean(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; - FOR_ALL_INTERFACES (vrf, ifp) + FOR_ALL_INTERFACES (rip->vrf, ifp) rip_interface_clean(ifp->info); } @@ -972,11 +993,10 @@ void rip_enable_apply(struct interface *ifp) /* Apply network configuration to all interface. */ static void rip_enable_apply_all(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; /* Check each interface. */ - FOR_ALL_INTERFACES (vrf, ifp) + FOR_ALL_INTERFACES (rip->vrf, ifp) rip_enable_apply(ifp); } @@ -1090,10 +1110,9 @@ static void rip_passive_interface_apply(struct interface *ifp) static void rip_passive_interface_apply_all(struct rip *rip) { - struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; - FOR_ALL_INTERFACES (vrf, ifp) + FOR_ALL_INTERFACES (rip->vrf, ifp) rip_passive_interface_apply(ifp); } @@ -1154,22 +1173,25 @@ void rip_passive_nondefault_clean(struct rip *rip) /* Write rip configuration of each interface. */ static int rip_interface_config_write(struct vty *vty) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct interface *ifp; + struct vrf *vrf; int write = 0; - FOR_ALL_INTERFACES (vrf, ifp) { - struct lyd_node *dnode; + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + struct interface *ifp; - dnode = yang_dnode_get( - running_config->dnode, - "/frr-interface:lib/interface[name='%s'][vrf='%s']", - ifp->name, vrf->name); - if (dnode == NULL) - continue; + FOR_ALL_INTERFACES (vrf, ifp) { + struct lyd_node *dnode; - write = 1; - nb_cli_show_dnode_cmds(vty, dnode, false); + dnode = yang_dnode_get( + running_config->dnode, + "/frr-interface:lib/interface[name='%s'][vrf='%s']", + ifp->name, vrf->name); + if (dnode == NULL) + continue; + + write = 1; + nb_cli_show_dnode_cmds(vty, dnode, false); + } } return write; @@ -1206,10 +1228,26 @@ static struct cmd_node interface_node = { INTERFACE_NODE, "%s(config-if)# ", 1, }; +void rip_interface_sync(struct interface *ifp) +{ + struct vrf *vrf; + + vrf = vrf_lookup_by_id(ifp->vrf_id); + if (vrf) { + struct rip_interface *ri; + + ri = ifp->info; + if (ri) + ri->rip = vrf->info; + } +} + /* Called when interface structure allocated. */ static int rip_interface_new_hook(struct interface *ifp) { - ifp->info = rip_interface_new(ifp); + ifp->info = rip_interface_new(); + rip_interface_sync(ifp); + return 0; } diff --git a/ripd/rip_interface.h b/ripd/rip_interface.h index 8723388e75..303be0315d 100644 --- a/ripd/rip_interface.h +++ b/ripd/rip_interface.h @@ -20,6 +20,8 @@ #ifndef _QUAGGA_RIP_INTERFACE_H #define _QUAGGA_RIP_INTERFACE_H +#include "zclient.h" + extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t); extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t); extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t); @@ -28,5 +30,8 @@ extern int rip_interface_address_add(int, struct zclient *, zebra_size_t, vrf_id_t); extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id); +extern void rip_interface_sync(struct interface *ifp); #endif /* _QUAGGA_RIP_INTERFACE_H */ diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 46babe2e0b..8b6e3a620a 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -46,7 +46,7 @@ static struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}}; /* ripd privileges */ -zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN}; struct zebra_privs_t ripd_privs = { #if defined(FRR_USER) @@ -59,7 +59,7 @@ struct zebra_privs_t ripd_privs = { .vty_group = VTY_GROUP, #endif .caps_p = _caps_p, - .cap_num_p = 2, + .cap_num_p = array_size(_caps_p), .cap_num_i = 0}; /* Master of threads. */ @@ -79,18 +79,9 @@ static void sighup(void) /* SIGINT handler. */ static void sigint(void) { - struct vrf *vrf; - zlog_notice("Terminating on signal"); - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - struct rip *rip; - - rip = vrf->info; - if (rip) - rip_clean(rip); - } - + rip_vrf_terminate(); rip_zclient_stop(); frr_fini(); @@ -179,7 +170,7 @@ int main(int argc, char **argv) /* Library initialization. */ rip_error_init(); keychain_init(); - vrf_init(NULL, NULL, NULL, NULL, NULL); + rip_vrf_init(); /* RIP related initialization. */ rip_init(); diff --git a/ripd/rip_memory.c b/ripd/rip_memory.c index 1852410743..7d703a86db 100644 --- a/ripd/rip_memory.c +++ b/ripd/rip_memory.c @@ -27,6 +27,7 @@ DEFINE_MGROUP(RIPD, "ripd") DEFINE_MTYPE(RIPD, RIP, "RIP structure") +DEFINE_MTYPE(RIPD, RIP_VRF_NAME, "RIP VRF name") DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info") DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface") DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String") diff --git a/ripd/rip_memory.h b/ripd/rip_memory.h index 29013ecec3..1f9d8f500f 100644 --- a/ripd/rip_memory.h +++ b/ripd/rip_memory.h @@ -26,6 +26,7 @@ DECLARE_MGROUP(RIPD) DECLARE_MTYPE(RIP) +DECLARE_MTYPE(RIP_VRF_NAME) DECLARE_MTYPE(RIP_INFO) DECLARE_MTYPE(RIP_INTERFACE) DECLARE_MTYPE(RIP_INTERFACE_STRING) diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index f5a75707e8..8a8cbae1fa 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -42,25 +42,42 @@ static int ripd_instance_create(enum nb_event event, { struct rip *rip; struct vrf *vrf; + const char *vrf_name; int socket; + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrf_name); + + /* + * Try to create a RIP socket only if the VRF is enabled, otherwise + * create a disabled RIP instance and wait for the VRF to be enabled. + */ switch (event) { case NB_EV_VALIDATE: break; case NB_EV_PREPARE: - socket = rip_create_socket(); + if (!vrf || !vrf_is_enabled(vrf)) + break; + + socket = rip_create_socket(vrf); if (socket < 0) return NB_ERR_RESOURCE; resource->fd = socket; break; case NB_EV_ABORT: + if (!vrf || !vrf_is_enabled(vrf)) + break; + socket = resource->fd; close(socket); break; case NB_EV_APPLY: - vrf = vrf_lookup_by_id(VRF_DEFAULT); - socket = resource->fd; - rip = rip_create(vrf, socket); + if (vrf && vrf_is_enabled(vrf)) + socket = resource->fd; + else + socket = -1; + + rip = rip_create(vrf_name, vrf, socket); yang_dnode_set_entry(dnode, rip); break; } diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 6fbc170cb9..d8b35cf976 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -47,7 +47,7 @@ static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp, int count = 0; memset(&api, 0, sizeof(api)); - api.vrf_id = rip->vrf_id; + api.vrf_id = rip->vrf->vrf_id; api.type = ZEBRA_ROUTE_RIP; api.safi = SAFI_UNICAST; @@ -56,7 +56,7 @@ static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp, if (count >= MULTIPATH_NUM) break; api_nh = &api.nexthops[count]; - api_nh->vrf_id = rip->vrf_id; + api_nh->vrf_id = rip->vrf->vrf_id; api_nh->gate = rinfo->nh.gate; api_nh->type = NEXTHOP_TYPE_IPV4; if (cmd == ZEBRA_ROUTE_ADD) @@ -153,14 +153,14 @@ static int rip_zebra_read_route(int command, struct zclient *zclient, void rip_redistribute_conf_update(struct rip *rip, int type) { zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, - 0, rip->vrf_id); + 0, rip->vrf->vrf_id); } void rip_redistribute_conf_delete(struct rip *rip, int type) { if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, - AFI_IP, type, 0, rip->vrf_id); + AFI_IP, type, 0, rip->vrf->vrf_id); /* Remove the routes from RIP table. */ rip_redistribute_withdraw(rip, type); @@ -168,21 +168,23 @@ void rip_redistribute_conf_delete(struct rip *rip, int type) int rip_redistribute_check(struct rip *rip, int type) { - return vrf_bitmap_check(zclient->redist[AFI_IP][type], rip->vrf_id); + return vrf_bitmap_check(zclient->redist[AFI_IP][type], + rip->vrf->vrf_id); } void rip_redistribute_clean(struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], rip->vrf_id)) + if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], + rip->vrf->vrf_id)) continue; if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, i, 0, - rip->vrf_id); + rip->vrf->vrf_id); - vrf_bitmap_unset(zclient->redist[AFI_IP][i], rip->vrf_id); + vrf_bitmap_unset(zclient->redist[AFI_IP][i], rip->vrf->vrf_id); } } @@ -191,13 +193,37 @@ void rip_show_redistribute_config(struct vty *vty, struct rip *rip) for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == zclient->redist_default || !vrf_bitmap_check(zclient->redist[AFI_IP][i], - rip->vrf_id)) + rip->vrf->vrf_id)) continue; vty_out(vty, " %s", zebra_route_string(i)); } } +void rip_zebra_vrf_register(struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s: register VRF %s(%u) to zebra", __func__, + vrf->name, vrf->vrf_id); + + zclient_send_reg_requests(zclient, vrf->vrf_id); +} + +void rip_zebra_vrf_deregister(struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__, + vrf->name, vrf->vrf_id); + + zclient_send_dereg_requests(zclient, vrf->vrf_id); +} + static void rip_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); @@ -215,6 +241,7 @@ void rip_zclient_init(struct thread_master *master) zclient->interface_address_delete = rip_interface_address_delete; zclient->interface_up = rip_interface_up; zclient->interface_down = rip_interface_down; + zclient->interface_vrf_update = rip_interface_vrf_update; zclient->redistribute_route_add = rip_zebra_read_route; zclient->redistribute_route_del = rip_zebra_read_route; } diff --git a/ripd/ripd.c b/ripd/ripd.c index c6abfb557d..a6a2a29deb 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -46,6 +46,7 @@ #include "ripd/ripd.h" #include "ripd/rip_debug.h" #include "ripd/rip_errors.h" +#include "ripd/rip_interface.h" /* UDP receive buffer size */ #define RIP_UDP_RCV_BUF 41600 @@ -57,6 +58,8 @@ static int rip_triggered_update(struct thread *); static int rip_update_jitter(unsigned long); static void rip_distance_table_node_cleanup(struct route_table *table, struct route_node *node); +static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock); +static void rip_instance_disable(struct rip *rip); static void rip_distribute_update(struct distribute_ctx *ctx, struct distribute *dist); @@ -73,6 +76,15 @@ static const struct message rip_msg[] = {{RIP_REQUEST, "REQUEST"}, {RIP_POLL_ENTRY, "POLL ENTRY"}, {0}}; +/* Generate rb-tree of RIP instances. */ +static inline int rip_instance_compare(const struct rip *a, const struct rip *b) +{ + return strcmp(a->vrf_name, b->vrf_name); +} +RB_GENERATE(rip_instance_head, rip, entry, rip_instance_compare) + +struct rip_instance_head rip_instances = RB_INITIALIZER(&rip_instances); + /* Utility function to set boradcast option to the socket. */ static int sockopt_broadcast(int sock) { @@ -372,7 +384,6 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, /* Check nexthop address validity. */ static int rip_nexthop_check(struct rip *rip, struct in_addr *addr) { - struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct interface *ifp; struct listnode *cnode; struct connected *ifc; @@ -381,7 +392,7 @@ static int rip_nexthop_check(struct rip *rip, struct in_addr *addr) /* If nexthop address matches local configured address then it is invalid nexthop. */ - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (rip->vrf, ifp) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { p = ifc->address; @@ -1114,7 +1125,8 @@ static void rip_response_process(struct rip_packet *packet, int size, whether the datagram is from a valid neighbor; the source of the datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */ - if (if_lookup_address((void *)&from->sin_addr, AF_INET, rip->vrf_id) + if (if_lookup_address((void *)&from->sin_addr, AF_INET, + rip->vrf->vrf_id) == NULL) { zlog_info( "This datagram doesn't came from a valid neighbor: %s", @@ -1197,7 +1209,7 @@ static void rip_response_process(struct rip_packet *packet, int size, } if (!if_lookup_address((void *)&rte->nexthop, AF_INET, - rip->vrf_id)) { + rip->vrf->vrf_id)) { struct route_node *rn; struct rip_info *rinfo; @@ -1327,11 +1339,12 @@ static void rip_response_process(struct rip_packet *packet, int size, } /* Make socket for RIP protocol. */ -int rip_create_socket(void) +int rip_create_socket(struct vrf *vrf) { int ret; int sock; struct sockaddr_in addr; + const char *vrf_dev = NULL; memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; @@ -1343,11 +1356,17 @@ int rip_create_socket(void) addr.sin_port = htons(RIP_PORT_DEFAULT); /* Make datagram socket. */ - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) { - flog_err_sys(EC_LIB_SOCKET, "Cannot create UDP socket: %s", - safe_strerror(errno)); - return -1; + if (vrf->vrf_id != VRF_DEFAULT) + vrf_dev = vrf->name; + frr_elevate_privs(&ripd_privs) { + sock = vrf_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, vrf->vrf_id, + vrf_dev); + if (sock < 0) { + flog_err_sys(EC_LIB_SOCKET, + "Cannot create UDP socket: %s", + safe_strerror(errno)); + return -1; + } } sockopt_broadcast(sock); @@ -1586,8 +1605,9 @@ void rip_redistribute_delete(struct rip *rip, int type, int sub_type, "infinity metric [delete]", inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, - rip->vrf_id)); + ifindex2ifname( + ifindex, + rip->vrf->vrf_id)); rip_event(rip, RIP_TRIGGERED_UPDATE, 0); } @@ -1708,33 +1728,37 @@ static int rip_read(struct thread *t) len = recvfrom(sock, (char *)&rip_buf.buf, sizeof(rip_buf.buf), 0, (struct sockaddr *)&from, &fromlen); if (len < 0) { - zlog_info("recvfrom failed: %s", safe_strerror(errno)); + zlog_info("recvfrom failed (VRF %s): %s", rip->vrf_name, + safe_strerror(errno)); return len; } /* Check is this packet comming from myself? */ if (if_check_address(rip, from.sin_addr)) { if (IS_RIP_DEBUG_PACKET) - zlog_debug("ignore packet comes from myself"); + zlog_debug("ignore packet comes from myself (VRF %s)", + rip->vrf_name); return -1; } /* Which interface is this packet comes from. */ - ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, rip->vrf_id); + ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, + rip->vrf->vrf_id); if (ifc) ifp = ifc->ifp; /* RIP packet received */ if (IS_RIP_DEBUG_EVENT) - zlog_debug("RECV packet from %s port %d on %s", + zlog_debug("RECV packet from %s port %d on %s (VRF %s)", inet_ntoa(from.sin_addr), ntohs(from.sin_port), - ifp ? ifp->name : "unknown"); + ifp ? ifp->name : "unknown", rip->vrf_name); /* If this packet come from unknown interface, ignore it. */ if (ifp == NULL) { zlog_info( - "rip_read: cannot find interface for packet from %s port %d", - inet_ntoa(from.sin_addr), ntohs(from.sin_port)); + "rip_read: cannot find interface for packet from %s port %d (VRF %s)", + inet_ntoa(from.sin_addr), ntohs(from.sin_port), + rip->vrf_name); return -1; } @@ -1747,9 +1771,9 @@ static int rip_read(struct thread *t) if (ifc == NULL) { zlog_info( "rip_read: cannot find connected address for packet from %s " - "port %d on interface %s", + "port %d on interface %s (VRF %s)", inet_ntoa(from.sin_addr), ntohs(from.sin_port), - ifp->name); + ifp->name, rip->vrf_name); return -1; } @@ -2415,7 +2439,6 @@ static void rip_update_interface(struct connected *ifc, uint8_t version, /* Update send to all interface and neighbor. */ static void rip_update_process(struct rip *rip, int route_type) { - struct vrf *vrf = vrf_lookup_by_id(rip->vrf_id); struct listnode *ifnode, *ifnnode; struct connected *connected; struct interface *ifp; @@ -2425,7 +2448,7 @@ static void rip_update_process(struct rip *rip, int route_type) struct prefix *p; /* Send RIP update to each interface. */ - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (rip->vrf, ifp) { if (if_is_loopback(ifp)) continue; @@ -2478,7 +2501,7 @@ static void rip_update_process(struct rip *rip, int route_type) p = &rp->p; connected = if_lookup_address(&p->u.prefix4, AF_INET, - rip->vrf_id); + rip->vrf->vrf_id); if (!connected) { zlog_warn( "Neighbor %s doesn't have connected interface!", @@ -2622,7 +2645,7 @@ void rip_redistribute_withdraw(struct rip *rip, int type) p->prefixlen, ifindex2ifname( rinfo->nh.ifindex, - rip->vrf_id)); + rip->vrf->vrf_id)); } rip_event(rip, RIP_TRIGGERED_UPDATE, 0); @@ -2641,13 +2664,22 @@ struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id) return vrf->info; } +struct rip *rip_lookup_by_vrf_name(const char *vrf_name) +{ + struct rip rip; + + rip.vrf_name = (char *)vrf_name; + + return RB_FIND(rip_instance_head, &rip_instances, &rip); +} + /* Create new RIP instance and set it to global variable. */ -struct rip *rip_create(struct vrf *vrf, int socket) +struct rip *rip_create(const char *vrf_name, struct vrf *vrf, int socket) { struct rip *rip; - struct interface *ifp; rip = XCALLOC(MTYPE_RIP, sizeof(struct rip)); + rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf_name); /* Set initial value. */ rip->ecmp = yang_get_default_bool("%s/allow-ecmp", RIP_INSTANCE); @@ -2685,31 +2717,23 @@ struct rip *rip_create(struct vrf *vrf, int socket) rip->offset_list_master->del = (void (*)(void *))offset_list_del; /* Distribute list install. */ - rip->distribute_ctx = - distribute_list_ctx_create(vrf_lookup_by_id(VRF_DEFAULT)); + 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); /* Make output stream. */ rip->obuf = stream_new(1500); - /* Set socket. */ - rip->sock = socket; - - /* Create read and timer thread. */ - rip_event(rip, RIP_READ, rip->sock); - rip_event(rip, RIP_UPDATE_EVENT, 1); - - /* Link RIP instance to VRF. */ - rip->vrf_id = vrf->vrf_id; - vrf->info = rip; - FOR_ALL_INTERFACES (vrf, ifp) { - struct rip_interface *ri; - - ri = ifp->info; - ri->rip = rip; + /* 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; } @@ -2988,20 +3012,34 @@ static const char *rip_route_type_print(int sub_type) DEFUN (show_ip_rip, show_ip_rip_cmd, - "show ip rip", + "show ip rip [vrf NAME]", SHOW_STR IP_STR - "Show RIP routes\n") + "Show RIP routes\n" + VRF_CMD_HELP_STR) { struct rip *rip; struct route_node *np; struct rip_info *rinfo = NULL; struct list *list = NULL; struct listnode *listnode = NULL; + const char *vrf_name; + int idx = 0; - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (!rip) + if (argv_find(argv, argc, "vrf", &idx)) + vrf_name = argv[idx + 1]->arg; + else + vrf_name = VRF_DEFAULT_NAME; + + rip = rip_lookup_by_vrf_name(vrf_name); + if (!rip) { + vty_out(vty, "%% RIP instance not found\n"); return CMD_SUCCESS; + } + if (!rip->enabled) { + vty_out(vty, "%% RIP instance is disabled\n"); + return CMD_SUCCESS; + } vty_out(vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n" @@ -3093,23 +3131,36 @@ DEFUN (show_ip_rip, /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */ DEFUN (show_ip_rip_status, show_ip_rip_status_cmd, - "show ip rip status", + "show ip rip [vrf NAME] status", SHOW_STR IP_STR "Show RIP routes\n" + VRF_CMD_HELP_STR "IP routing protocol process parameters and statistics\n") { struct rip *rip; - struct vrf *vrf; struct interface *ifp; struct rip_interface *ri; extern const struct message ri_version_msg[]; const char *send_version; const char *receive_version; + const char *vrf_name; + int idx = 0; - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (!rip) + if (argv_find(argv, argc, "vrf", &idx)) + vrf_name = argv[idx + 1]->arg; + else + vrf_name = VRF_DEFAULT_NAME; + + rip = rip_lookup_by_vrf_name(vrf_name); + if (!rip) { + vty_out(vty, "%% RIP instance not found\n"); return CMD_SUCCESS; + } + if (!rip->enabled) { + vty_out(vty, "%% RIP instance is disabled\n"); + return CMD_SUCCESS; + } vty_out(vty, "Routing Protocol is \"rip\"\n"); vty_out(vty, " Sending updates every %u seconds with +/-50%%,", @@ -3141,8 +3192,7 @@ DEFUN (show_ip_rip_status, vty_out(vty, " Interface Send Recv Key-chain\n"); - vrf = vrf_lookup_by_id(rip->vrf_id); - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (rip->vrf, ifp) { ri = ifp->info; if (!ri->running) @@ -3176,7 +3226,7 @@ DEFUN (show_ip_rip_status, { int found_passive = 0; - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (rip->vrf, ifp) { ri = ifp->info; if ((ri->enable_network || ri->enable_interface) @@ -3204,28 +3254,31 @@ DEFUN (show_ip_rip_status, /* RIP configuration write function. */ static int config_write_rip(struct vty *vty) { + struct rip *rip; int write = 0; - struct lyd_node *dnode; - dnode = yang_dnode_get(running_config->dnode, - "/frr-ripd:ripd/instance"); - if (dnode) { - struct rip *rip; + RB_FOREACH(rip, rip_instance_head, &rip_instances) { + char xpath[XPATH_MAXLEN]; + struct lyd_node *dnode; - write++; + snprintf(xpath, sizeof(xpath), + "/frr-ripd:ripd/instance[vrf='%s']", rip->vrf_name); + + dnode = yang_dnode_get(running_config->dnode, xpath); + assert(dnode); nb_cli_show_dnode_cmds(vty, dnode, false); - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (rip) { - /* Distribute configuration. */ - write += config_write_distribute(vty, - rip->distribute_ctx); + /* Distribute configuration. */ + config_write_distribute(vty, rip->distribute_ctx); - /* Interface routemap configuration */ - write += config_write_if_rmap(vty); - } + /* Interface routemap configuration */ + if (strmatch(rip->vrf_name, VRF_DEFAULT_NAME)) + config_write_if_rmap(vty); + + write = 1; } + return write; } @@ -3241,10 +3294,10 @@ static void rip_distribute_update(struct distribute_ctx *ctx, struct access_list *alist; struct prefix_list *plist; - if (!dist->ifname) + if (!ctx->vrf || !dist->ifname) return; - ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id); if (ifp == NULL) return; @@ -3323,46 +3376,8 @@ static void rip_distribute_update_all_wrapper(struct access_list *notused) /* Delete all added rip route. */ void rip_clean(struct rip *rip) { - struct vrf *vrf; - struct interface *ifp; - struct route_node *rp; - - /* Clear RIP routes */ - for (rp = route_top(rip->table); rp; rp = route_next(rp)) { - struct rip_info *rinfo; - struct list *list; - struct listnode *listnode; - - if ((list = rp->info) == NULL) - continue; - - rinfo = listgetdata(listhead(list)); - if (rip_route_rte(rinfo)) - rip_zebra_ipv4_delete(rip, rp); - - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - RIP_TIMER_OFF(rinfo->t_timeout); - RIP_TIMER_OFF(rinfo->t_garbage_collect); - rip_info_free(rinfo); - } - list_delete(&list); - rp->info = NULL; - route_unlock_node(rp); - } - - /* 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; - } + if (rip->enabled) + rip_instance_disable(rip); stream_free(rip->obuf); @@ -3385,16 +3400,8 @@ void rip_clean(struct rip *rip) route_table_finish(rip->distance_table); rip_redistribute_clean(rip); - vrf = vrf_lookup_by_id(rip->vrf_id); - vrf->info = NULL; - - FOR_ALL_INTERFACES (vrf, ifp) { - struct rip_interface *ri; - - ri = ifp->info; - ri->rip = NULL; - } - + RB_REMOVE(rip_instance_head, &rip_instances, rip); + XFREE(MTYPE_RIP_VRF_NAME, rip->vrf_name); XFREE(MTYPE_RIP, rip); } @@ -3461,6 +3468,168 @@ static void rip_routemap_update(const char *notused) rip_routemap_update_redistribute(rip); } +/* Link RIP instance to VRF. */ +static void rip_vrf_link(struct rip *rip, struct vrf *vrf) +{ + struct interface *ifp; + + rip->vrf = vrf; + rip->distribute_ctx->vrf = vrf; + vrf->info = rip; + + FOR_ALL_INTERFACES (vrf, ifp) + rip_interface_sync(ifp); +} + +/* Unlink RIP instance from VRF. */ +static void rip_vrf_unlink(struct rip *rip, struct vrf *vrf) +{ + struct interface *ifp; + + rip->vrf = NULL; + rip->distribute_ctx->vrf = NULL; + vrf->info = NULL; + + FOR_ALL_INTERFACES (vrf, ifp) + rip_interface_sync(ifp); +} + +static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock) +{ + rip->sock = sock; + + rip_vrf_link(rip, vrf); + rip->enabled = true; + + /* Create read and timer thread. */ + rip_event(rip, RIP_READ, rip->sock); + rip_event(rip, RIP_UPDATE_EVENT, 1); + + rip_zebra_vrf_register(vrf); +} + +static void rip_instance_disable(struct rip *rip) +{ + struct vrf *vrf = rip->vrf; + struct route_node *rp; + + /* Clear RIP routes */ + for (rp = route_top(rip->table); rp; rp = route_next(rp)) { + struct rip_info *rinfo; + struct list *list; + struct listnode *listnode; + + if ((list = rp->info) == NULL) + continue; + + rinfo = listgetdata(listhead(list)); + if (rip_route_rte(rinfo)) + rip_zebra_ipv4_delete(rip, rp); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + rip_info_free(rinfo); + } + list_delete(&list); + rp->info = NULL; + route_unlock_node(rp); + } + + /* Cancel RIP related timers. */ + RIP_TIMER_OFF(rip->t_update); + RIP_TIMER_OFF(rip->t_triggered_update); + RIP_TIMER_OFF(rip->t_triggered_interval); + + /* Cancel read thread. */ + THREAD_READ_OFF(rip->t_read); + + /* Close RIP socket. */ + close(rip->sock); + rip->sock = -1; + + /* Clear existing peers. */ + list_delete_all_node(rip->peer_list); + + rip_zebra_vrf_deregister(vrf); + + rip_vrf_unlink(rip, vrf); + rip->enabled = false; +} + +static int rip_vrf_new(struct vrf *vrf) +{ + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name, + vrf->vrf_id); + + return 0; +} + +static int rip_vrf_delete(struct vrf *vrf) +{ + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name, + vrf->vrf_id); + + return 0; +} + +static int rip_vrf_enable(struct vrf *vrf) +{ + struct rip *rip; + int socket; + + rip = rip_lookup_by_vrf_name(vrf->name); + if (!rip || rip->enabled) + return 0; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name, + vrf->vrf_id); + + /* Activate the VRF RIP instance. */ + if (!rip->enabled) { + socket = rip_create_socket(vrf); + if (socket < 0) + return -1; + + rip_instance_enable(rip, vrf, socket); + } + + return 0; +} + +static int rip_vrf_disable(struct vrf *vrf) +{ + struct rip *rip; + + rip = rip_lookup_by_vrf_name(vrf->name); + if (!rip || !rip->enabled) + return 0; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name, + vrf->vrf_id); + + /* Deactivate the VRF RIP instance. */ + if (rip->enabled) + rip_instance_disable(rip); + + return 0; +} + +void rip_vrf_init(void) +{ + vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete, + NULL); +} + +void rip_vrf_terminate(void) +{ + vrf_terminate(); +} + /* Allocate new rip structure and set default value. */ void rip_init(void) { diff --git a/ripd/ripd.h b/ripd/ripd.h index a18a741579..268ba74b96 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -99,8 +99,16 @@ /* RIP structure. */ struct rip { - /* VRF ID. */ - vrf_id_t vrf_id; + RB_ENTRY(rip) entry; + + /* VRF this routing instance is associated with. */ + char *vrf_name; + + /* VRF backpointer (might be NULL if the VRF doesn't exist). */ + struct vrf *vrf; + + /* Status of the routing instance. */ + bool enabled; /* RIP socket. */ int sock; @@ -182,6 +190,8 @@ struct rip { 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 { @@ -416,11 +426,15 @@ extern int rip_passive_nondefault_unset(struct rip *rip, const char *ifname); extern void rip_passive_nondefault_clean(struct rip *rip); extern void rip_if_init(void); extern void rip_route_map_init(void); +extern void rip_zebra_vrf_register(struct vrf *vrf); +extern void rip_zebra_vrf_deregister(struct vrf *vrf); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_stop(void); extern int if_check_address(struct rip *rip, struct in_addr addr); extern struct rip *rip_lookup_by_vrf_id(vrf_id_t vrf_id); -extern struct rip *rip_create(struct vrf *vrf, int socket); +extern struct rip *rip_lookup_by_vrf_name(const char *vrf_name); +extern struct rip *rip_create(const char *vrf_name, struct vrf *vrf, + int socket); extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t, struct connected *); @@ -436,7 +450,7 @@ 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(void); +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); @@ -495,6 +509,9 @@ extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, extern int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2); +extern void rip_vrf_init(void); +extern void rip_vrf_terminate(void); + /* YANG notifications */ extern void ripd_notif_send_auth_type_failure(const char *ifname); extern void ripd_notif_send_auth_failure(const char *ifname); diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 6cf45789dd..11be03363c 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1519,8 +1519,8 @@ DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)", return CMD_SUCCESS; } -DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip", - ROUTER_STR "RIP\n") +DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]", + ROUTER_STR "RIP\n" VRF_CMD_HELP_STR) { vty->node = RIP_NODE; return CMD_SUCCESS; diff --git a/yang/example/ripd.json b/yang/example/ripd.json index 888c52b930..00040622e5 100644 --- a/yang/example/ripd.json +++ b/yang/example/ripd.json @@ -20,25 +20,28 @@ ] }, "frr-ripd:ripd": { - "instance": { - "allow-ecmp": "true", - "distance": { - "source": [ + "instance": [ + { + "vrf": "default", + "allow-ecmp": "true", + "distance": { + "source": [ + { + "distance": "25", + "prefix": "172.16.1.0/24" + } + ] + }, + "redistribute": [ { - "prefix": "172.16.1.0/24", - "distance": "25" + "metric": "3", + "protocol": "ospf" } + ], + "static-route": [ + "10.0.1.0/24" ] - }, - "redistribute": [ - { - "protocol": "ospf", - "metric": "3" - } - ], - "static-route": [ - "10.0.1.0/24" - ] - } + } + ] } } diff --git a/yang/example/ripd.xml b/yang/example/ripd.xml index 756e382bd6..2feddde2d8 100644 --- a/yang/example/ripd.xml +++ b/yang/example/ripd.xml @@ -18,6 +18,7 @@ + default true 10.0.1.0/24 diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index 8073fba77e..ca2b766159 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -34,13 +34,18 @@ module frr-ripd { container ripd { /* - * Global configuration data + * Routing instance configuration. */ - container instance { - presence "Present if the RIP protocol is enabled."; + list instance { + key "vrf"; description "RIP routing instance."; + leaf vrf { + type string; + description + "VRF name."; + } leaf allow-ecmp { type boolean; default "false"; From 32600a9807fafe113cc332dff1496631269f6a3a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 28/36] ripd: make YANG operational-data VRF aware too Move the "state" container into the "instance" list and adapt the code accordingly. Signed-off-by: Renato Westphal --- ripd/rip_northbound.c | 190 +++++++++++++++++++++++------------------- ripd/ripd.h | 1 + yang/frr-ripd.yang | 136 +++++++++++++++--------------- 3 files changed, 175 insertions(+), 152 deletions(-) diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 8a8cbae1fa..1bdb2341e4 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -99,6 +99,38 @@ static int ripd_instance_delete(enum nb_event event, return NB_OK; } +static const void *ripd_instance_get_next(const void *parent_list_entry, + const void *list_entry) +{ + const struct rip *rip = list_entry; + + if (list_entry == NULL) + rip = RB_MIN(rip_instance_head, &rip_instances); + else + rip = RB_NEXT(rip_instance_head, (struct rip *)rip); + + return rip; +} + +static int ripd_instance_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct rip *rip = list_entry; + + keys->num = 1; + strlcpy(keys->key[0], rip->vrf_name, sizeof(keys->key[0])); + + return NB_OK; +} + +static const void *ripd_instance_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + const char *vrf_name = keys->key[0]; + + return rip_lookup_by_vrf_name(vrf_name); +} + /* * XPath: /frr-ripd:ripd/instance/allow-ecmp */ @@ -1099,19 +1131,15 @@ lib_interface_rip_authentication_key_chain_delete(enum nb_event event, } /* - * XPath: /frr-ripd:ripd/state/neighbors/neighbor + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor */ static const void * -ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry, - const void *list_entry) +ripd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, + const void *list_entry) { - struct rip *rip; + const struct rip *rip = parent_list_entry; struct listnode *node; - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (rip == NULL) - return NULL; - if (list_entry == NULL) node = listhead(rip->peer_list); else @@ -1120,8 +1148,9 @@ ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry, return node; } -static int ripd_state_neighbors_neighbor_get_keys(const void *list_entry, - struct yang_list_keys *keys) +static int +ripd_instance_state_neighbors_neighbor_get_keys(const void *list_entry, + struct yang_list_keys *keys) { const struct listnode *node = list_entry; const struct rip_peer *peer = listgetdata(node); @@ -1133,21 +1162,16 @@ static int ripd_state_neighbors_neighbor_get_keys(const void *list_entry, return NB_OK; } -static const void * -ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) +static const void *ripd_instance_state_neighbors_neighbor_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys) { - struct rip *rip; + const struct rip *rip = parent_list_entry; struct in_addr address; struct rip_peer *peer; struct listnode *node; yang_str2ipv4(keys->key[0], &address); - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (rip == NULL) - return NULL; - for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) { if (IPV4_ADDR_SAME(&peer->addr, &address)) return node; @@ -1157,11 +1181,11 @@ ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, } /* - * XPath: /frr-ripd:ripd/state/neighbors/neighbor/address + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/address */ static struct yang_data * -ripd_state_neighbors_neighbor_address_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_neighbors_neighbor_address_get_elem(const char *xpath, + const void *list_entry) { const struct listnode *node = list_entry; const struct rip_peer *peer = listgetdata(node); @@ -1170,22 +1194,22 @@ ripd_state_neighbors_neighbor_address_get_elem(const char *xpath, } /* - * XPath: /frr-ripd:ripd/state/neighbors/neighbor/last-update + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/last-update */ static struct yang_data * -ripd_state_neighbors_neighbor_last_update_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_neighbors_neighbor_last_update_get_elem( + const char *xpath, const void *list_entry) { /* TODO: yang:date-and-time is tricky */ return NULL; } /* - * XPath: /frr-ripd:ripd/state/neighbors/neighbor/bad-packets-rcvd + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd */ static struct yang_data * -ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( + const char *xpath, const void *list_entry) { const struct listnode *node = list_entry; const struct rip_peer *peer = listgetdata(node); @@ -1194,11 +1218,11 @@ ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(const char *xpath, } /* - * XPath: /frr-ripd:ripd/state/neighbors/neighbor/bad-routes-rcvd + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd */ static struct yang_data * -ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( + const char *xpath, const void *list_entry) { const struct listnode *node = list_entry; const struct rip_peer *peer = listgetdata(node); @@ -1207,19 +1231,15 @@ ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath, } /* - * XPath: /frr-ripd:ripd/state/routes/route + * XPath: /frr-ripd:ripd/instance/state/routes/route */ static const void * -ripd_state_routes_route_get_next(const void *parent_list_entry, - const void *list_entry) +ripd_instance_state_routes_route_get_next(const void *parent_list_entry, + const void *list_entry) { - struct rip *rip; + const struct rip *rip = parent_list_entry; struct route_node *rn; - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (rip == NULL) - return NULL; - if (list_entry == NULL) rn = route_top(rip->table); else @@ -1230,8 +1250,9 @@ ripd_state_routes_route_get_next(const void *parent_list_entry, return rn; } -static int ripd_state_routes_route_get_keys(const void *list_entry, - struct yang_list_keys *keys) +static int +ripd_instance_state_routes_route_get_keys(const void *list_entry, + struct yang_list_keys *keys) { const struct route_node *rn = list_entry; @@ -1242,19 +1263,15 @@ static int ripd_state_routes_route_get_keys(const void *list_entry, } static const void * -ripd_state_routes_route_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) +ripd_instance_state_routes_route_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) { - struct rip *rip; + const struct rip *rip = parent_list_entry; struct prefix prefix; struct route_node *rn; yang_str2ipv4p(keys->key[0], &prefix); - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (rip == NULL) - return NULL; - rn = route_node_lookup(rip->table, &prefix); if (!rn || !rn->info) return NULL; @@ -1265,11 +1282,11 @@ ripd_state_routes_route_lookup_entry(const void *parent_list_entry, } /* - * XPath: /frr-ripd:ripd/state/routes/route/prefix + * XPath: /frr-ripd:ripd/instance/state/routes/route/prefix */ static struct yang_data * -ripd_state_routes_route_prefix_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_routes_route_prefix_get_elem(const char *xpath, + const void *list_entry) { const struct route_node *rn = list_entry; const struct rip_info *rinfo = listnode_head(rn->info); @@ -1278,11 +1295,11 @@ ripd_state_routes_route_prefix_get_elem(const char *xpath, } /* - * XPath: /frr-ripd:ripd/state/routes/route/next-hop + * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop */ static struct yang_data * -ripd_state_routes_route_next_hop_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_routes_route_next_hop_get_elem(const char *xpath, + const void *list_entry) { const struct route_node *rn = list_entry; const struct rip_info *rinfo = listnode_head(rn->info); @@ -1297,31 +1314,33 @@ ripd_state_routes_route_next_hop_get_elem(const char *xpath, } /* - * XPath: /frr-ripd:ripd/state/routes/route/interface + * XPath: /frr-ripd:ripd/instance/state/routes/route/interface */ static struct yang_data * -ripd_state_routes_route_interface_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_routes_route_interface_get_elem(const char *xpath, + const void *list_entry) { const struct route_node *rn = list_entry; const struct rip_info *rinfo = listnode_head(rn->info); + const struct rip *rip = rip_info_get_instance(rinfo); switch (rinfo->nh.type) { case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX: return yang_data_new_string( - xpath, ifindex2ifname(rinfo->nh.ifindex, VRF_DEFAULT)); + xpath, + ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id)); default: return NULL; } } /* - * XPath: /frr-ripd:ripd/state/routes/route/metric + * XPath: /frr-ripd:ripd/instance/state/routes/route/metric */ static struct yang_data * -ripd_state_routes_route_metric_get_elem(const char *xpath, - const void *list_entry) +ripd_instance_state_routes_route_metric_get_elem(const char *xpath, + const void *list_entry) { const struct route_node *rn = list_entry; const struct rip_info *rinfo = listnode_head(rn->info); @@ -1423,6 +1442,9 @@ const struct frr_yang_module_info frr_ripd_info = { .xpath = "/frr-ripd:ripd/instance", .cbs.create = ripd_instance_create, .cbs.delete = 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, }, { @@ -1607,48 +1629,48 @@ const struct frr_yang_module_info frr_ripd_info = { .cbs.cli_show = cli_show_ip_rip_authentication_key_chain, }, { - .xpath = "/frr-ripd:ripd/state/neighbors/neighbor", - .cbs.get_next = ripd_state_neighbors_neighbor_get_next, - .cbs.get_keys = ripd_state_neighbors_neighbor_get_keys, - .cbs.lookup_entry = ripd_state_neighbors_neighbor_lookup_entry, + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor", + .cbs.get_next = ripd_instance_state_neighbors_neighbor_get_next, + .cbs.get_keys = ripd_instance_state_neighbors_neighbor_get_keys, + .cbs.lookup_entry = ripd_instance_state_neighbors_neighbor_lookup_entry, }, { - .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/address", - .cbs.get_elem = ripd_state_neighbors_neighbor_address_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/address", + .cbs.get_elem = ripd_instance_state_neighbors_neighbor_address_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/last-update", - .cbs.get_elem = ripd_state_neighbors_neighbor_last_update_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/last-update", + .cbs.get_elem = ripd_instance_state_neighbors_neighbor_last_update_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/bad-packets-rcvd", - .cbs.get_elem = ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd", + .cbs.get_elem = ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/bad-routes-rcvd", - .cbs.get_elem = ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd", + .cbs.get_elem = ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/routes/route", - .cbs.get_next = ripd_state_routes_route_get_next, - .cbs.get_keys = ripd_state_routes_route_get_keys, - .cbs.lookup_entry = ripd_state_routes_route_lookup_entry, + .xpath = "/frr-ripd:ripd/instance/state/routes/route", + .cbs.get_next = ripd_instance_state_routes_route_get_next, + .cbs.get_keys = ripd_instance_state_routes_route_get_keys, + .cbs.lookup_entry = ripd_instance_state_routes_route_lookup_entry, }, { - .xpath = "/frr-ripd:ripd/state/routes/route/prefix", - .cbs.get_elem = ripd_state_routes_route_prefix_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/routes/route/prefix", + .cbs.get_elem = ripd_instance_state_routes_route_prefix_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/routes/route/next-hop", - .cbs.get_elem = ripd_state_routes_route_next_hop_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/routes/route/next-hop", + .cbs.get_elem = ripd_instance_state_routes_route_next_hop_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/routes/route/interface", - .cbs.get_elem = ripd_state_routes_route_interface_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/routes/route/interface", + .cbs.get_elem = ripd_instance_state_routes_route_interface_get_elem, }, { - .xpath = "/frr-ripd:ripd/state/routes/route/metric", - .cbs.get_elem = ripd_state_routes_route_metric_get_elem, + .xpath = "/frr-ripd:ripd/instance/state/routes/route/metric", + .cbs.get_elem = ripd_instance_state_routes_route_metric_get_elem, }, { .xpath = "/frr-ripd:clear-rip-route", diff --git a/ripd/ripd.h b/ripd/ripd.h index 268ba74b96..d88c5c1e61 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -517,6 +517,7 @@ extern void ripd_notif_send_auth_type_failure(const char *ifname); extern void ripd_notif_send_auth_failure(const char *ifname); extern struct zebra_privs_t ripd_privs; +extern struct rip_instance_head rip_instances; /* Master thread strucutre. */ extern struct thread_master *master; diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index ca2b766159..e9f2fe0e99 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -298,83 +298,83 @@ module frr-ripd { '(./receive = "2" and ./send = "2") or ' + '(./receive = "1-2" and ./send = "2")'; } - } - /* - * Operational data. - */ - container state { - config false; - description - "Operational data."; - - container neighbors { + /* + * Operational data. + */ + container state { + config false; description - "Neighbor information."; - list neighbor { - key "address"; + "Operational data."; + + container neighbors { description - "A RIP neighbor."; - leaf address { - type inet:ipv4-address; + "Neighbor information."; + list neighbor { + key "address"; description - "IP address that a RIP neighbor is using as its - source address."; - } - leaf last-update { - type yang:date-and-time; - description - "The time when the most recent RIP update was - received from this neighbor."; - } - leaf bad-packets-rcvd { - type yang:counter32; - description - "The number of RIP invalid packets received from - this neighbor which were subsequently discarded - for any reason (e.g. a version 0 packet, or an - unknown command type)."; - } - leaf bad-routes-rcvd { - type yang:counter32; - description - "The number of routes received from this neighbor, - in valid RIP packets, which were ignored for any - reason (e.g. unknown address family, or invalid - metric)."; + "A RIP neighbor."; + leaf address { + type inet:ipv4-address; + description + "IP address that a RIP neighbor is using as its + source address."; + } + leaf last-update { + type yang:date-and-time; + description + "The time when the most recent RIP update was + received from this neighbor."; + } + leaf bad-packets-rcvd { + type yang:counter32; + description + "The number of RIP invalid packets received from + this neighbor which were subsequently discarded + for any reason (e.g. a version 0 packet, or an + unknown command type)."; + } + leaf bad-routes-rcvd { + type yang:counter32; + description + "The number of routes received from this neighbor, + in valid RIP packets, which were ignored for any + reason (e.g. unknown address family, or invalid + metric)."; + } } } - } - container routes { - description - "Route information."; - list route { - key "prefix"; + container routes { description - "A RIP IPv4 route."; - leaf prefix { - type inet:ipv4-prefix; + "Route information."; + list route { + key "prefix"; description - "IP address (in the form A.B.C.D) and prefix length, - separated by the slash (/) character. The range of - values for the prefix-length is 0 to 32."; - } - leaf next-hop { - type inet:ipv4-address; - description - "Next hop IPv4 address."; - } - leaf interface { - type string; - description - "The interface that the route uses."; - } - leaf metric { - type uint8 { - range "0..16"; + "A RIP IPv4 route."; + leaf prefix { + type inet:ipv4-prefix; + description + "IP address (in the form A.B.C.D) and prefix length, + separated by the slash (/) character. The range of + values for the prefix-length is 0 to 32."; + } + leaf next-hop { + type inet:ipv4-address; + description + "Next hop IPv4 address."; + } + leaf interface { + type string; + description + "The interface that the route uses."; + } + leaf metric { + type uint8 { + range "0..16"; + } + description + "Route metric."; } - description - "Route metric."; } } } From 14f17e6362fdc36428883c8557df6c681c9bceb4 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 29/36] ripd: add vrf input parameter to the "clear-rip-route" RPC Description of the new parameter (adapted from the ietf-rip module): "VRF name identifying a specific RIP instance. This leaf is optional for the rpc. If it is specified, the rpc will clear all routes in the specified RIP instance; if it is not specified, the rpc will clear all routes in all RIP instances."; Signed-off-by: Renato Westphal --- ripd/rip_cli.c | 18 +++++++++++++++--- ripd/rip_northbound.c | 41 ++++++++++++++++++++++++++++++++--------- yang/frr-ripd.yang | 13 +++++++++++++ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index be24d04ff3..6e5c01b6db 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -983,12 +983,24 @@ void cli_show_ip_rip_authentication_key_chain(struct vty *vty, */ DEFPY (clear_ip_rip, clear_ip_rip_cmd, - "clear ip rip", + "clear ip rip [vrf WORD]", CLEAR_STR IP_STR - "Clear IP RIP database\n") + "Clear IP RIP database\n" + VRF_CMD_HELP_STR) { - return nb_cli_rpc("/frr-ripd:clear-rip-route", NULL, NULL); + struct list *input; + + input = list_new(); + if (vrf) { + struct yang_data *yang_vrf; + + yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf", + vrf); + listnode_add(input, yang_vrf); + } + + return nb_cli_rpc("/frr-ripd:clear-rip-route", input, NULL); } void rip_cli_init(void) diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 1bdb2341e4..d2360c470c 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -31,6 +31,7 @@ #include "libfrr.h" #include "ripd/ripd.h" +#include "ripd/rip_debug.h" #include "ripd/rip_cli.h" /* @@ -1351,21 +1352,19 @@ ripd_instance_state_routes_route_metric_get_elem(const char *xpath, /* * XPath: /frr-ripd:clear-rip-route */ -static int clear_rip_route_rpc(const char *xpath, const struct list *input, - struct list *output) +static void clear_rip_route(struct rip *rip) { - struct rip *rip; struct route_node *rp; - struct rip_info *rinfo; - struct list *list; - struct listnode *listnode; - rip = rip_lookup_by_vrf_id(VRF_DEFAULT); - if (!rip) - return NB_OK; + if (IS_RIP_DEBUG_EVENT) + zlog_debug("Clearing all RIP routes (VRF %s)", rip->vrf_name); /* Clear received RIP routes */ for (rp = route_top(rip->table); rp; rp = route_next(rp)) { + struct list *list; + struct listnode *listnode; + struct rip_info *rinfo; + list = rp->info; if (!list) continue; @@ -1392,6 +1391,30 @@ static int clear_rip_route_rpc(const char *xpath, const struct list *input, route_unlock_node(rp); } } +} + +static int clear_rip_route_rpc(const char *xpath, const struct list *input, + struct list *output) +{ + struct rip *rip; + struct yang_data *yang_vrf; + + yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf"); + if (yang_vrf) { + rip = rip_lookup_by_vrf_name(yang_vrf->value); + if (rip) + clear_rip_route(rip); + } else { + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + rip = vrf->info; + if (!rip) + continue; + + clear_rip_route(rip); + } + } return NB_OK; } diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index e9f2fe0e99..07690793f0 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -552,6 +552,19 @@ module frr-ripd { description "Clears RIP routes from the IP routing table and routes redistributed into the RIP protocol."; + + input { + leaf vrf { + type string; + description + "VRF name identifying a specific RIP instance. + This leaf is optional for the rpc. + If it is specified, the rpc will clear all routes in the + specified RIP instance; + if it is not specified, the rpc will clear all routes in + all RIP instances."; + } + } } /* From dde7b15b83513b5883378ba1d4f2298ef451450b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 30/36] ripngd: add VRF support * Turn the "instance" YANG presence-container into a YANG list keyed by the new "vrf" leaf. This is a backward incompatible change but this should be ok for now. * RIPng VRF instances can be configured even when the corresponding VRF doesn't exist. And a RIPng VRF instance isn't deleted when the corresponding VRF is deleted. For this to work, implement the ripng_instance_enable() and ripng_instance_disable() functions that are called to enable/disable RIPng routing instances when necessary. A RIPng routing instance can be enabled only when the corresponding VRF is enabled (this information comes from zebra and depends on the underlying VRF backend). Routing instances are stored in the new ripng_instances rb-tree (global variable). * Add a vrf pointer to the ripng structure instead of storing vrf_id only. This is much more convenient than using vrf_lookup_by_id() every time we need to get the vrf pointer from the VRF ID. The ripng->vrf pointer is updated whenever the VRF enable/disable hooks are called. Signed-off-by: Renato Westphal --- ripngd/ripng_cli.c | 42 +++- ripngd/ripng_interface.c | 113 ++++++---- ripngd/ripng_main.c | 17 +- ripngd/ripng_memory.c | 1 + ripngd/ripng_memory.h | 1 + ripngd/ripng_northbound.c | 25 ++- ripngd/ripng_zebra.c | 45 +++- ripngd/ripngd.c | 442 +++++++++++++++++++++++++++----------- ripngd/ripngd.h | 28 ++- vtysh/vtysh.c | 4 +- yang/frr-ripngd.yang | 11 +- 11 files changed, 517 insertions(+), 212 deletions(-) diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index a187e80fd7..c89832d51d 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -39,31 +39,46 @@ */ DEFPY_NOSH (router_ripng, router_ripng_cmd, - "router ripng", + "router ripng [vrf NAME]", "Enable a routing process\n" - "Make RIPng instance command\n") + "Make RIPng instance command\n" + VRF_CMD_HELP_STR) { + char xpath[XPATH_MAXLEN]; int ret; - nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE, - NULL); + /* 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_CREATE, NULL); ret = nb_cli_apply_changes(vty, NULL); if (ret == CMD_SUCCESS) - VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance"); + VTY_PUSH_XPATH(RIPNG_NODE, xpath); return ret; } 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_DELETE, - 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); return nb_cli_apply_changes(vty, NULL); } @@ -71,8 +86,15 @@ DEFPY (no_router_ripng, void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { + const char *vrf_name; + + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + vty_out(vty, "!\n"); - vty_out(vty, "router ripng\n"); + vty_out(vty, "router ripng"); + if (!strmatch(vrf_name, VRF_DEFAULT_NAME)) + vty_out(vty, " vrf %s", vrf_name); + vty_out(vty, "\n"); } /* diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index af2b1c260a..edc258c05b 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -209,9 +209,11 @@ int ripng_interface_up(int command, struct zclient *zclient, if (IS_RIPNG_DEBUG_ZEBRA) zlog_debug( - "interface up %s index %d flags %llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6); + "interface up %s vrf %u index %d flags %llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6); + + ripng_interface_sync(ifp); /* Check if this interface is RIPng enabled or not. */ ripng_enable_apply(ifp); @@ -240,13 +242,14 @@ int ripng_interface_down(int command, struct zclient *zclient, if (ifp == NULL) return 0; + ripng_interface_sync(ifp); ripng_if_down(ifp); if (IS_RIPNG_DEBUG_ZEBRA) zlog_debug( - "interface down %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6); + "interface down %s vrf %u index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6); return 0; } @@ -258,12 +261,13 @@ int ripng_interface_add(int command, struct zclient *zclient, struct interface *ifp; ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + ripng_interface_sync(ifp); if (IS_RIPNG_DEBUG_ZEBRA) zlog_debug( - "RIPng interface add %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6); + "RIPng interface add %s vrf %u index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6); /* Check is this interface is RIP enabled or not.*/ ripng_enable_apply(ifp); @@ -291,13 +295,15 @@ int ripng_interface_delete(int command, struct zclient *zclient, if (ifp == NULL) return 0; + ripng_interface_sync(ifp); if (if_is_up(ifp)) { ripng_if_down(ifp); } - zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6); + zlog_info( + "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6); /* To support pseudo interface do not free interface structure. */ /* if_delete(ifp); */ @@ -306,13 +312,34 @@ int ripng_interface_delete(int command, struct zclient *zclient, return 0; } +/* VRF update for an interface. */ +int ripng_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct interface *ifp; + vrf_id_t new_vrf_id; + + ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, + &new_vrf_id); + if (!ifp) + return 0; + + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug("interface %s VRF change vrf_id %u new vrf id %u", + ifp->name, vrf_id, new_vrf_id); + + if_update_to_new_vrf(ifp, new_vrf_id); + ripng_interface_sync(ifp); + + return 0; +} + void ripng_interface_clean(struct ripng *ripng) { - struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; struct ripng_interface *ri; - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (ripng->vrf, ifp) { ri = ifp->info; ri->enable_network = 0; @@ -748,10 +775,9 @@ void ripng_enable_apply(struct interface *ifp) /* Set distribute list to all interfaces. */ static void ripng_enable_apply_all(struct ripng *ripng) { - struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; - FOR_ALL_INTERFACES (vrf, ifp) + FOR_ALL_INTERFACES (ripng->vrf, ifp) ripng_enable_apply(ifp); } @@ -812,10 +838,9 @@ void ripng_passive_interface_apply(struct interface *ifp) static void ripng_passive_interface_apply_all(struct ripng *ripng) { - struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; - FOR_ALL_INTERFACES (vrf, ifp) + FOR_ALL_INTERFACES (ripng->vrf, ifp) ripng_passive_interface_apply(ifp); } @@ -890,17 +915,12 @@ int ripng_network_write(struct vty *vty, struct ripng *ripng) return 0; } -static struct ripng_interface *ri_new(struct interface *ifp) +static struct ripng_interface *ri_new(void) { - 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 @@ -911,9 +931,25 @@ static struct ripng_interface *ri_new(struct interface *ifp) return ri; } +void ripng_interface_sync(struct interface *ifp) +{ + struct vrf *vrf; + + vrf = vrf_lookup_by_id(ifp->vrf_id); + if (vrf) { + struct ripng_interface *ri; + + ri = ifp->info; + if (ri) + ri->ripng = vrf->info; + } +} + static int ripng_if_new_hook(struct interface *ifp) { - ifp->info = ri_new(ifp); + ifp->info = ri_new(); + ripng_interface_sync(ifp); + return 0; } @@ -928,22 +964,25 @@ static int ripng_if_delete_hook(struct interface *ifp) /* Configuration write function for ripngd. */ static int interface_config_write(struct vty *vty) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct interface *ifp; + struct vrf *vrf; int write = 0; - FOR_ALL_INTERFACES (vrf, ifp) { - struct lyd_node *dnode; + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + struct interface *ifp; - dnode = yang_dnode_get( - running_config->dnode, - "/frr-interface:lib/interface[name='%s'][vrf='%s']", - ifp->name, vrf->name); - if (dnode == NULL) - continue; + FOR_ALL_INTERFACES (vrf, ifp) { + struct lyd_node *dnode; - write = 1; - nb_cli_show_dnode_cmds(vty, dnode, false); + dnode = yang_dnode_get( + running_config->dnode, + "/frr-interface:lib/interface[name='%s'][vrf='%s']", + ifp->name, vrf->name); + if (dnode == NULL) + continue; + + write = 1; + nb_cli_show_dnode_cmds(vty, dnode, false); + } } return write; diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index e7246efc43..37b163c5e4 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -46,7 +46,7 @@ struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}}; /* ripngd privileges */ -zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN}; struct zebra_privs_t ripngd_privs = { #if defined(FRR_USER) @@ -59,7 +59,7 @@ struct zebra_privs_t ripngd_privs = { .vty_group = VTY_GROUP, #endif .caps_p = _caps_p, - .cap_num_p = 2, + .cap_num_p = array_size(_caps_p), .cap_num_i = 0}; @@ -80,18 +80,9 @@ static void sighup(void) /* SIGINT handler. */ static void sigint(void) { - struct vrf *vrf; - zlog_notice("Terminating on signal"); - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - struct ripng *ripng; - - ripng = vrf->info; - if (ripng) - ripng_clean(ripng); - } - + ripng_vrf_terminate(); ripng_zebra_stop(); frr_fini(); exit(0); @@ -178,7 +169,7 @@ int main(int argc, char **argv) master = frr_init(); /* Library inits. */ - vrf_init(NULL, NULL, NULL, NULL, NULL); + ripng_vrf_init(); /* RIPngd inits. */ ripng_init(); diff --git a/ripngd/ripng_memory.c b/ripngd/ripng_memory.c index 0cb24052e6..f459566bed 100644 --- a/ripngd/ripng_memory.c +++ b/ripngd/ripng_memory.c @@ -27,6 +27,7 @@ DEFINE_MGROUP(RIPNGD, "ripngd") DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure") +DEFINE_MTYPE(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name") DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info") DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate") DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer") diff --git a/ripngd/ripng_memory.h b/ripngd/ripng_memory.h index a4102086c7..3dfc57b3ff 100644 --- a/ripngd/ripng_memory.h +++ b/ripngd/ripng_memory.h @@ -26,6 +26,7 @@ DECLARE_MGROUP(RIPNGD) DECLARE_MTYPE(RIPNG) +DECLARE_MTYPE(RIPNG_VRF_NAME) DECLARE_MTYPE(RIPNG_ROUTE) DECLARE_MTYPE(RIPNG_AGGREGATE) DECLARE_MTYPE(RIPNG_PEER) diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index a6700c8454..9784d0c200 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -44,25 +44,42 @@ static int ripngd_instance_create(enum nb_event event, { struct ripng *ripng; struct vrf *vrf; + const char *vrf_name; int socket; + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrf_name); + + /* + * Try to create a RIPng socket only if the VRF is enabled, otherwise + * create a disabled RIPng instance and wait for the VRF to be enabled. + */ switch (event) { case NB_EV_VALIDATE: break; case NB_EV_PREPARE: - socket = ripng_make_socket(); + if (!vrf || !vrf_is_enabled(vrf)) + break; + + socket = ripng_make_socket(vrf); if (socket < 0) return NB_ERR_RESOURCE; resource->fd = socket; break; case NB_EV_ABORT: + if (!vrf || !vrf_is_enabled(vrf)) + break; + socket = resource->fd; close(socket); break; case NB_EV_APPLY: - vrf = vrf_lookup_by_id(VRF_DEFAULT); - socket = resource->fd; - ripng = ripng_create(vrf, socket); + if (vrf && vrf_is_enabled(vrf)) + socket = resource->fd; + else + socket = -1; + + ripng = ripng_create(vrf_name, vrf, socket); yang_dnode_set_entry(dnode, ripng); break; } diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 9e8dd03cbc..913ac5191c 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -48,7 +48,7 @@ static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp, int count = 0; memset(&api, 0, sizeof(api)); - api.vrf_id = ripng->vrf_id; + api.vrf_id = ripng->vrf->vrf_id; api.type = ZEBRA_ROUTE_RIPNG; api.safi = SAFI_UNICAST; api.prefix = rp->p; @@ -58,7 +58,7 @@ static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp, if (count >= MULTIPATH_NUM) break; api_nh = &api.nexthops[count]; - api_nh->vrf_id = ripng->vrf_id; + api_nh->vrf_id = ripng->vrf->vrf_id; api_nh->gate.ipv6 = rinfo->nexthop; api_nh->ifindex = rinfo->ifindex; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; @@ -151,36 +151,38 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient, void ripng_redistribute_conf_update(struct ripng *ripng, int type) { zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, - ripng->vrf_id); + ripng->vrf->vrf_id); } 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, ripng->vrf_id); + AFI_IP6, type, 0, ripng->vrf->vrf_id); ripng_redistribute_withdraw(ripng, type); } int ripng_redistribute_check(struct ripng *ripng, int type) { - return vrf_bitmap_check(zclient->redist[AFI_IP6][type], ripng->vrf_id); + return vrf_bitmap_check(zclient->redist[AFI_IP6][type], + ripng->vrf->vrf_id); } 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], - ripng->vrf_id)) + ripng->vrf->vrf_id)) continue; if (zclient->sock > 0) zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, i, 0, - ripng->vrf_id); + ripng->vrf->vrf_id); - vrf_bitmap_unset(zclient->redist[AFI_IP6][i], ripng->vrf_id); + vrf_bitmap_unset(zclient->redist[AFI_IP6][i], + ripng->vrf->vrf_id); } } @@ -191,13 +193,37 @@ void ripng_redistribute_write(struct vty *vty, struct ripng *ripng) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == zclient->redist_default || !vrf_bitmap_check(zclient->redist[AFI_IP6][i], - ripng->vrf_id)) + ripng->vrf->vrf_id)) continue; vty_out(vty, " %s", zebra_route_string(i)); } } +void ripng_zebra_vrf_register(struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("%s: register VRF %s(%u) to zebra", __func__, + vrf->name, vrf->vrf_id); + + zclient_send_reg_requests(zclient, vrf->vrf_id); +} + +void ripng_zebra_vrf_deregister(struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__, + vrf->name, vrf->vrf_id); + + zclient_send_dereg_requests(zclient, vrf->vrf_id); +} + static void ripng_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); @@ -217,6 +243,7 @@ void zebra_init(struct thread_master *master) zclient->interface_delete = ripng_interface_delete; zclient->interface_address_add = ripng_interface_address_add; zclient->interface_address_delete = ripng_interface_address_delete; + zclient->interface_vrf_update = ripng_interface_vrf_update; zclient->redistribute_route_add = ripng_zebra_read_route; zclient->redistribute_route_del = ripng_zebra_read_route; } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 292b3da6ab..951c73bc45 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -52,9 +52,22 @@ static void ripng_distribute_update(struct distribute_ctx *ctx, /* 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 *); +/* 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 { @@ -91,18 +104,30 @@ struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo) } /* Create ripng socket. */ -int ripng_make_socket(void) +int ripng_make_socket(struct vrf *vrf) { int ret; int sock; struct sockaddr_in6 ripaddr; + const char *vrf_dev = NULL; - sock = socket(AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) { - flog_err_sys(EC_LIB_SOCKET, "Can't make ripng socket"); - return sock; + /* Make datagram socket. */ + if (vrf->vrf_id != VRF_DEFAULT) + vrf_dev = vrf->name; + frr_elevate_privs(&ripngd_privs) + { + sock = vrf_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, + vrf->vrf_id, vrf_dev); + if (sock < 0) { + flog_err_sys(EC_LIB_SOCKET, + "Cannot create UDP socket: %s", + safe_strerror(errno)); + return -1; + } } + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); setsockopt_so_recvbuf(sock, 8096); ret = setsockopt_ipv6_pktinfo(sock, 1); if (ret < 0) @@ -631,7 +656,7 @@ static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p, } /* All interface filter check. */ - dist = distribute_lookup(ripng->distribute_ctx, NULL); + dist = distribute_lookup(ri->ripng->distribute_ctx, NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup(AFI_IP6, @@ -968,13 +993,13 @@ void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type, zlog_debug( "Redistribute new prefix %s/%d on the interface %s", inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, ripng->vrf_id)); + ifindex2ifname(ifindex, ripng->vrf->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, ripng->vrf_id)); + ifindex2ifname(ifindex, ripng->vrf->vrf_id)); } ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); @@ -1020,8 +1045,9 @@ void ripng_redistribute_delete(struct ripng *ripng, int type, int sub_type, "infinity metric [delete]", inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, - ripng->vrf_id)); + ifindex2ifname( + ifindex, + ripng->vrf->vrf_id)); ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); } @@ -1062,8 +1088,9 @@ void ripng_redistribute_withdraw(struct ripng *ripng, int type) "Poisone %s/%d on the interface %s [withdraw]", inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex, - ripng->vrf_id)); + ifindex2ifname( + rinfo->ifindex, + ripng->vrf->vrf_id)); } ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0); @@ -1313,27 +1340,29 @@ static int ripng_read(struct thread *thread) STREAM_SIZE(ripng->ibuf), &from, &ifindex, &hoplimit); if (len < 0) { - zlog_warn("RIPng recvfrom failed: %s.", safe_strerror(errno)); + zlog_warn("RIPng recvfrom failed (VRF %s): %s.", + ripng->vrf_name, safe_strerror(errno)); return len; } /* Check RTE boundary. RTE size (Packet length - RIPng header size (4)) must be multiple size of one RTE size (20). */ if (((len - 4) % 20) != 0) { - zlog_warn("RIPng invalid packet size %d from %s", len, - inet6_ntoa(from.sin6_addr)); + zlog_warn("RIPng invalid packet size %d from %s (VRF %s)", len, + inet6_ntoa(from.sin6_addr), ripng->vrf_name); ripng_peer_bad_packet(ripng, &from); return 0; } packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf); - ifp = if_lookup_by_index(ifindex, ripng->vrf_id); + ifp = if_lookup_by_index(ifindex, ripng->vrf->vrf_id); /* RIPng packet received. */ if (IS_RIPNG_DEBUG_EVENT) - zlog_debug("RIPng packet received from %s port %d on %s", - inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port), - ifp ? ifp->name : "unknown"); + zlog_debug( + "RIPng packet received from %s port %d on %s (VRF %s)", + inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port), + ifp ? ifp->name : "unknown", ripng->vrf_name); /* Logging before packet checking. */ if (IS_RIPNG_DEBUG_RECV) @@ -1341,16 +1370,17 @@ static int ripng_read(struct thread *thread) /* Packet comes from unknown interface. */ if (ifp == NULL) { - zlog_warn("RIPng packet comes from unknown interface %d", - ifindex); + zlog_warn( + "RIPng packet comes from unknown interface %d (VRF %s)", + ifindex, ripng->vrf_name); return 0; } /* Packet version mismatch checking. */ if (packet->version != ripng->version) { zlog_warn( - "RIPng packet version %d doesn't fit to my version %d", - packet->version, ripng->version); + "RIPng packet version %d doesn't fit to my version %d (VRF %s)", + packet->version, ripng->version, ripng->vrf_name); ripng_peer_bad_packet(ripng, &from); return 0; } @@ -1364,7 +1394,8 @@ static int ripng_read(struct thread *thread) ripng_response_process(packet, len, &from, ifp, hoplimit); break; default: - zlog_warn("Invalid RIPng command %d", packet->command); + zlog_warn("Invalid RIPng command %d (VRF %s)", packet->command, + ripng->vrf_name); ripng_peer_bad_packet(ripng, &from); break; } @@ -1394,7 +1425,6 @@ static void ripng_clear_changed_flag(struct ripng *ripng) static int ripng_update(struct thread *t) { struct ripng *ripng = THREAD_ARG(t); - struct vrf *vrf = vrf_lookup_by_id(ripng->vrf_id); struct interface *ifp; struct ripng_interface *ri; @@ -1406,7 +1436,7 @@ static int ripng_update(struct thread *t) zlog_debug("RIPng update timer expired!"); /* Supply routes to each interface. */ - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (ripng->vrf, ifp) { ri = ifp->info; if (if_is_loopback(ifp) || !if_is_up(ifp)) @@ -1465,7 +1495,6 @@ static int ripng_triggered_interval(struct thread *t) int ripng_triggered_update(struct thread *t) { 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; @@ -1485,7 +1514,7 @@ int ripng_triggered_update(struct thread *t) /* Split Horizon processing is done when generating triggered updates as well as normal updates (see section 2.6). */ - FOR_ALL_INTERFACES (vrf, ifp) { + FOR_ALL_INTERFACES (ripng->vrf, ifp) { ri = ifp->info; if (if_is_loopback(ifp) || !if_is_up(ifp)) @@ -1811,14 +1840,23 @@ struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id) return vrf->info; } +struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name) +{ + struct ripng ripng; + + ripng.vrf_name = (char *)vrf_name; + + return RB_FIND(ripng_instance_head, &ripng_instances, &ripng); +} + /* Create new RIPng instance and set it to global variable. */ -struct ripng *ripng_create(struct vrf *vrf, int socket) +struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf, int socket) { struct ripng *ripng; - struct interface *ifp; /* Allocaste RIPng instance. */ ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng)); + ripng->vrf_name = XSTRDUP(MTYPE_RIPNG_VRF_NAME, vrf_name); /* Default version and timer values. */ ripng->version = RIPNG_V1; @@ -1850,31 +1888,23 @@ struct ripng *ripng_create(struct vrf *vrf, int socket) (int (*)(void *, void *))offset_list_cmp; ripng->offset_list_master->del = (void (*)(void *))ripng_offset_list_del; - - /* Distribute list install. */ - ripng->distribute_ctx = distribute_list_ctx_create( - vrf_lookup_by_id(VRF_DEFAULT)); + ripng->distribute_ctx = distribute_list_ctx_create(vrf); distribute_list_add_hook(ripng->distribute_ctx, ripng_distribute_update); distribute_list_delete_hook(ripng->distribute_ctx, ripng_distribute_update); - /* Make socket. */ - ripng->sock = socket; - /* Threads. */ - ripng_event(ripng, RIPNG_READ, ripng->sock); - ripng_event(ripng, RIPNG_UPDATE_EVENT, 1); - /* 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; + /* 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; } + RB_INSERT(ripng_instance_head, &ripng_instances, ripng); + return ripng; } @@ -2003,10 +2033,11 @@ static char *ripng_route_subtype_print(struct ripng_info *rinfo) DEFUN (show_ipv6_ripng, show_ipv6_ripng_cmd, - "show ipv6 ripng", + "show ipv6 ripng [vrf NAME]", SHOW_STR IPV6_STR - "Show RIPng routes\n") + "Show RIPng routes\n" + VRF_CMD_HELP_STR) { struct ripng *ripng; struct agg_node *rp; @@ -2016,10 +2047,23 @@ DEFUN (show_ipv6_ripng, struct list *list = NULL; struct listnode *listnode = NULL; int len; + const char *vrf_name; + int idx = 0; - ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT); - if (!ripng) + if (argv_find(argv, argc, "vrf", &idx)) + vrf_name = argv[idx + 1]->arg; + else + vrf_name = VRF_DEFAULT_NAME; + + ripng = ripng_lookup_by_vrf_name(vrf_name); + if (!ripng) { + vty_out(vty, "%% RIPng instance not found\n"); return CMD_SUCCESS; + } + if (!ripng->enabled) { + vty_out(vty, "%% RIPng instance is disabled\n"); + return CMD_SUCCESS; + } /* Header of display. */ vty_out(vty, @@ -2079,8 +2123,9 @@ DEFUN (show_ipv6_ripng, && (rinfo->sub_type == RIPNG_ROUTE_RTE)) { len = vty_out( vty, "%s", - ifindex2ifname(rinfo->ifindex, - ripng->vrf_id)); + ifindex2ifname( + rinfo->ifindex, + ripng->vrf->vrf_id)); } else if (rinfo->metric == RIPNG_METRIC_INFINITY) { len = vty_out(vty, "kill"); @@ -2114,19 +2159,32 @@ DEFUN (show_ipv6_ripng, DEFUN (show_ipv6_ripng_status, show_ipv6_ripng_status_cmd, - "show ipv6 ripng status", + "show ipv6 ripng [vrf NAME] status", SHOW_STR IPV6_STR "Show RIPng routes\n" + VRF_CMD_HELP_STR "IPv6 routing protocol process parameters and statistics\n") { struct ripng *ripng; - struct vrf *vrf; struct interface *ifp; + const char *vrf_name; + int idx = 0; - ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT); - if (!ripng) + if (argv_find(argv, argc, "vrf", &idx)) + vrf_name = argv[idx + 1]->arg; + else + vrf_name = VRF_DEFAULT_NAME; + + ripng = ripng_lookup_by_vrf_name(vrf_name); + if (!ripng) { + vty_out(vty, "%% RIPng instance not found\n"); return CMD_SUCCESS; + } + if (!ripng->enabled) { + vty_out(vty, "%% RIPng instance is disabled\n"); + return CMD_SUCCESS; + } vty_out(vty, "Routing Protocol is \"RIPng\"\n"); vty_out(vty, " Sending updates every %u seconds with +/-50%%,", @@ -2155,8 +2213,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) { + FOR_ALL_INTERFACES (ripng->vrf, ifp) { struct ripng_interface *ri; ri = ifp->info; @@ -2350,21 +2407,25 @@ void ripng_ecmp_disable(struct ripng *ripng) /* 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) { - struct ripng *ripng; + RB_FOREACH(ripng, ripng_instance_head, &ripng_instances) { + char xpath[XPATH_MAXLEN]; + struct lyd_node *dnode; + + snprintf(xpath, sizeof(xpath), + "/frr-ripngd:ripngd/instance[vrf='%s']", + ripng->vrf_name); + + dnode = yang_dnode_get(running_config->dnode, xpath); + assert(dnode); nb_cli_show_dnode_cmds(vty, dnode, false); - ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT); - if (ripng) { - config_write_distribute(vty, ripng->distribute_ctx); + config_write_distribute(vty, ripng->distribute_ctx); + if (strmatch(ripng->vrf_name, VRF_DEFAULT_NAME)) config_write_if_rmap(vty); - } write = 1; } @@ -2385,10 +2446,10 @@ static void ripng_distribute_update(struct distribute_ctx *ctx, struct access_list *alist; struct prefix_list *plist; - if (!dist->ifname) + if (!ctx->vrf || !dist->ifname) return; - ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id); if (ifp == NULL) return; @@ -2437,6 +2498,8 @@ static void ripng_distribute_update(struct distribute_ctx *ctx, void ripng_distribute_update_interface(struct interface *ifp) { + struct ripng_interface *ri = ifp->info; + struct ripng *ripng = ri->ripng; struct distribute *dist; if (!ripng) @@ -2464,56 +2527,8 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused) /* delete all the added ripng routes. */ void ripng_clean(struct ripng *ripng) { - struct vrf *vrf; - struct interface *ifp; - struct agg_node *rp; - - /* Clear RIPng routes */ - for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { - struct ripng_aggregate *aggregate; - struct list *list; - - if ((list = rp->info) != NULL) { - struct ripng_info *rinfo; - struct listnode *listnode; - - rinfo = listgetdata(listhead(list)); - if (ripng_route_rte(rinfo)) - ripng_zebra_ipv6_delete(ripng, 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; - } + if (ripng->enabled) + ripng_instance_disable(ripng); for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) if (ripng->route_map[i].name) @@ -2535,16 +2550,8 @@ void ripng_clean(struct ripng *ripng) 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; - } - + RB_REMOVE(ripng_instance_head, &ripng_instances, ripng); + XFREE(MTYPE_RIPNG_VRF_NAME, ripng->vrf_name); XFREE(MTYPE_RIPNG, ripng); } @@ -2611,6 +2618,181 @@ static void ripng_routemap_update(const char *unused) ripng_routemap_update_redistribute(ripng); } +/* Link RIPng instance to VRF. */ +static void ripng_vrf_link(struct ripng *ripng, struct vrf *vrf) +{ + struct interface *ifp; + + ripng->vrf = vrf; + ripng->distribute_ctx->vrf = vrf; + vrf->info = ripng; + + FOR_ALL_INTERFACES (vrf, ifp) + ripng_interface_sync(ifp); +} + +/* Unlink RIPng instance from VRF. */ +static void ripng_vrf_unlink(struct ripng *ripng, struct vrf *vrf) +{ + struct interface *ifp; + + ripng->vrf = NULL; + ripng->distribute_ctx->vrf = NULL; + vrf->info = NULL; + + FOR_ALL_INTERFACES (vrf, ifp) + ripng_interface_sync(ifp); +} + +static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf, + int sock) +{ + ripng->sock = sock; + + ripng_vrf_link(ripng, vrf); + ripng->enabled = true; + + /* Create read and timer thread. */ + ripng_event(ripng, RIPNG_READ, ripng->sock); + ripng_event(ripng, RIPNG_UPDATE_EVENT, 1); + + ripng_zebra_vrf_register(vrf); +} + +static void ripng_instance_disable(struct ripng *ripng) +{ + struct vrf *vrf = ripng->vrf; + struct agg_node *rp; + + /* Clear RIPng routes */ + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { + struct ripng_aggregate *aggregate; + struct list *list; + + if ((list = rp->info) != NULL) { + struct ripng_info *rinfo; + struct listnode *listnode; + + rinfo = listgetdata(listhead(list)); + if (ripng_route_rte(rinfo)) + ripng_zebra_ipv6_delete(ripng, 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; + } + + /* Clear existing peers. */ + list_delete_all_node(ripng->peer_list); + + ripng_zebra_vrf_deregister(vrf); + + ripng_vrf_unlink(ripng, vrf); + ripng->enabled = false; +} + +static int ripng_vrf_new(struct vrf *vrf) +{ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name, + vrf->vrf_id); + + return 0; +} + +static int ripng_vrf_delete(struct vrf *vrf) +{ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name, + vrf->vrf_id); + + return 0; +} + +static int ripng_vrf_enable(struct vrf *vrf) +{ + struct ripng *ripng; + int socket; + + ripng = ripng_lookup_by_vrf_name(vrf->name); + if (!ripng || ripng->enabled) + return 0; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name, + vrf->vrf_id); + + /* Activate the VRF RIPng instance. */ + if (!ripng->enabled) { + socket = ripng_make_socket(vrf); + if (socket < 0) + return -1; + + ripng_instance_enable(ripng, vrf, socket); + } + + return 0; +} + +static int ripng_vrf_disable(struct vrf *vrf) +{ + struct ripng *ripng; + + ripng = ripng_lookup_by_vrf_name(vrf->name); + if (!ripng || !ripng->enabled) + return 0; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name, + vrf->vrf_id); + + /* Deactivate the VRF RIPng instance. */ + if (ripng->enabled) + ripng_instance_disable(ripng); + + return 0; +} + +void ripng_vrf_init(void) +{ + vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable, + ripng_vrf_delete, NULL); +} + +void ripng_vrf_terminate(void) +{ + vrf_terminate(); +} + /* Initialize ripng structure and set commands. */ void ripng_init() { diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 95039bf579..e9894dd4cf 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -89,8 +89,16 @@ /* RIPng structure. */ struct ripng { - /* VRF ID. */ - vrf_id_t vrf_id; + RB_ENTRY(ripng) entry; + + /* VRF this routing instance is associated with. */ + char *vrf_name; + + /* VRF backpointer (might be NULL if the VRF doesn't exist). */ + struct vrf *vrf; + + /* Status of the routing instance. */ + bool enabled; /* RIPng socket. */ int sock; @@ -152,6 +160,8 @@ struct ripng { /* For distribute-list container */ struct distribute_ctx *distribute_ctx; }; +RB_HEAD(ripng_instance_head, ripng); +RB_PROTOTYPE(ripng_instance_head, ripng, entry, ripng_instance_compare) /* Routing table entry. */ struct rte { @@ -378,6 +388,8 @@ extern int ripng_passive_interface_unset(struct ripng *ripng, 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_zebra_vrf_register(struct vrf *vrf); +extern void ripng_zebra_vrf_deregister(struct vrf *vrf); extern void ripng_terminate(void); /* zclient_init() is done by ripng_zebra.c:zebra_init() */ extern void zebra_init(struct thread_master *); @@ -459,10 +471,15 @@ extern int ripng_interface_address_add(int command, struct zclient *, zebra_size_t, vrf_id_t); extern int ripng_interface_address_delete(int command, struct zclient *, zebra_size_t, vrf_id_t); +extern int ripng_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id); +extern void ripng_interface_sync(struct interface *ifp); 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 struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name); +extern struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf, + int socket); +extern int ripng_make_socket(struct vrf *vrf); extern int ripng_network_write(struct vty *vty, struct ripng *ripng); extern struct ripng_info *ripng_ecmp_add(struct ripng *ripng, @@ -472,6 +489,9 @@ extern struct ripng_info *ripng_ecmp_replace(struct ripng *ripng, extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng, struct ripng_info *rinfo); +extern void ripng_vrf_init(void); +extern void ripng_vrf_terminate(void); + /* Northbound. */ extern void ripng_cli_init(void); extern const struct frr_yang_module_info frr_ripngd_info; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 11be03363c..41bc50670f 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1526,8 +1526,8 @@ DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]", return CMD_SUCCESS; } -DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng", - ROUTER_STR "RIPng\n") +DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]", + ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR) { vty->node = RIPNG_NODE; return CMD_SUCCESS; diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index 0cc5f18a5f..5d6d61564f 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -33,13 +33,18 @@ module frr-ripngd { container ripngd { /* - * Global configuration data + * Routing instance configuration. */ - container instance { - presence "Present if the RIPng protocol is enabled."; + list instance { + key "vrf"; description "RIPng routing instance."; + leaf vrf { + type string; + description + "VRF name."; + } leaf allow-ecmp { type boolean; default "false"; From 80cf4e451db10daf78d277f36a97ece1615f0450 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 31/36] ripngd: make YANG operational-data VRF aware too Move the "state" container into the "instance" list and adapt the code accordingly. Signed-off-by: Renato Westphal --- ripngd/ripng_northbound.c | 189 +++++++++++++++++++++----------------- ripngd/ripngd.h | 1 + yang/frr-ripngd.yang | 134 +++++++++++++-------------- 3 files changed, 173 insertions(+), 151 deletions(-) diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index 9784d0c200..3a1d528375 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -101,6 +101,39 @@ static int ripngd_instance_delete(enum nb_event event, return NB_OK; } +static const void *ripngd_instance_get_next(const void *parent_list_entry, + const void *list_entry) +{ + const struct ripng *ripng = list_entry; + + if (list_entry == NULL) + ripng = RB_MIN(ripng_instance_head, &ripng_instances); + else + ripng = RB_NEXT(ripng_instance_head, (struct ripng *)ripng); + + return ripng; +} + +static int ripngd_instance_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct ripng *ripng = list_entry; + + keys->num = 1; + strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0])); + + return NB_OK; +} + +static const void * +ripngd_instance_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + const char *vrf_name = keys->key[0]; + + return ripng_lookup_by_vrf_name(vrf_name); +} + /* * XPath: /frr-ripngd:ripngd/instance/allow-ecmp */ @@ -655,19 +688,15 @@ ripngd_instance_timers_update_interval_modify(enum nb_event event, } /* - * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor */ static const void * -ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry, - const void *list_entry) +ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, + const void *list_entry) { - struct ripng *ripng; + const struct ripng *ripng = parent_list_entry; struct listnode *node; - ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT); - if (!ripng) - return NULL; - if (list_entry == NULL) node = listhead(ripng->peer_list); else @@ -676,8 +705,9 @@ ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry, return node; } -static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry, - struct yang_list_keys *keys) +static int +ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry, + struct yang_list_keys *keys) { const struct listnode *node = list_entry; const struct ripng_peer *peer = listgetdata(node); @@ -689,21 +719,16 @@ static int ripngd_state_neighbors_neighbor_get_keys(const void *list_entry, return NB_OK; } -static const void * -ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) +static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys) { - struct ripng *ripng; + const struct ripng *ripng = parent_list_entry; 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; - for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) { if (IPV6_ADDR_SAME(&peer->addr, &address)) return node; @@ -713,11 +738,11 @@ ripngd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry, } /* - * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address */ static struct yang_data * -ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_neighbors_neighbor_address_get_elem( + const char *xpath, const void *list_entry) { const struct listnode *node = list_entry; const struct ripng_peer *peer = listgetdata(node); @@ -726,21 +751,21 @@ ripngd_state_neighbors_neighbor_address_get_elem(const char *xpath, } /* - * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/last-update + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update */ static struct yang_data * -ripngd_state_neighbors_neighbor_last_update_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_neighbors_neighbor_last_update_get_elem( + const char *xpath, const void *list_entry) { /* TODO: yang:date-and-time is tricky */ return NULL; } /* - * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd */ static struct yang_data * -ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem( +ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( const char *xpath, const void *list_entry) { const struct listnode *node = list_entry; @@ -750,11 +775,11 @@ ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem( } /* - * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd */ static struct yang_data * -ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( + const char *xpath, const void *list_entry) { const struct listnode *node = list_entry; const struct ripng_peer *peer = listgetdata(node); @@ -763,19 +788,15 @@ ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath, } /* - * XPath: /frr-ripngd:ripngd/state/routes/route + * XPath: /frr-ripngd:ripngd/instance/state/routes/route */ static const void * -ripngd_state_routes_route_get_next(const void *parent_list_entry, - const void *list_entry) +ripngd_instance_state_routes_route_get_next(const void *parent_list_entry, + const void *list_entry) { - struct ripng *ripng; + const struct ripng *ripng = parent_list_entry; struct agg_node *rn; - ripng = ripng_lookup_by_vrf_id(VRF_DEFAULT); - if (ripng == NULL) - return NULL; - if (list_entry == NULL) rn = agg_route_top(ripng->table); else @@ -786,8 +807,9 @@ ripngd_state_routes_route_get_next(const void *parent_list_entry, return rn; } -static int ripngd_state_routes_route_get_keys(const void *list_entry, - struct yang_list_keys *keys) +static int +ripngd_instance_state_routes_route_get_keys(const void *list_entry, + struct yang_list_keys *keys) { const struct agg_node *rn = list_entry; @@ -797,20 +819,15 @@ static int ripngd_state_routes_route_get_keys(const void *list_entry, return NB_OK; } -static const void * -ripngd_state_routes_route_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) +static const void *ripngd_instance_state_routes_route_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys) { - struct ripng *ripng; + const struct ripng *ripng = parent_list_entry; 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; @@ -821,11 +838,11 @@ ripngd_state_routes_route_lookup_entry(const void *parent_list_entry, } /* - * XPath: /frr-ripngd:ripngd/state/routes/route/prefix + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix */ static struct yang_data * -ripngd_state_routes_route_prefix_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath, + const void *list_entry) { const struct agg_node *rn = list_entry; const struct ripng_info *rinfo = listnode_head(rn->info); @@ -834,11 +851,11 @@ ripngd_state_routes_route_prefix_get_elem(const char *xpath, } /* - * XPath: /frr-ripngd:ripngd/state/routes/route/next-hop + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop */ static struct yang_data * -ripngd_state_routes_route_next_hop_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath, + const void *list_entry) { const struct agg_node *rn = list_entry; const struct ripng_info *rinfo = listnode_head(rn->info); @@ -847,25 +864,26 @@ ripngd_state_routes_route_next_hop_get_elem(const char *xpath, } /* - * XPath: /frr-ripngd:ripngd/state/routes/route/interface + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface */ static struct yang_data * -ripngd_state_routes_route_interface_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_routes_route_interface_get_elem(const char *xpath, + const void *list_entry) { const struct agg_node *rn = list_entry; const struct ripng_info *rinfo = listnode_head(rn->info); + const struct ripng *ripng = ripng_info_get_instance(rinfo); return yang_data_new_string( - xpath, ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); + xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id)); } /* - * XPath: /frr-ripngd:ripngd/state/routes/route/metric + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric */ static struct yang_data * -ripngd_state_routes_route_metric_get_elem(const char *xpath, - const void *list_entry) +ripngd_instance_state_routes_route_metric_get_elem(const char *xpath, + const void *list_entry) { const struct agg_node *rn = list_entry; const struct ripng_info *rinfo = listnode_head(rn->info); @@ -950,6 +968,9 @@ const struct frr_yang_module_info frr_ripngd_info = { .xpath = "/frr-ripngd:ripngd/instance", .cbs.create = ripngd_instance_create, .cbs.delete = 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, }, { @@ -1046,48 +1067,48 @@ const struct frr_yang_module_info frr_ripngd_info = { .cbs.modify = ripngd_instance_timers_update_interval_modify, }, { - .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor", - .cbs.get_next = ripngd_state_neighbors_neighbor_get_next, - .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys, - .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry, + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor", + .cbs.get_next = ripngd_instance_state_neighbors_neighbor_get_next, + .cbs.get_keys = ripngd_instance_state_neighbors_neighbor_get_keys, + .cbs.lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry, }, { - .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address", - .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address", + .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update", - .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update", + .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd", - .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd", + .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd", - .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd", + .cbs.get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/routes/route", - .cbs.get_next = ripngd_state_routes_route_get_next, - .cbs.get_keys = ripngd_state_routes_route_get_keys, - .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry, + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route", + .cbs.get_next = ripngd_instance_state_routes_route_get_next, + .cbs.get_keys = ripngd_instance_state_routes_route_get_keys, + .cbs.lookup_entry = ripngd_instance_state_routes_route_lookup_entry, }, { - .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix", - .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix", + .cbs.get_elem = ripngd_instance_state_routes_route_prefix_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop", - .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop", + .cbs.get_elem = ripngd_instance_state_routes_route_next_hop_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/routes/route/interface", - .cbs.get_elem = ripngd_state_routes_route_interface_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface", + .cbs.get_elem = ripngd_instance_state_routes_route_interface_get_elem, }, { - .xpath = "/frr-ripngd:ripngd/state/routes/route/metric", - .cbs.get_elem = ripngd_state_routes_route_metric_get_elem, + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric", + .cbs.get_elem = ripngd_instance_state_routes_route_metric_get_elem, }, { .xpath = "/frr-ripngd:clear-ripng-route", diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index e9894dd4cf..d6c4394c6d 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -372,6 +372,7 @@ struct ripng_offset_list { /* Extern variables. */ extern struct zebra_privs_t ripngd_privs; extern struct thread_master *master; +extern struct ripng_instance_head ripng_instances; /* Prototypes. */ extern void ripng_init(void); diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index 5d6d61564f..6f7773f8ba 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -199,82 +199,82 @@ module frr-ripngd { "Interval at which RIPng updates are sent."; } } - } - /* - * Operational data. - */ - container state { - config false; - description - "Operational data."; - - container neighbors { + /* + * Operational data. + */ + container state { + config false; description - "Neighbor information."; - list neighbor { - key "address"; + "Operational data."; + + container neighbors { description - "A RIPng neighbor."; - leaf address { - type inet:ipv6-address; + "Neighbor information."; + list neighbor { + key "address"; description - "IPv6 address that a RIPng neighbor is using as its - source address."; - } - leaf last-update { - type yang:date-and-time; - description - "The time when the most recent RIPng update was - received from this neighbor."; - } - leaf bad-packets-rcvd { - type yang:counter32; - description - "The number of RIPng invalid packets received from - this neighbor which were subsequently discarded - for any reason (e.g. a version 0 packet, or an - unknown command type)."; - } - leaf bad-routes-rcvd { - type yang:counter32; - description - "The number of routes received from this neighbor, - in valid RIPng packets, which were ignored for any - reason (e.g. unknown address family, or invalid - metric)."; + "A RIPng neighbor."; + leaf address { + type inet:ipv6-address; + description + "IPv6 address that a RIPng neighbor is using as its + source address."; + } + leaf last-update { + type yang:date-and-time; + description + "The time when the most recent RIPng update was + received from this neighbor."; + } + leaf bad-packets-rcvd { + type yang:counter32; + description + "The number of RIPng invalid packets received from + this neighbor which were subsequently discarded + for any reason (e.g. a version 0 packet, or an + unknown command type)."; + } + leaf bad-routes-rcvd { + type yang:counter32; + description + "The number of routes received from this neighbor, + in valid RIPng packets, which were ignored for any + reason (e.g. unknown address family, or invalid + metric)."; + } } } - } - container routes { - description - "Route information."; - list route { - key "prefix"; + container routes { description - "A RIPng IPv6 route."; - leaf prefix { - type inet:ipv6-prefix; + "Route information."; + list route { + key "prefix"; description - "IPv6 address and prefix length, in the format - specified in RFC6991."; - } - leaf next-hop { - type inet:ipv6-address; - description - "Next hop IPv6 address."; - } - leaf interface { - type string; - description - "The interface that the route uses."; - } - leaf metric { - type uint8 { - range "0..16"; + "A RIPng IPv6 route."; + leaf prefix { + type inet:ipv6-prefix; + description + "IPv6 address and prefix length, in the format + specified in RFC6991."; + } + leaf next-hop { + type inet:ipv6-address; + description + "Next hop IPv6 address."; + } + leaf interface { + type string; + description + "The interface that the route uses."; + } + leaf metric { + type uint8 { + range "0..16"; + } + description + "Route metric."; } - description - "Route metric."; } } } From c5b2b5f65cd76c76f9d1ed1a219b33469f1e8524 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 32/36] ripngd: add vrf input parameter to the "clear-ripng-route" RPC Description of the new parameter (adapted from the ietf-rip module): "VRF name identifying a specific RIPng instance. This leaf is optional for the rpc. If it is specified, the rpc will clear all routes in the specified RIPng instance; if it is not specified, the rpc will clear all routes in all RIPng instances."; Signed-off-by: Renato Westphal --- ripngd/ripng_cli.c | 18 ++++++++++++++--- ripngd/ripng_northbound.c | 42 ++++++++++++++++++++++++++++++--------- yang/frr-ripngd.yang | 13 ++++++++++++ 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index c89832d51d..804fa8dea6 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -478,12 +478,24 @@ void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode, */ DEFPY (clear_ipv6_rip, clear_ipv6_rip_cmd, - "clear ipv6 ripng", + "clear ipv6 ripng [vrf WORD]", CLEAR_STR IPV6_STR - "Clear IPv6 RIP database\n") + "Clear IPv6 RIP database\n" + VRF_CMD_HELP_STR) { - return nb_cli_rpc("/frr-ripngd:clear-ripng-route", NULL, NULL); + struct list *input; + + input = list_new(); + if (vrf) { + struct yang_data *yang_vrf; + + yang_vrf = yang_data_new( + "/frr-ripngd:clear-ripng-route/input/vrf", vrf); + listnode_add(input, yang_vrf); + } + + return nb_cli_rpc("/frr-ripngd:clear-ripng-route", input, NULL); } void ripng_cli_init(void) diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index 3a1d528375..4b15a3aef7 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -32,6 +32,7 @@ #include "libfrr.h" #include "ripngd/ripngd.h" +#include "ripngd/ripng_debug.h" #include "ripngd/ripng_route.h" #include "ripngd/ripng_cli.h" @@ -894,21 +895,20 @@ ripngd_instance_state_routes_route_metric_get_elem(const char *xpath, /* * XPath: /frr-ripngd:clear-ripng-route */ -static int clear_ripng_route_rpc(const char *xpath, const struct list *input, - struct list *output) +static void clear_ripng_route(struct ripng *ripng) { - 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; + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("Clearing all RIPng routes (VRF %s)", + ripng->vrf_name); /* Clear received RIPng routes */ for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { + struct list *list; + struct listnode *listnode; + struct ripng_info *rinfo; + list = rp->info; if (list == NULL) continue; @@ -935,6 +935,30 @@ static int clear_ripng_route_rpc(const char *xpath, const struct list *input, agg_unlock_node(rp); } } +} + +static int clear_ripng_route_rpc(const char *xpath, const struct list *input, + struct list *output) +{ + struct ripng *ripng; + struct yang_data *yang_vrf; + + yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf"); + if (yang_vrf) { + ripng = ripng_lookup_by_vrf_name(yang_vrf->value); + if (ripng) + clear_ripng_route(ripng); + } else { + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + ripng = vrf->info; + if (!ripng) + continue; + + clear_ripng_route(ripng); + } + } return NB_OK; } diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index 6f7773f8ba..b341b438a4 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -322,5 +322,18 @@ module frr-ripngd { description "Clears RIPng routes from the IPv6 routing table and routes redistributed into the RIPng protocol."; + + input { + leaf vrf { + type string; + description + "VRF name identifying a specific RIPng instance. + This leaf is optional for the rpc. + If it is specified, the rpc will clear all routes in the + specified RIPng instance; + if it is not specified, the rpc will clear all routes in + all RIPng instances."; + } + } } } From 64dac4ffb9316ab51754822713c1bab6444491ac Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 33/36] ripd: fix unsetting of authentication password Regression introduced by commit a6233bfc. Signed-off-by: Renato Westphal --- ripd/rip_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 6e5c01b6db..149b30b5d4 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -915,7 +915,7 @@ DEFPY (no_ip_rip_authentication_string, "Authentication string\n" "Authentication string\n") { - nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DELETE, NULL); return nb_cli_apply_changes(vty, "./frr-ripd:rip"); From f9120f719ac2433dd9f168eed97e7b71ea38125e Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 4 Jan 2019 19:08:10 -0200 Subject: [PATCH 34/36] ripd, ripngd: change how we keep track of redistribution configuration ripd and ripngd were leveraging the zclient code to keep track of the redistribute configuration, which is what most daemons do. The problem, however, is that the zclient code uses VRF IDs to identify VRFs, and VRF IDs are unknown until a VRF is enabled (information received from zebra). This means we can't configure a redistribute command on a RIP instance when the corresponding VRF is disabled (doing so leads to a null-dereference crash right now in both ripd and ripngd). To fix this, change the rip/ripng data structures so that they keep track of the full redistribute configuration and not only the route-map and metric associated to each command. This is similar to what bgpd and ospfd are doing to solve the same problem. In the future the zclient code and all daemons need to be refactored to consolidate the handling of redistribute configuration in a single place to reduce code duplication. One of the most important changes to do is to use VRF names and not VRF IDs to identify VRFs. Signed-off-by: Renato Westphal --- ripd/rip_northbound.c | 48 ++++++++++++++++++++++++++++----------- ripd/rip_zebra.c | 28 +++++++++++++---------- ripd/ripd.c | 26 ++++++++++++--------- ripd/ripd.h | 14 ++++++++---- ripngd/ripng_northbound.c | 48 ++++++++++++++++++++++++++++----------- ripngd/ripng_zebra.c | 29 ++++++++++++----------- ripngd/ripngd.c | 31 +++++++++++++++---------- ripngd/ripngd.h | 14 ++++++++---- 8 files changed, 154 insertions(+), 84 deletions(-) diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index d2360c470c..13520d11de 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -637,6 +637,17 @@ static int ripd_instance_redistribute_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + struct rip *rip; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = yang_dnode_get_entry(dnode, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + rip->redist[type].enabled = true; + return NB_OK; } @@ -652,7 +663,17 @@ static int ripd_instance_redistribute_delete(enum nb_event event, rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - rip_redistribute_conf_delete(rip, type); + rip->redist[type].enabled = false; + if (rip->redist[type].route_map.name) { + free(rip->redist[type].route_map.name); + rip->redist[type].route_map.name = NULL; + rip->redist[type].route_map.map = NULL; + } + rip->redist[type].metric_config = false; + rip->redist[type].metric = 0; + + if (rip->enabled) + rip_redistribute_conf_delete(rip, type); return NB_OK; } @@ -666,7 +687,8 @@ ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode) rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - rip_redistribute_conf_update(rip, type); + if (rip->enabled) + rip_redistribute_conf_update(rip, type); } /* @@ -688,10 +710,10 @@ ripd_instance_redistribute_route_map_modify(enum nb_event event, type = yang_dnode_get_enum(dnode, "../protocol"); rmap_name = yang_dnode_get_string(dnode, NULL); - if (rip->route_map[type].name) - free(rip->route_map[type].name); - rip->route_map[type].name = strdup(rmap_name); - rip->route_map[type].map = route_map_lookup_by_name(rmap_name); + if (rip->redist[type].route_map.name) + free(rip->redist[type].route_map.name); + rip->redist[type].route_map.name = strdup(rmap_name); + rip->redist[type].route_map.map = route_map_lookup_by_name(rmap_name); return NB_OK; } @@ -709,9 +731,9 @@ ripd_instance_redistribute_route_map_delete(enum nb_event event, rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); - free(rip->route_map[type].name); - rip->route_map[type].name = NULL; - rip->route_map[type].map = NULL; + free(rip->redist[type].route_map.name); + rip->redist[type].route_map.name = NULL; + rip->redist[type].route_map.map = NULL; return NB_OK; } @@ -735,8 +757,8 @@ ripd_instance_redistribute_metric_modify(enum nb_event event, type = yang_dnode_get_enum(dnode, "../protocol"); metric = yang_dnode_get_uint8(dnode, NULL); - rip->route_map[type].metric_config = true; - rip->route_map[type].metric = metric; + rip->redist[type].metric_config = true; + rip->redist[type].metric = metric; return NB_OK; } @@ -754,8 +776,8 @@ ripd_instance_redistribute_metric_delete(enum nb_event event, rip = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); - rip->route_map[type].metric_config = false; - rip->route_map[type].metric = 0; + rip->redist[type].metric_config = false; + rip->redist[type].metric = 0; return NB_OK; } diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index d8b35cf976..4f0df12232 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -168,23 +168,28 @@ void rip_redistribute_conf_delete(struct rip *rip, int type) int rip_redistribute_check(struct rip *rip, int type) { - return vrf_bitmap_check(zclient->redist[AFI_IP][type], - rip->vrf->vrf_id); + return rip->redist[type].enabled; } -void rip_redistribute_clean(struct rip *rip) +void rip_redistribute_enable(struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP][i], - rip->vrf->vrf_id)) + if (!rip_redistribute_check(rip, i)) continue; - if (zclient->sock > 0) - zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, - zclient, AFI_IP, i, 0, - rip->vrf->vrf_id); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, + i, 0, rip->vrf->vrf_id); + } +} - vrf_bitmap_unset(zclient->redist[AFI_IP][i], rip->vrf->vrf_id); +void rip_redistribute_disable(struct rip *rip) +{ + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (!rip_redistribute_check(rip, i)) + continue; + + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP, i, 0, rip->vrf->vrf_id); } } @@ -192,8 +197,7 @@ void rip_show_redistribute_config(struct vty *vty, struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == zclient->redist_default - || !vrf_bitmap_check(zclient->redist[AFI_IP][i], - rip->vrf->vrf_id)) + || !rip_redistribute_check(rip, i)) continue; vty_out(vty, " %s", zebra_route_string(i)); diff --git a/ripd/ripd.c b/ripd/ripd.c index a6a2a29deb..7fe8fc8c8b 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2239,10 +2239,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, } /* Apply redistribute route map - continue, if deny */ - if (rip->route_map[rinfo->type].name + if (rip->redist[rinfo->type].route_map.name && rinfo->sub_type != RIP_ROUTE_INTERFACE) { ret = route_map_apply( - rip->route_map[rinfo->type].map, + rip->redist[rinfo->type].route_map.map, (struct prefix *)p, RMAP_RIP, rinfo); if (ret == RMAP_DENYMATCH) { @@ -2258,11 +2258,10 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, /* When route-map does not set metric. */ if (!rinfo->metric_set) { /* If redistribute metric is set. */ - if (rip->route_map[rinfo->type].metric_config + if (rip->redist[rinfo->type].metric_config && rinfo->metric != RIP_METRIC_INFINITY) { rinfo->metric_out = - rip->route_map[rinfo->type] - .metric; + rip->redist[rinfo->type].metric; } else { /* If the route is not connected or localy generated @@ -3382,8 +3381,8 @@ void rip_clean(struct rip *rip) stream_free(rip->obuf); for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (rip->route_map[i].name) - free(rip->route_map[i].name); + if (rip->redist[i].route_map.name) + free(rip->redist[i].route_map.name); route_table_finish(rip->table); route_table_finish(rip->neighbor); @@ -3398,7 +3397,6 @@ void rip_clean(struct rip *rip) list_delete(&rip->offset_list_master); rip_interfaces_clean(rip); route_table_finish(rip->distance_table); - rip_redistribute_clean(rip); RB_REMOVE(rip_instance_head, &rip_instances, rip); XFREE(MTYPE_RIP_VRF_NAME, rip->vrf_name); @@ -3447,9 +3445,9 @@ void rip_if_rmap_update_interface(struct interface *ifp) static void rip_routemap_update_redistribute(struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (rip->route_map[i].name) - rip->route_map[i].map = route_map_lookup_by_name( - rip->route_map[i].name); + if (rip->redist[i].route_map.name) + rip->redist[i].route_map.map = route_map_lookup_by_name( + rip->redist[i].route_map.name); } } @@ -3501,6 +3499,9 @@ static void rip_instance_enable(struct rip *rip, struct vrf *vrf, int sock) rip_vrf_link(rip, vrf); rip->enabled = true; + /* Resend all redistribute requests. */ + rip_redistribute_enable(rip); + /* Create read and timer thread. */ rip_event(rip, RIP_READ, rip->sock); rip_event(rip, RIP_UPDATE_EVENT, 1); @@ -3536,6 +3537,9 @@ static void rip_instance_disable(struct rip *rip) route_unlock_node(rp); } + /* Flush all redistribute requests. */ + rip_redistribute_disable(rip); + /* Cancel RIP related timers. */ RIP_TIMER_OFF(rip->t_update); RIP_TIMER_OFF(rip->t_triggered_update); diff --git a/ripd/ripd.h b/ripd/ripd.h index d88c5c1e61..f78dae7a8b 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -170,13 +170,16 @@ struct rip { /* RIP offset-lists. */ struct list *offset_list_master; - /* For redistribute route map. */ + /* RIP redistribute configuration. */ struct { - char *name; - struct route_map *map; + bool enabled; + struct { + char *name; + struct route_map *map; + } route_map; bool metric_config; uint8_t metric; - } route_map[ZEBRA_ROUTE_MAX]; + } redist[ZEBRA_ROUTE_MAX]; /* For distribute-list container */ struct distribute_ctx *distribute_ctx; @@ -487,7 +490,8 @@ 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 *rip, struct rip_info *rinfo); -extern void rip_redistribute_clean(struct rip *rip); +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 *rip, diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index 4b15a3aef7..dda57a31fe 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -411,6 +411,17 @@ static int ripngd_instance_redistribute_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { + 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->redist[type].enabled = true; + return NB_OK; } @@ -426,7 +437,17 @@ static int ripngd_instance_redistribute_delete(enum nb_event event, ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - ripng_redistribute_conf_delete(ripng, type); + ripng->redist[type].enabled = false; + if (ripng->redist[type].route_map.name) { + free(ripng->redist[type].route_map.name); + ripng->redist[type].route_map.name = NULL; + ripng->redist[type].route_map.map = NULL; + } + ripng->redist[type].metric_config = false; + ripng->redist[type].metric = 0; + + if (ripng->enabled) + ripng_redistribute_conf_delete(ripng, type); return NB_OK; } @@ -440,7 +461,8 @@ ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode) ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "./protocol"); - ripng_redistribute_conf_update(ripng, type); + if (ripng->enabled) + ripng_redistribute_conf_update(ripng, type); } /* @@ -462,10 +484,10 @@ ripngd_instance_redistribute_route_map_modify(enum nb_event event, type = yang_dnode_get_enum(dnode, "../protocol"); rmap_name = yang_dnode_get_string(dnode, NULL); - if (ripng->route_map[type].name) - free(ripng->route_map[type].name); - ripng->route_map[type].name = strdup(rmap_name); - ripng->route_map[type].map = route_map_lookup_by_name(rmap_name); + if (ripng->redist[type].route_map.name) + free(ripng->redist[type].route_map.name); + ripng->redist[type].route_map.name = strdup(rmap_name); + ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name); return NB_OK; } @@ -483,9 +505,9 @@ ripngd_instance_redistribute_route_map_delete(enum nb_event event, ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); - free(ripng->route_map[type].name); - ripng->route_map[type].name = NULL; - ripng->route_map[type].map = NULL; + free(ripng->redist[type].route_map.name); + ripng->redist[type].route_map.name = NULL; + ripng->redist[type].route_map.map = NULL; return NB_OK; } @@ -509,8 +531,8 @@ ripngd_instance_redistribute_metric_modify(enum nb_event event, type = yang_dnode_get_enum(dnode, "../protocol"); metric = yang_dnode_get_uint8(dnode, NULL); - ripng->route_map[type].metric_config = true; - ripng->route_map[type].metric = metric; + ripng->redist[type].metric_config = true; + ripng->redist[type].metric = metric; return NB_OK; } @@ -528,8 +550,8 @@ ripngd_instance_redistribute_metric_delete(enum nb_event event, ripng = yang_dnode_get_entry(dnode, true); type = yang_dnode_get_enum(dnode, "../protocol"); - ripng->route_map[type].metric_config = false; - ripng->route_map[type].metric = 0; + ripng->redist[type].metric_config = false; + ripng->redist[type].metric = 0; return NB_OK; } diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 913ac5191c..e2dcc02384 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -165,24 +165,28 @@ void ripng_redistribute_conf_delete(struct ripng *ripng, int type) int ripng_redistribute_check(struct ripng *ripng, int type) { - return vrf_bitmap_check(zclient->redist[AFI_IP6][type], - ripng->vrf->vrf_id); + return ripng->redist[type].enabled; } -void ripng_redistribute_clean(struct ripng *ripng) +void ripng_redistribute_enable(struct ripng *ripng) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], - ripng->vrf->vrf_id)) + if (!ripng_redistribute_check(ripng, i)) continue; - if (zclient->sock > 0) - zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, - zclient, AFI_IP6, i, 0, - ripng->vrf->vrf_id); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP6, i, 0, ripng->vrf->vrf_id); + } +} - vrf_bitmap_unset(zclient->redist[AFI_IP6][i], - ripng->vrf->vrf_id); +void ripng_redistribute_disable(struct ripng *ripng) +{ + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (!ripng_redistribute_check(ripng, i)) + continue; + + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP6, i, 0, ripng->vrf->vrf_id); } } @@ -192,8 +196,7 @@ void ripng_redistribute_write(struct vty *vty, struct ripng *ripng) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == zclient->redist_default - || !vrf_bitmap_check(zclient->redist[AFI_IP6][i], - ripng->vrf->vrf_id)) + || !ripng_redistribute_check(ripng, i)) continue; vty_out(vty, " %s", zebra_route_string(i)); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 951c73bc45..c3aa9d8dbf 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1682,10 +1682,11 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, } /* Redistribute route-map. */ - if (ripng->route_map[rinfo->type].name) { - ret = route_map_apply( - ripng->route_map[rinfo->type].map, - (struct prefix *)p, RMAP_RIPNG, rinfo); + if (ripng->redist[rinfo->type].route_map.name) { + ret = route_map_apply(ripng->redist[rinfo->type] + .route_map.map, + (struct prefix *)p, + RMAP_RIPNG, rinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIPNG_DEBUG_PACKET) @@ -1700,10 +1701,10 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, /* When the route-map does not set metric. */ if (!rinfo->metric_set) { /* If the redistribute metric is set. */ - if (ripng->route_map[rinfo->type].metric_config + if (ripng->redist[rinfo->type].metric_config && rinfo->metric != RIPNG_METRIC_INFINITY) { rinfo->metric_out = - ripng->route_map[rinfo->type] + ripng->redist[rinfo->type] .metric; } else { /* If the route is not connected or @@ -2531,8 +2532,8 @@ void ripng_clean(struct ripng *ripng) ripng_instance_disable(ripng); for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (ripng->route_map[i].name) - free(ripng->route_map[i].name); + if (ripng->redist[i].route_map.name) + free(ripng->redist[i].route_map.name); agg_table_finish(ripng->table); list_delete(&ripng->peer_list); @@ -2548,7 +2549,6 @@ void ripng_clean(struct ripng *ripng) vector_free(ripng->passive_interface); list_delete(&ripng->offset_list_master); ripng_interface_clean(ripng); - ripng_redistribute_clean(ripng); RB_REMOVE(ripng_instance_head, &ripng_instances, ripng); XFREE(MTYPE_RIPNG_VRF_NAME, ripng->vrf_name); @@ -2598,9 +2598,10 @@ void ripng_if_rmap_update_interface(struct interface *ifp) static void ripng_routemap_update_redistribute(struct ripng *ripng) { 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); + if (ripng->redist[i].route_map.name) + ripng->redist[i].route_map.map = + route_map_lookup_by_name( + ripng->redist[i].route_map.name); } } @@ -2652,6 +2653,9 @@ static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf, ripng_vrf_link(ripng, vrf); ripng->enabled = true; + /* Resend all redistribute requests. */ + ripng_redistribute_enable(ripng); + /* Create read and timer thread. */ ripng_event(ripng, RIPNG_READ, ripng->sock); ripng_event(ripng, RIPNG_UPDATE_EVENT, 1); @@ -2694,6 +2698,9 @@ static void ripng_instance_disable(struct ripng *ripng) } } + /* Flush all redistribute requests. */ + ripng_redistribute_disable(ripng); + /* Cancel the RIPng timers */ RIPNG_TIMER_OFF(ripng->t_update); RIPNG_TIMER_OFF(ripng->t_triggered_update); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index d6c4394c6d..b38e6b3a95 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -149,13 +149,16 @@ struct ripng { /* RIPng ECMP flag */ bool ecmp; - /* For redistribute route map. */ + /* RIPng redistribute configuration. */ struct { - char *name; - struct route_map *map; + bool enabled; + struct { + char *name; + struct route_map *map; + } route_map; bool metric_config; uint8_t metric; - } route_map[ZEBRA_ROUTE_MAX]; + } redist[ZEBRA_ROUTE_MAX]; /* For distribute-list container */ struct distribute_ctx *distribute_ctx; @@ -447,7 +450,8 @@ extern void ripng_if_rmap_update_interface(struct interface *); 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(struct ripng *ripng); +extern void ripng_redistribute_enable(struct ripng *ripng); +extern void ripng_redistribute_disable(struct ripng *ripng); extern int ripng_redistribute_check(struct ripng *ripng, int type); extern void ripng_redistribute_write(struct vty *vty, struct ripng *ripng); From 6a534dcafcb623f1b85b5ee2a13c74faab227ced Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 15 Jan 2019 10:50:20 -0200 Subject: [PATCH 35/36] yang: sync the IETF module translator with the latest frr-ripd changes Signed-off-by: Renato Westphal --- yang/ietf/frr-ietf-translator.json | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/yang/ietf/frr-ietf-translator.json b/yang/ietf/frr-ietf-translator.json index 9855480b45..38a609982f 100644 --- a/yang/ietf/frr-ietf-translator.json +++ b/yang/ietf/frr-ietf-translator.json @@ -22,7 +22,7 @@ "mappings": [ { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']", - "native": "/frr-ripd:ripd/instance" + "native": "/frr-ripd:ripd/instance[vrf='default']" } ] }, @@ -32,31 +32,31 @@ "mappings": [ { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/default-metric", - "native": "/frr-ripd:ripd/instance/default-metric" + "native": "/frr-ripd:ripd/instance[vrf='default']/default-metric" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/distance", - "native": "/frr-ripd:ripd/instance/distance/default" + "native": "/frr-ripd:ripd/instance[vrf='default']/distance/default" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/originate-default-route/enabled", - "native": "/frr-ripd:ripd/instance/default-information-originate" + "native": "/frr-ripd:ripd/instance[vrf='default']/default-information-originate" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/update-interval", - "native": "/frr-ripd:ripd/instance/timers/update-interval" + "native": "/frr-ripd:ripd/instance[vrf='default']/timers/update-interval" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/holddown-interval", - "native": "/frr-ripd:ripd/instance/timers/holddown-interval" + "native": "/frr-ripd:ripd/instance[vrf='default']/timers/holddown-interval" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/timers/flush-interval", - "native": "/frr-ripd:ripd/instance/timers/flush-interval" + "native": "/frr-ripd:ripd/instance[vrf='default']/timers/flush-interval" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']", - "native": "/frr-ripd:ripd/instance/interface[.='KEY1']" + "native": "/frr-ripd:ripd/instance[vrf='default']/interface[.='KEY1']" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/interfaces/interface[interface='KEY1']/split-horizon", @@ -64,43 +64,43 @@ }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']", - "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/ipv4-address", - "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/address" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/address" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/last-update", - "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/last-update" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/last-update" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-packets-rcvd", - "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-packets-rcvd" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/neighbors/neighbor[ipv4-address='KEY1']/bad-routes-rcvd", - "native": "/frr-ripd:ripd/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/neighbors/neighbor[address='KEY1']/bad-routes-rcvd" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']", - "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/ipv4-prefix", - "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/prefix" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/prefix" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/next-hop", - "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/next-hop" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/next-hop" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/interface", - "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/interface" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/interface" }, { "custom": "/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-rip:ripv2'][name='main']/ietf-rip:rip/ipv4/routes/route[ipv4-prefix='KEY1']/metric", - "native": "/frr-ripd:ripd/state/routes/route[prefix='KEY1']/metric" + "native": "/frr-ripd:ripd/instance[vrf='default']/state/routes/route[prefix='KEY1']/metric" }, { "custom": "/ietf-rip:clear-rip-route", From 6a3fdeecf102f18afa95dbbe714d3b72f9e2a9dc Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 2 Mar 2019 15:42:42 -0300 Subject: [PATCH 36/36] lib, ripd, ripngd: rename remaining delete northbound callbacks PR #3622 renamed the "delete" northbound callback to "destroy" in order to make the libfrr headers compatible with C++. This commit renames a few functions that still use "delete" instead of "destroy" in their names. Signed-off-by: Renato Westphal --- lib/if.c | 12 ++--- ripd/rip_northbound.c | 94 +++++++++++++++++++-------------------- ripngd/ripng_northbound.c | 60 ++++++++++++------------- 3 files changed, 83 insertions(+), 83 deletions(-) diff --git a/lib/if.c b/lib/if.c index 48841c7ee8..b26934c3f6 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1309,8 +1309,8 @@ static int lib_interface_create(enum nb_event event, return NB_OK; } -static int lib_interface_delete(enum nb_event event, - const struct lyd_node *dnode) +static int lib_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct interface *ifp; @@ -1357,8 +1357,8 @@ static int lib_interface_description_modify(enum nb_event event, return NB_OK; } -static int lib_interface_description_delete(enum nb_event event, - const struct lyd_node *dnode) +static int lib_interface_description_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct interface *ifp; @@ -1379,13 +1379,13 @@ const struct frr_yang_module_info frr_interface_info = { { .xpath = "/frr-interface:lib/interface", .cbs.create = lib_interface_create, - .cbs.destroy = lib_interface_delete, + .cbs.destroy = lib_interface_destroy, .cbs.cli_show = cli_show_interface, }, { .xpath = "/frr-interface:lib/interface/description", .cbs.modify = lib_interface_description_modify, - .cbs.destroy = lib_interface_description_delete, + .cbs.destroy = lib_interface_description_destroy, .cbs.cli_show = cli_show_interface_desc, }, { diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 2c53824ea1..05bbc8dd76 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -86,8 +86,8 @@ static int ripd_instance_create(enum nb_event event, return NB_OK; } -static int ripd_instance_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; @@ -250,8 +250,8 @@ static int ripd_instance_distance_source_create(enum nb_event event, return NB_OK; } -static int ripd_instance_distance_source_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_distance_source_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct route_node *rn; struct rip_distance *rdistance; @@ -320,8 +320,8 @@ ripd_instance_distance_source_access_list_modify(enum nb_event event, } static int -ripd_instance_distance_source_access_list_delete(enum nb_event event, - const struct lyd_node *dnode) +ripd_instance_distance_source_access_list_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct route_node *rn; struct rip_distance *rdistance; @@ -359,8 +359,8 @@ static int ripd_instance_explicit_neighbor_create(enum nb_event event, return rip_neighbor_add(rip, &p); } -static int ripd_instance_explicit_neighbor_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_explicit_neighbor_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; struct prefix_ipv4 p; @@ -396,8 +396,8 @@ static int ripd_instance_network_create(enum nb_event event, return rip_enable_network_add(rip, &p); } -static int ripd_instance_network_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_network_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; struct prefix p; @@ -431,8 +431,8 @@ static int ripd_instance_interface_create(enum nb_event event, return rip_enable_if_add(rip, ifname); } -static int ripd_instance_interface_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; const char *ifname; @@ -469,8 +469,8 @@ static int ripd_instance_offset_list_create(enum nb_event event, return NB_OK; } -static int ripd_instance_offset_list_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_offset_list_destroy(enum nb_event event, + const struct lyd_node *dnode) { int direct; struct rip_offset_list *offset; @@ -579,8 +579,8 @@ static int ripd_instance_passive_interface_create(enum nb_event event, return rip_passive_nondefault_set(rip, ifname); } -static int ripd_instance_passive_interface_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; const char *ifname; @@ -615,8 +615,8 @@ ripd_instance_non_passive_interface_create(enum nb_event event, } static int -ripd_instance_non_passive_interface_delete(enum nb_event event, - const struct lyd_node *dnode) +ripd_instance_non_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; const char *ifname; @@ -651,8 +651,8 @@ static int ripd_instance_redistribute_create(enum nb_event event, return NB_OK; } -static int ripd_instance_redistribute_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_redistribute_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; int type; @@ -719,8 +719,8 @@ ripd_instance_redistribute_route_map_modify(enum nb_event event, } static int -ripd_instance_redistribute_route_map_delete(enum nb_event event, - const struct lyd_node *dnode) +ripd_instance_redistribute_route_map_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; int type; @@ -764,8 +764,8 @@ ripd_instance_redistribute_metric_modify(enum nb_event event, } static int -ripd_instance_redistribute_metric_delete(enum nb_event event, - const struct lyd_node *dnode) +ripd_instance_redistribute_metric_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; int type; @@ -808,8 +808,8 @@ static int ripd_instance_static_route_create(enum nb_event event, return NB_OK; } -static int ripd_instance_static_route_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripd_instance_static_route_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct rip *rip; struct prefix_ipv4 p; @@ -1054,7 +1054,7 @@ static int lib_interface_rip_authentication_scheme_md5_auth_length_modify( return NB_OK; } -static int lib_interface_rip_authentication_scheme_md5_auth_length_delete( +static int lib_interface_rip_authentication_scheme_md5_auth_length_destroy( enum nb_event event, const struct lyd_node *dnode) { struct interface *ifp; @@ -1096,8 +1096,8 @@ lib_interface_rip_authentication_password_modify(enum nb_event event, } static int -lib_interface_rip_authentication_password_delete(enum nb_event event, - const struct lyd_node *dnode) +lib_interface_rip_authentication_password_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct interface *ifp; struct rip_interface *ri; @@ -1137,8 +1137,8 @@ lib_interface_rip_authentication_key_chain_modify(enum nb_event event, } static int -lib_interface_rip_authentication_key_chain_delete(enum nb_event event, - const struct lyd_node *dnode) +lib_interface_rip_authentication_key_chain_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct interface *ifp; struct rip_interface *ri; @@ -1486,7 +1486,7 @@ const struct frr_yang_module_info frr_ripd_info = { { .xpath = "/frr-ripd:ripd/instance", .cbs.create = ripd_instance_create, - .cbs.destroy = ripd_instance_delete, + .cbs.destroy = ripd_instance_destroy, .cbs.get_next = ripd_instance_get_next, .cbs.get_keys = ripd_instance_get_keys, .cbs.lookup_entry = ripd_instance_lookup_entry, @@ -1515,7 +1515,7 @@ const struct frr_yang_module_info frr_ripd_info = { { .xpath = "/frr-ripd:ripd/instance/distance/source", .cbs.create = ripd_instance_distance_source_create, - .cbs.destroy = ripd_instance_distance_source_delete, + .cbs.destroy = ripd_instance_distance_source_destroy, .cbs.cli_show = cli_show_rip_distance_source, }, { @@ -1525,30 +1525,30 @@ const struct frr_yang_module_info frr_ripd_info = { { .xpath = "/frr-ripd:ripd/instance/distance/source/access-list", .cbs.modify = ripd_instance_distance_source_access_list_modify, - .cbs.destroy = ripd_instance_distance_source_access_list_delete, + .cbs.destroy = ripd_instance_distance_source_access_list_destroy, }, { .xpath = "/frr-ripd:ripd/instance/explicit-neighbor", .cbs.create = ripd_instance_explicit_neighbor_create, - .cbs.destroy = ripd_instance_explicit_neighbor_delete, + .cbs.destroy = ripd_instance_explicit_neighbor_destroy, .cbs.cli_show = cli_show_rip_neighbor, }, { .xpath = "/frr-ripd:ripd/instance/network", .cbs.create = ripd_instance_network_create, - .cbs.destroy = ripd_instance_network_delete, + .cbs.destroy = ripd_instance_network_destroy, .cbs.cli_show = cli_show_rip_network_prefix, }, { .xpath = "/frr-ripd:ripd/instance/interface", .cbs.create = ripd_instance_interface_create, - .cbs.destroy = ripd_instance_interface_delete, + .cbs.destroy = ripd_instance_interface_destroy, .cbs.cli_show = cli_show_rip_network_interface, }, { .xpath = "/frr-ripd:ripd/instance/offset-list", .cbs.create = ripd_instance_offset_list_create, - .cbs.destroy = ripd_instance_offset_list_delete, + .cbs.destroy = ripd_instance_offset_list_destroy, .cbs.cli_show = cli_show_rip_offset_list, }, { @@ -1567,36 +1567,36 @@ const struct frr_yang_module_info frr_ripd_info = { { .xpath = "/frr-ripd:ripd/instance/passive-interface", .cbs.create = ripd_instance_passive_interface_create, - .cbs.destroy = ripd_instance_passive_interface_delete, + .cbs.destroy = ripd_instance_passive_interface_destroy, .cbs.cli_show = cli_show_rip_passive_interface, }, { .xpath = "/frr-ripd:ripd/instance/non-passive-interface", .cbs.create = ripd_instance_non_passive_interface_create, - .cbs.destroy = ripd_instance_non_passive_interface_delete, + .cbs.destroy = ripd_instance_non_passive_interface_destroy, .cbs.cli_show = cli_show_rip_non_passive_interface, }, { .xpath = "/frr-ripd:ripd/instance/redistribute", .cbs.create = ripd_instance_redistribute_create, - .cbs.destroy = ripd_instance_redistribute_delete, + .cbs.destroy = ripd_instance_redistribute_destroy, .cbs.apply_finish = ripd_instance_redistribute_apply_finish, .cbs.cli_show = cli_show_rip_redistribute, }, { .xpath = "/frr-ripd:ripd/instance/redistribute/route-map", .cbs.modify = ripd_instance_redistribute_route_map_modify, - .cbs.destroy = ripd_instance_redistribute_route_map_delete, + .cbs.destroy = ripd_instance_redistribute_route_map_destroy, }, { .xpath = "/frr-ripd:ripd/instance/redistribute/metric", .cbs.modify = ripd_instance_redistribute_metric_modify, - .cbs.destroy = ripd_instance_redistribute_metric_delete, + .cbs.destroy = ripd_instance_redistribute_metric_destroy, }, { .xpath = "/frr-ripd:ripd/instance/static-route", .cbs.create = ripd_instance_static_route_create, - .cbs.destroy = ripd_instance_static_route_delete, + .cbs.destroy = ripd_instance_static_route_destroy, .cbs.cli_show = cli_show_rip_route, }, { @@ -1659,18 +1659,18 @@ const struct frr_yang_module_info frr_ripd_info = { { .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length", .cbs.modify = lib_interface_rip_authentication_scheme_md5_auth_length_modify, - .cbs.destroy = lib_interface_rip_authentication_scheme_md5_auth_length_delete, + .cbs.destroy = lib_interface_rip_authentication_scheme_md5_auth_length_destroy, }, { .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password", .cbs.modify = lib_interface_rip_authentication_password_modify, - .cbs.destroy = lib_interface_rip_authentication_password_delete, + .cbs.destroy = lib_interface_rip_authentication_password_destroy, .cbs.cli_show = cli_show_ip_rip_authentication_string, }, { .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain", .cbs.modify = lib_interface_rip_authentication_key_chain_modify, - .cbs.destroy = lib_interface_rip_authentication_key_chain_delete, + .cbs.destroy = lib_interface_rip_authentication_key_chain_destroy, .cbs.cli_show = cli_show_ip_rip_authentication_key_chain, }, { diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index 66b9e13d7f..c483ad65f8 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -88,8 +88,8 @@ static int ripngd_instance_create(enum nb_event event, return NB_OK; } -static int ripngd_instance_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripngd_instance_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; @@ -222,8 +222,8 @@ static int ripngd_instance_network_create(enum nb_event event, return ripng_enable_network_add(ripng, &p); } -static int ripngd_instance_network_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripngd_instance_network_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; struct prefix p; @@ -257,8 +257,8 @@ static int ripngd_instance_interface_create(enum nb_event event, return ripng_enable_if_add(ripng, ifname); } -static int ripngd_instance_interface_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripngd_instance_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; const char *ifname; @@ -295,8 +295,8 @@ static int ripngd_instance_offset_list_create(enum nb_event event, return NB_OK; } -static int ripngd_instance_offset_list_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripngd_instance_offset_list_destroy(enum nb_event event, + const struct lyd_node *dnode) { int direct; struct ripng_offset_list *offset; @@ -389,8 +389,8 @@ ripngd_instance_passive_interface_create(enum nb_event event, } static int -ripngd_instance_passive_interface_delete(enum nb_event event, - const struct lyd_node *dnode) +ripngd_instance_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; const char *ifname; @@ -425,8 +425,8 @@ static int ripngd_instance_redistribute_create(enum nb_event event, return NB_OK; } -static int ripngd_instance_redistribute_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripngd_instance_redistribute_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; int type; @@ -493,8 +493,8 @@ ripngd_instance_redistribute_route_map_modify(enum nb_event event, } static int -ripngd_instance_redistribute_route_map_delete(enum nb_event event, - const struct lyd_node *dnode) +ripngd_instance_redistribute_route_map_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; int type; @@ -538,8 +538,8 @@ ripngd_instance_redistribute_metric_modify(enum nb_event event, } static int -ripngd_instance_redistribute_metric_delete(enum nb_event event, - const struct lyd_node *dnode) +ripngd_instance_redistribute_metric_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; int type; @@ -579,8 +579,8 @@ static int ripngd_instance_static_route_create(enum nb_event event, return NB_OK; } -static int ripngd_instance_static_route_delete(enum nb_event event, - const struct lyd_node *dnode) +static int ripngd_instance_static_route_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; struct prefix_ipv6 p; @@ -622,8 +622,8 @@ ripngd_instance_aggregate_address_create(enum nb_event event, } static int -ripngd_instance_aggregate_address_delete(enum nb_event event, - const struct lyd_node *dnode) +ripngd_instance_aggregate_address_destroy(enum nb_event event, + const struct lyd_node *dnode) { struct ripng *ripng; struct prefix_ipv6 p; @@ -1013,7 +1013,7 @@ const struct frr_yang_module_info frr_ripngd_info = { { .xpath = "/frr-ripngd:ripngd/instance", .cbs.create = ripngd_instance_create, - .cbs.destroy = ripngd_instance_delete, + .cbs.destroy = ripngd_instance_destroy, .cbs.get_next = ripngd_instance_get_next, .cbs.get_keys = ripngd_instance_get_keys, .cbs.lookup_entry = ripngd_instance_lookup_entry, @@ -1037,19 +1037,19 @@ const struct frr_yang_module_info frr_ripngd_info = { { .xpath = "/frr-ripngd:ripngd/instance/network", .cbs.create = ripngd_instance_network_create, - .cbs.destroy = ripngd_instance_network_delete, + .cbs.destroy = ripngd_instance_network_destroy, .cbs.cli_show = cli_show_ripng_network_prefix, }, { .xpath = "/frr-ripngd:ripngd/instance/interface", .cbs.create = ripngd_instance_interface_create, - .cbs.destroy = ripngd_instance_interface_delete, + .cbs.destroy = ripngd_instance_interface_destroy, .cbs.cli_show = cli_show_ripng_network_interface, }, { .xpath = "/frr-ripngd:ripngd/instance/offset-list", .cbs.create = ripngd_instance_offset_list_create, - .cbs.destroy = ripngd_instance_offset_list_delete, + .cbs.destroy = ripngd_instance_offset_list_destroy, .cbs.cli_show = cli_show_ripng_offset_list, }, { @@ -1063,36 +1063,36 @@ const struct frr_yang_module_info frr_ripngd_info = { { .xpath = "/frr-ripngd:ripngd/instance/passive-interface", .cbs.create = ripngd_instance_passive_interface_create, - .cbs.destroy = ripngd_instance_passive_interface_delete, + .cbs.destroy = ripngd_instance_passive_interface_destroy, .cbs.cli_show = cli_show_ripng_passive_interface, }, { .xpath = "/frr-ripngd:ripngd/instance/redistribute", .cbs.create = ripngd_instance_redistribute_create, - .cbs.destroy = ripngd_instance_redistribute_delete, + .cbs.destroy = ripngd_instance_redistribute_destroy, .cbs.apply_finish = ripngd_instance_redistribute_apply_finish, .cbs.cli_show = cli_show_ripng_redistribute, }, { .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map", .cbs.modify = ripngd_instance_redistribute_route_map_modify, - .cbs.destroy = ripngd_instance_redistribute_route_map_delete, + .cbs.destroy = ripngd_instance_redistribute_route_map_destroy, }, { .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric", .cbs.modify = ripngd_instance_redistribute_metric_modify, - .cbs.destroy = ripngd_instance_redistribute_metric_delete, + .cbs.destroy = ripngd_instance_redistribute_metric_destroy, }, { .xpath = "/frr-ripngd:ripngd/instance/static-route", .cbs.create = ripngd_instance_static_route_create, - .cbs.destroy = ripngd_instance_static_route_delete, + .cbs.destroy = ripngd_instance_static_route_destroy, .cbs.cli_show = cli_show_ripng_route, }, { .xpath = "/frr-ripngd:ripngd/instance/aggregate-address", .cbs.create = ripngd_instance_aggregate_address_create, - .cbs.destroy = ripngd_instance_aggregate_address_delete, + .cbs.destroy = ripngd_instance_aggregate_address_destroy, .cbs.cli_show = cli_show_ripng_aggregate_address, }, {