diff --git a/babeld/babel_filter.c b/babeld/babel_filter.c index 31778901a6..28ba8e16a2 100644 --- a/babeld/babel_filter.c +++ b/babeld/babel_filter.c @@ -39,10 +39,11 @@ babel_filter(int output, const unsigned char *prefix, unsigned short plen, struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); babel_interface_nfo *babel_ifp = ifp ? babel_get_if_nfo(ifp) : NULL; struct prefix p; - struct distribute *dist; + struct distribute *dist = NULL; struct access_list *alist; struct prefix_list *plist; int distribute; + struct babel *babel; p.family = v4mapped(prefix) ? AF_INET : AF_INET6; p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; @@ -81,7 +82,9 @@ babel_filter(int output, const unsigned char *prefix, unsigned short plen, } /* All interface filter check. */ - dist = distribute_lookup (NULL); + babel = babel_lookup(); + if (babel) + dist = distribute_lookup (babel->distribute_ctx, NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup (p.family, dist->list[distribute]); diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index 7121ca28d4..a8698bfce3 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -1248,11 +1248,16 @@ DEFUN (show_babel_parameters, "Babel information\n" "Configuration information\n") { + struct babel *babel_ctx; + vty_out (vty, " -- Babel running configuration --\n"); show_babel_main_configuration(vty); - vty_out (vty, " -- distribution lists --\n"); - config_show_distribute(vty); + babel_ctx = babel_lookup(); + if (babel_ctx) { + vty_out (vty, " -- distribution lists --\n"); + config_show_distribute(vty, babel_ctx->distribute_ctx); + } return CMD_SUCCESS; } diff --git a/babeld/babeld.c b/babeld/babeld.c index 0517cbea6d..702c1fbabb 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -53,7 +53,8 @@ static int babel_read_protocol (struct thread *thread); static int babel_main_loop(struct thread *thread); static void babel_set_timer(struct timeval *timeout); static void babel_fill_with_next_timeout(struct timeval *tv); - +static void +babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist); /* Informations relative to the babel running daemon. */ static struct babel *babel_routing_process = NULL; @@ -123,7 +124,7 @@ babel_config_write (struct vty *vty) } } - lines += config_write_distribute (vty); + lines += config_write_distribute (vty, babel_routing_process->distribute_ctx); return lines; } @@ -154,8 +155,12 @@ babel_create_routing_process (void) thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read); /* wait a little: zebra will announce interfaces, addresses, routes... */ thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L, &babel_routing_process->t_update); - return 0; + /* Distribute list install. */ + babel_routing_process->distribute_ctx = distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT)); + distribute_list_add_hook (babel_routing_process->distribute_ctx, babel_distribute_update); + distribute_list_delete_hook (babel_routing_process->distribute_ctx, babel_distribute_update); + return 0; fail: XFREE(MTYPE_BABEL, babel_routing_process); babel_routing_process = NULL; @@ -315,6 +320,7 @@ babel_clean_routing_process() thread_cancel(babel_routing_process->t_update); } + distribute_list_delete(&babel_routing_process->distribute_ctx); XFREE(MTYPE_BABEL, babel_routing_process); babel_routing_process = NULL; } @@ -539,7 +545,7 @@ resize_receive_buffer(int size) } static void -babel_distribute_update (struct distribute *dist) +babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist) { struct interface *ifp; babel_interface_nfo *babel_ifp; @@ -574,11 +580,12 @@ babel_distribute_update (struct distribute *dist) static void babel_distribute_update_interface (struct interface *ifp) { - struct distribute *dist; + struct distribute *dist = NULL; - dist = distribute_lookup (ifp->name); + if (babel_routing_process) + dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name); if (dist) - babel_distribute_update (dist); + babel_distribute_update (babel_routing_process->distribute_ctx, dist); } /* Update all interface's distribute list. */ @@ -736,9 +743,7 @@ babeld_quagga_init(void) prefix_list_delete_hook (babel_distribute_update_all); /* Distribute list install. */ - distribute_list_init (BABEL_NODE); - distribute_list_add_hook (babel_distribute_update); - distribute_list_delete_hook (babel_distribute_update); + distribute_list_init(BABEL_NODE); } /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */ @@ -767,3 +772,7 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, return 0; } +struct babel *babel_lookup(void) +{ + return babel_routing_process; +} diff --git a/babeld/babeld.h b/babeld/babeld.h index bc284c1e96..752cc8620a 100644 --- a/babeld/babeld.h +++ b/babeld/babeld.h @@ -111,6 +111,8 @@ struct babel /* Babel threads. */ struct thread *t_read; /* on Babel protocol's socket */ struct thread *t_update; /* timers */ + /* distribute_ctx */ + struct distribute_ctx *distribute_ctx; }; extern struct zebra_privs_t babeld_privs; @@ -125,6 +127,6 @@ extern int redistribute_filter(const unsigned char *prefix, unsigned short plen, unsigned int ifindex, int proto); extern int resize_receive_buffer(int size); extern void schedule_neighbours_check(int msecs, int override); - +extern struct babel *babel_lookup(void); #endif /* BABEL_BABELD_H */ diff --git a/eigrpd/eigrp_filter.c b/eigrpd/eigrp_filter.c index c1bf1647d8..93eed9452c 100644 --- a/eigrpd/eigrp_filter.c +++ b/eigrpd/eigrp_filter.c @@ -62,7 +62,8 @@ /* * Distribute-list update functions. */ -void eigrp_distribute_update(struct distribute *dist) +void eigrp_distribute_update(struct distribute_ctx *ctx, + struct distribute *dist) { struct interface *ifp; struct eigrp_interface *ei = NULL; @@ -285,10 +286,15 @@ void eigrp_distribute_update(struct distribute *dist) void eigrp_distribute_update_interface(struct interface *ifp) { struct distribute *dist; + struct eigrp *eigrp; - dist = distribute_lookup(ifp->name); + eigrp = eigrp_lookup(); + if (!eigrp) + return; + dist = distribute_lookup(eigrp->distribute_ctx, ifp->name); if (dist) - eigrp_distribute_update(dist); + eigrp_distribute_update(eigrp->distribute_ctx, + dist); } /* Update all interface's distribute list. diff --git a/eigrpd/eigrp_filter.h b/eigrpd/eigrp_filter.h index caec19b0fb..34d00ecc13 100644 --- a/eigrpd/eigrp_filter.h +++ b/eigrpd/eigrp_filter.h @@ -33,7 +33,8 @@ #ifndef EIGRPD_EIGRP_FILTER_H_ #define EIGRPD_EIGRP_FILTER_H_ -extern void eigrp_distribute_update(struct distribute *); +extern void eigrp_distribute_update(struct distribute_ctx *ctx, + struct distribute *dist); extern void eigrp_distribute_update_interface(struct interface *); extern void eigrp_distribute_update_all(struct prefix_list *); extern void eigrp_distribute_update_all_wrapper(struct access_list *); diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 063fc5fec1..b19b383e65 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -217,8 +217,6 @@ int main(int argc, char **argv, char **envp) /* Distribute list install. */ distribute_list_init(EIGRP_NODE); - distribute_list_add_hook(eigrp_distribute_update); - distribute_list_delete_hook(eigrp_distribute_update); frr_config_fork(); frr_run(master); diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index ce03a21fba..a9c5db5361 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -131,6 +131,9 @@ struct eigrp { uint32_t metric; } route_map[ZEBRA_ROUTE_MAX]; + /* distribute_ctx */ + struct distribute_ctx *distribute_ctx; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(eigrp) diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index a0c4fa887a..b9486e0260 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -174,7 +174,7 @@ static int config_write_eigrp_distribute(struct vty *vty, struct eigrp *eigrp) int write = 0; /* Distribute configuration. */ - write += config_write_distribute(vty); + write += config_write_distribute(vty, eigrp->distribute_ctx); return write; } diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index 9bbecdf9e3..38d54edfca 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -44,6 +44,7 @@ #include "keychain.h" #include "libfrr.h" #include "lib_errors.h" +#include "distribute.h" #include "eigrpd/eigrp_structs.h" #include "eigrpd/eigrpd.h" @@ -55,6 +56,7 @@ #include "eigrpd/eigrp_network.h" #include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_memory.h" +#include "eigrpd/eigrp_filter.h" DEFINE_QOBJ_TYPE(eigrp) @@ -197,6 +199,13 @@ static struct eigrp *eigrp_new(const char *AS) eigrp->routemap[EIGRP_FILTER_IN] = NULL; eigrp->routemap[EIGRP_FILTER_OUT] = NULL; + /* Distribute list install. */ + eigrp->distribute_ctx = distribute_list_ctx_create( + vrf_lookup_by_id(VRF_DEFAULT)); + distribute_list_add_hook(eigrp->distribute_ctx, + eigrp_distribute_update); + distribute_list_delete_hook(eigrp->distribute_ctx, + eigrp_distribute_update); QOBJ_REG(eigrp, eigrp); return eigrp; } @@ -279,6 +288,7 @@ void eigrp_finish_final(struct eigrp *eigrp) listnode_delete(eigrp_om->eigrp, eigrp); stream_free(eigrp->ibuf); + distribute_list_delete(&eigrp->distribute_ctx); XFREE(MTYPE_EIGRP_TOP, eigrp); } diff --git a/lib/distribute.c b/lib/distribute.c index 9697916332..3a6b775bc8 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -27,16 +27,12 @@ #include "distribute.h" #include "memory.h" +DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_CTX, "Distribute ctx") DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list") DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_IFNAME, "Dist-list ifname") DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name") -/* Hash of distribute list. */ -struct hash *disthash; - -/* Hook functions. */ -void (*distribute_add_hook)(struct distribute *); -void (*distribute_delete_hook)(struct distribute *); +struct list *dist_ctx_list; static struct distribute *distribute_new(void) { @@ -62,7 +58,8 @@ static void distribute_free(struct distribute *dist) XFREE(MTYPE_DISTRIBUTE, dist); } -static void distribute_free_if_empty(struct distribute *dist) +static void distribute_free_if_empty(struct distribute_ctx *ctx, + struct distribute *dist) { int i; @@ -70,12 +67,13 @@ static void distribute_free_if_empty(struct distribute *dist) if (dist->list[i] != NULL || dist->prefix[i] != NULL) return; - hash_release(disthash, dist); + hash_release(ctx->disthash, dist); distribute_free(dist); } /* Lookup interface's distribute list. */ -struct distribute *distribute_lookup(const char *ifname) +struct distribute *distribute_lookup(struct distribute_ctx *ctx, + const char *ifname) { struct distribute key; struct distribute *dist; @@ -83,7 +81,7 @@ struct distribute *distribute_lookup(const char *ifname) /* temporary reference */ key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL; - dist = hash_lookup(disthash, &key); + dist = hash_lookup(ctx->disthash, &key); if (key.ifname) XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname); @@ -91,14 +89,18 @@ struct distribute *distribute_lookup(const char *ifname) return dist; } -void distribute_list_add_hook(void (*func)(struct distribute *)) +void distribute_list_add_hook(struct distribute_ctx *ctx, + void (*func)(struct distribute_ctx *ctx, + struct distribute *)) { - distribute_add_hook = func; + ctx->distribute_add_hook = func; } -void distribute_list_delete_hook(void (*func)(struct distribute *)) +void distribute_list_delete_hook(struct distribute_ctx *ctx, + void (*func)(struct distribute_ctx *ctx, + struct distribute *)) { - distribute_delete_hook = func; + ctx->distribute_delete_hook = func; } static void *distribute_hash_alloc(struct distribute *arg) @@ -114,7 +116,8 @@ static void *distribute_hash_alloc(struct distribute *arg) } /* Make new distribute list and push into hash. */ -static struct distribute *distribute_get(const char *ifname) +static struct distribute *distribute_get(struct distribute_ctx *ctx, + const char *ifname) { struct distribute key; struct distribute *ret; @@ -122,7 +125,7 @@ static struct distribute *distribute_get(const char *ifname) /* temporary reference */ key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL; - ret = hash_get(disthash, &key, + ret = hash_get(ctx->disthash, &key, (void *(*)(void *))distribute_hash_alloc); if (key.ifname) @@ -152,29 +155,32 @@ static bool distribute_cmp(const struct distribute *dist1, } /* Set access-list name to the distribute list. */ -static void distribute_list_set(const char *ifname, enum distribute_type type, +static void distribute_list_set(struct distribute_ctx *ctx, + const char *ifname, enum distribute_type type, const char *alist_name) { struct distribute *dist; - dist = distribute_get(ifname); + dist = distribute_get(ctx, ifname); if (dist->list[type]) XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]); dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name); /* Apply this distribute-list to the interface. */ - (*distribute_add_hook)(dist); + (ctx->distribute_add_hook)(ctx, dist); } /* Unset distribute-list. If matched distribute-list exist then return 1. */ -static int distribute_list_unset(const char *ifname, enum distribute_type type, +static int distribute_list_unset(struct distribute_ctx *ctx, + const char *ifname, + enum distribute_type type, const char *alist_name) { struct distribute *dist; - dist = distribute_lookup(ifname); + dist = distribute_lookup(ctx, ifname); if (!dist) return 0; @@ -187,39 +193,41 @@ static int distribute_list_unset(const char *ifname, enum distribute_type type, dist->list[type] = NULL; /* Apply this distribute-list to the interface. */ - (*distribute_delete_hook)(dist); + (ctx->distribute_delete_hook)(ctx, dist); /* If all dist are NULL, then free distribute list. */ - distribute_free_if_empty(dist); + distribute_free_if_empty(ctx, dist); return 1; } /* Set access-list name to the distribute list. */ -static void distribute_list_prefix_set(const char *ifname, +static void distribute_list_prefix_set(struct distribute_ctx *ctx, + const char *ifname, enum distribute_type type, const char *plist_name) { struct distribute *dist; - dist = distribute_get(ifname); + dist = distribute_get(ctx, ifname); if (dist->prefix[type]) XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]); dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name); /* Apply this distribute-list to the interface. */ - (*distribute_add_hook)(dist); + (ctx->distribute_add_hook)(ctx, dist); } /* Unset distribute-list. If matched distribute-list exist then return 1. */ -static int distribute_list_prefix_unset(const char *ifname, +static int distribute_list_prefix_unset(struct distribute_ctx *ctx, + const char *ifname, enum distribute_type type, const char *plist_name) { struct distribute *dist; - dist = distribute_lookup(ifname); + dist = distribute_lookup(ctx, ifname); if (!dist) return 0; @@ -232,10 +240,10 @@ static int distribute_list_prefix_unset(const char *ifname, dist->prefix[type] = NULL; /* Apply this distribute-list to the interface. */ - (*distribute_delete_hook)(dist); + (ctx->distribute_delete_hook)(ctx, dist); /* If all dist are NULL, then free distribute list. */ - distribute_free_if_empty(dist); + distribute_free_if_empty(ctx, dist); return 1; } @@ -250,15 +258,17 @@ DEFUN (distribute_list, "Interface name\n") { int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; - /* Check of distribute list type. */ enum distribute_type type = argv[2 + prefix]->arg[0] == 'i' ? DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT; /* Set appropriate function call */ - void (*distfn)(const char *, enum distribute_type, const char *) = + void (*distfn)(struct distribute_ctx *, const char *, + enum distribute_type, const char *) = prefix ? &distribute_list_prefix_set : &distribute_list_set; + struct distribute_ctx *ctx = + (struct distribute_ctx *)listnode_head(dist_ctx_list); /* if interface is present, get name */ const char *ifname = NULL; @@ -266,7 +276,7 @@ DEFUN (distribute_list, ifname = argv[argc - 1]->arg; /* Get interface name corresponding distribute list. */ - distfn(ifname, type, argv[1 + prefix]->arg); + distfn(ctx, ifname, type, argv[1 + prefix]->arg); return CMD_SUCCESS; } @@ -283,15 +293,16 @@ DEFUN (ipv6_distribute_list, "Interface name\n") { int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; - /* Check of distribute list type. */ enum distribute_type type = argv[3 + prefix]->arg[0] == 'i' ? DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT; /* Set appropriate function call */ - void (*distfn)(const char *, enum distribute_type, const char *) = + void (*distfn)(struct distribute_ctx *, const char *, + enum distribute_type, const char *) = prefix ? &distribute_list_prefix_set : &distribute_list_set; + struct distribute_ctx *ctx = listnode_head(dist_ctx_list); /* if interface is present, get name */ const char *ifname = NULL; @@ -299,7 +310,7 @@ DEFUN (ipv6_distribute_list, ifname = argv[argc - 1]->arg; /* Get interface name corresponding distribute list. */ - distfn(ifname, type, argv[2 + prefix]->arg); + distfn(ctx, ifname, type, argv[2 + prefix]->arg); return CMD_SUCCESS; } @@ -316,7 +327,6 @@ DEFUN (no_distribute_list, "Interface name\n") { int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; - int idx_alname = 2 + prefix; int idx_disttype = idx_alname + 1; enum distribute_type type = @@ -324,16 +334,17 @@ DEFUN (no_distribute_list, DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT; /* Set appropriate function call */ - int (*distfn)(const char *, enum distribute_type, - const char *) = + int (*distfn)(struct distribute_ctx *, const char *, + enum distribute_type, const char *) = prefix ? &distribute_list_prefix_unset : &distribute_list_unset; + struct distribute_ctx *ctx = listnode_head(dist_ctx_list); /* if interface is present, get name */ const char *ifname = NULL; if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; /* Get interface name corresponding distribute list. */ - int ret = distfn(ifname, type, argv[2 + prefix]->arg); + int ret = distfn(ctx, ifname, type, argv[2 + prefix]->arg); if (!ret) { vty_out(vty, "distribute list doesn't exist\n"); @@ -355,16 +366,17 @@ DEFUN (no_ipv6_distribute_list, "Interface name\n") { int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0; - int idx_alname = 3 + prefix; int idx_disttype = idx_alname + 1; enum distribute_type type = argv[idx_disttype]->arg[0] == 'i' ? DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT; + struct distribute_ctx *ctx = listnode_head(dist_ctx_list); /* Set appropriate function call */ - int (*distfn)(const char *, enum distribute_type, const char *) = + int (*distfn)(struct distribute_ctx *, const char *, + enum distribute_type, const char *) = prefix ? &distribute_list_prefix_unset : &distribute_list_unset; /* if interface is present, get name */ @@ -373,7 +385,7 @@ DEFUN (no_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; /* Get interface name corresponding distribute list. */ - int ret = distfn(ifname, type, argv[3 + prefix]->arg); + int ret = distfn(ctx, ifname, type, argv[3 + prefix]->arg); if (!ret) { vty_out(vty, "distribute list doesn't exist\n"); @@ -393,7 +405,7 @@ static int distribute_print(struct vty *vty, char *tab[], int is_prefix, return has_print; } -int config_show_distribute(struct vty *vty) +int config_show_distribute(struct vty *vty, struct distribute_ctx *dist_ctxt) { unsigned int i; int has_print = 0; @@ -401,7 +413,7 @@ int config_show_distribute(struct vty *vty) struct distribute *dist; /* Output filter configuration. */ - dist = distribute_lookup(NULL); + dist = distribute_lookup(dist_ctxt, NULL); vty_out(vty, " Outgoing update filter list for all interface is"); has_print = 0; if (dist) { @@ -419,8 +431,8 @@ int config_show_distribute(struct vty *vty) else vty_out(vty, " not set\n"); - for (i = 0; i < disthash->size; i++) - for (mp = disthash->index[i]; mp; mp = mp->next) { + for (i = 0; i < dist_ctxt->disthash->size; i++) + for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) { dist = mp->data; if (dist->ifname) { vty_out(vty, " %s filtered by", @@ -447,7 +459,7 @@ int config_show_distribute(struct vty *vty) /* Input filter configuration. */ - dist = distribute_lookup(NULL); + dist = distribute_lookup(dist_ctxt, NULL); vty_out(vty, " Incoming update filter list for all interface is"); has_print = 0; if (dist) { @@ -465,8 +477,8 @@ int config_show_distribute(struct vty *vty) else vty_out(vty, " not set\n"); - for (i = 0; i < disthash->size; i++) - for (mp = disthash->index[i]; mp; mp = mp->next) { + for (i = 0; i < dist_ctxt->disthash->size; i++) + for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) { dist = mp->data; if (dist->ifname) { vty_out(vty, " %s filtered by", @@ -494,7 +506,8 @@ int config_show_distribute(struct vty *vty) } /* Configuration write function. */ -int config_write_distribute(struct vty *vty) +int config_write_distribute(struct vty *vty, + struct distribute_ctx *dist_ctxt) { unsigned int i; int j; @@ -502,8 +515,8 @@ int config_write_distribute(struct vty *vty) struct hash_backet *mp; int write = 0; - for (i = 0; i < disthash->size; i++) - for (mp = disthash->index[i]; mp; mp = mp->next) { + for (i = 0; i < dist_ctxt->disthash->size; i++) + for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) { struct distribute *dist; dist = mp->data; @@ -543,19 +556,38 @@ int config_write_distribute(struct vty *vty) return write; } -/* Clear all distribute list. */ -void distribute_list_reset() +void distribute_list_delete(struct distribute_ctx **ctx) { - hash_clean(disthash, (void (*)(void *))distribute_free); + if ((*ctx)->disthash) { + hash_clean((*ctx)->disthash, (void (*)(void *))distribute_free); + } + if (!dist_ctx_list) + dist_ctx_list = list_new(); + listnode_delete(dist_ctx_list, *ctx); + if (list_isempty(dist_ctx_list)) + list_delete(&dist_ctx_list); + XFREE(MTYPE_DISTRIBUTE_CTX, (*ctx)); } -/* Initialize distribute list related hash. */ -void distribute_list_init(int node) +/* Initialize distribute list container */ +struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf) { - disthash = hash_create( + struct distribute_ctx *ctx; + + ctx = XCALLOC(MTYPE_DISTRIBUTE_CTX, sizeof(struct distribute_ctx)); + ctx->vrf = vrf; + ctx->disthash = hash_create( distribute_hash_make, (bool (*)(const void *, const void *))distribute_cmp, NULL); + if (!dist_ctx_list) + dist_ctx_list = list_new(); + listnode_add(dist_ctx_list, ctx); + return ctx; +} +/* Initialize distribute list vty commands */ +void distribute_list_init(int node) +{ /* vtysh command-extraction doesn't grok install_element(node, ) */ if (node == RIP_NODE) { install_element(RIP_NODE, &distribute_list_cmd); @@ -563,10 +595,7 @@ void distribute_list_init(int node) } else if (node == RIPNG_NODE) { install_element(RIPNG_NODE, &distribute_list_cmd); install_element(RIPNG_NODE, &no_distribute_list_cmd); - } - - /* install v6 */ - if (node == RIPNG_NODE) { + /* install v6 */ install_element(RIPNG_NODE, &ipv6_distribute_list_cmd); install_element(RIPNG_NODE, &no_ipv6_distribute_list_cmd); } diff --git a/lib/distribute.h b/lib/distribute.h index 35c5e0d6b6..44c699b38a 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -45,14 +45,36 @@ struct distribute { char *prefix[DISTRIBUTE_MAX]; }; +struct distribute_ctx { + /* Hash of distribute list. */ + struct hash *disthash; + + /* Hook functions. */ + void (*distribute_add_hook)(struct distribute_ctx *ctx, + struct distribute *dist); + void (*distribute_delete_hook)(struct distribute_ctx *ctx, + struct distribute *dist); + + /* vrf information */ + struct vrf *vrf; +}; + /* Prototypes for distribute-list. */ -extern void distribute_list_init(int); -extern void distribute_list_reset(void); -extern void distribute_list_add_hook(void (*)(struct distribute *)); -extern void distribute_list_delete_hook(void (*)(struct distribute *)); -extern struct distribute *distribute_lookup(const char *); -extern int config_write_distribute(struct vty *); -extern int config_show_distribute(struct vty *); +extern void distribute_list_init(int node); +extern struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf); +extern void distribute_list_delete(struct distribute_ctx **ctx); +extern void distribute_list_add_hook(struct distribute_ctx *ctx, + void (*)(struct distribute_ctx *ctx, + struct distribute *)); +extern void distribute_list_delete_hook(struct distribute_ctx *ctx, + void (*)(struct distribute_ctx *ctx, + struct distribute *)); +extern struct distribute *distribute_lookup(struct distribute_ctx *ctx, + const char *ifname); +extern int config_write_distribute(struct vty *vty, + struct distribute_ctx *ctx); +extern int config_show_distribute(struct vty *vty, + struct distribute_ctx *ctx); extern enum filter_type distribute_apply_in(struct interface *, struct prefix *); diff --git a/lib/vrf.c b/lib/vrf.c index 8409a1c9a1..0c82f6a3cd 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -330,6 +330,8 @@ vrf_id_t vrf_name_to_id(const char *name) vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid // id/ routine not used. + if (!name) + return vrf_id; vrf = vrf_lookup_by_name(name); if (vrf) vrf_id = vrf->vrf_id; diff --git a/ripd/ripd.c b/ripd/ripd.c index 59a8832257..0ce5324057 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -68,6 +68,9 @@ static void rip_output_process(struct connected *, struct sockaddr_in *, int, static int rip_triggered_update(struct thread *); static int rip_update_jitter(unsigned long); +static void rip_distribute_update(struct distribute_ctx *ctx, + struct distribute *dist); + /* RIP output routes type. */ enum { rip_all_route, rip_changed_route }; @@ -328,7 +331,7 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, } /* All interface filter check. */ - dist = distribute_lookup(NULL); + dist = distribute_lookup(rip->distribute_ctx, NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup(AFI_IP, @@ -2702,7 +2705,13 @@ 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; } @@ -3121,7 +3130,7 @@ DEFUN (show_ip_rip_status, vty_out(vty, " garbage collect after %u seconds\n", rip->garbage_time); /* Filtering status show. */ - config_show_distribute(vty); + config_show_distribute(vty, rip->distribute_ctx); /* Default metric information. */ vty_out(vty, " Default redistribution metric is %u\n", @@ -3215,7 +3224,8 @@ static int config_write_rip(struct vty *vty) nb_cli_show_dnode_cmds(vty, dnode, false); /* Distribute configuration. */ - write += config_write_distribute(vty); + write += config_write_distribute(vty, + rip->distribute_ctx); /* Interface routemap configuration */ write += config_write_if_rmap(vty); @@ -3227,7 +3237,8 @@ static int config_write_rip(struct vty *vty) static struct cmd_node rip_node = {RIP_NODE, "%s(config-router)# ", 1}; /* Distribute-list update functions. */ -static void rip_distribute_update(struct distribute *dist) +static void rip_distribute_update(struct distribute_ctx *ctx, + struct distribute *dist) { struct interface *ifp; struct rip_interface *ri; @@ -3288,9 +3299,11 @@ void rip_distribute_update_interface(struct interface *ifp) { struct distribute *dist; - dist = distribute_lookup(ifp->name); + if (!rip) + return; + dist = distribute_lookup(rip->distribute_ctx, ifp->name); if (dist) - rip_distribute_update(dist); + rip_distribute_update(rip->distribute_ctx, dist); } /* Update all interface's distribute list. */ @@ -3367,6 +3380,7 @@ void rip_clean(void) route_table_finish(rip->table); route_table_finish(rip->neighbor); + distribute_list_delete(&rip->distribute_ctx); XFREE(MTYPE_RIP, rip); rip = NULL; } @@ -3390,7 +3404,6 @@ static void rip_if_rmap_update(struct if_rmap *if_rmap) return; ri = ifp->info; - if (if_rmap->routemap[IF_RMAP_IN]) { rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]); if (rmap) @@ -3472,8 +3485,6 @@ void rip_init(void) /* Distribute list install. */ distribute_list_init(RIP_NODE); - distribute_list_add_hook(rip_distribute_update); - distribute_list_delete_hook(rip_distribute_update); /* Route-map */ rip_route_map_init(); diff --git a/ripd/ripd.h b/ripd/ripd.h index 91fab2a7a2..7b8fe3a906 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -23,6 +23,7 @@ #include "hook.h" #include "nexthop.h" +#include "distribute.h" #include "rip_memory.h" /* RIP version number. */ @@ -150,6 +151,9 @@ struct rip { bool metric_config; uint8_t metric; } route_map[ZEBRA_ROUTE_MAX]; + + /* For distribute-list container */ + struct distribute_ctx *distribute_ctx; }; /* RIP routing table entry which belong to rip_packet. */ diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 4ec9209da7..ae8e8ab7d9 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -52,6 +52,9 @@ enum { ripng_all_route, ripng_changed_route, }; +static void ripng_distribute_update(struct distribute_ctx *ctx, + struct distribute *dist); + /* Prototypes. */ void ripng_output_process(struct interface *, struct sockaddr_in6 *, int); @@ -619,7 +622,7 @@ static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p, } /* All interface filter check. */ - dist = distribute_lookup(NULL); + dist = distribute_lookup(ripng->distribute_ctx, NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup(AFI_IP6, @@ -1806,6 +1809,13 @@ int ripng_create(int socket) /* Initialize RIPng routig table. */ ripng->table = agg_table_init(); + /* Distribute list install. */ + ripng->distribute_ctx = distribute_list_ctx_create( + vrf_lookup_by_id(VRF_DEFAULT)); + 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; @@ -2071,7 +2081,7 @@ DEFUN (show_ipv6_ripng_status, ripng->garbage_time); /* Filtering status show. */ - config_show_distribute(vty); + config_show_distribute(vty, ripng->distribute_ctx); /* Default metric information. */ vty_out(vty, " Default redistribution metric is %d\n", @@ -2290,7 +2300,8 @@ static int ripng_config_write(struct vty *vty) if (dnode) { nb_cli_show_dnode_cmds(vty, dnode, false); - config_write_distribute(vty); + config_write_distribute(vty, + ripng->distribute_ctx); config_write_if_rmap(vty); @@ -2305,7 +2316,8 @@ static struct cmd_node cmd_ripng_node = { RIPNG_NODE, "%s(config-router)# ", 1, }; -static void ripng_distribute_update(struct distribute *dist) +static void ripng_distribute_update(struct distribute_ctx *ctx, + struct distribute *dist) { struct interface *ifp; struct ripng_interface *ri; @@ -2366,9 +2378,11 @@ void ripng_distribute_update_interface(struct interface *ifp) { struct distribute *dist; - dist = distribute_lookup(ifp->name); + if (!ripng) + return; + dist = distribute_lookup(ripng->distribute_ctx, ifp->name); if (dist) - ripng_distribute_update(dist); + ripng_distribute_update(ripng->distribute_ctx, dist); } /* Update all interface's distribute list. */ @@ -2450,6 +2464,7 @@ void ripng_clean() stream_free(ripng->ibuf); stream_free(ripng->obuf); + distribute_list_delete(&ripng->distribute_ctx); XFREE(MTYPE_RIPNG, ripng); ripng = NULL; } /* if (ripng) */ @@ -2563,8 +2578,6 @@ void ripng_init() /* Distribute list install. */ distribute_list_init(RIPNG_NODE); - distribute_list_add_hook(ripng_distribute_update); - distribute_list_delete_hook(ripng_distribute_update); /* Route-map for interface. */ ripng_route_map_init(); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 5b32374ace..1db7a83b11 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -24,6 +24,7 @@ #include #include +#include #include "ripng_memory.h" @@ -128,6 +129,9 @@ struct ripng { bool metric_config; uint8_t metric; } route_map[ZEBRA_ROUTE_MAX]; + + /* For distribute-list container */ + struct distribute_ctx *distribute_ctx; }; /* Routing table entry. */