diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/rt_netlink.c | 7 | ||||
| -rw-r--r-- | zebra/sample_plugin.c | 134 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_mpls.c | 40 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 47 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 8 |
6 files changed, 205 insertions, 35 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 915ad1a10c..c9a9a81b18 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2456,7 +2456,6 @@ int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) return 0; } -#if 0 /* Force off kernel nexthop group installs for now */ /** * netlink_request_nexthop() - Request nextop information from the kernel * @zns: Zebra namespace @@ -2515,12 +2514,6 @@ int netlink_nexthop_read(struct zebra_ns *zns) return ret; } -#else -int netlink_nexthop_read(struct zebra_ns *zns) -{ - return 0; -} -#endif int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, diff --git a/zebra/sample_plugin.c b/zebra/sample_plugin.c new file mode 100644 index 0000000000..c96a86cc73 --- /dev/null +++ b/zebra/sample_plugin.c @@ -0,0 +1,134 @@ +/* + * Sample plugin for the FRR zebra dataplane. + * + * Copyright (c) 2019 Volta Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Should be possible to build this plugin using this sort of command: + * + * gcc -I ~/work/frr/ -I ~/work/frr/lib -I ~/work/frr/zebra \ + * -g -O0 -o sample_plugin.so -shared -fPIC sample_plugin.c + * + * where 'frr' is a configured and built frr sandbox. + * + * Run zebra with '-M /path/to/sample_plugin.so' to load the module. + */ + +#include "config.h" /* Include this explicitly */ +#include "lib/zebra.h" +#include "lib/libfrr.h" +#include "zebra/zebra_dplane.h" +#include "zebra/debug.h" + +static const char *plugin_name = "SAMPLE"; + +static struct zebra_dplane_provider *prov_p; + +/* + * Startup/init callback, called from the dataplane. + */ +static int sample_start(struct zebra_dplane_provider *prov) +{ + /* Nothing special to do - we don't allocate anything. */ + return 0; +} + + +/* + * Shutdown/cleanup callback, called from the dataplane pthread. + */ +static int sample_fini(struct zebra_dplane_provider *prov, bool early) +{ + /* Nothing special to do. */ + return 0; +} + +/* + * Callback from the dataplane to process incoming work; this runs in the + * dplane pthread. + */ +static int sample_process(struct zebra_dplane_provider *prov) +{ + int counter, limit; + struct zebra_dplane_ctx *ctx; + + limit = dplane_provider_get_work_limit(prov_p); + + /* Respect the configured limit on the amount of work to do in + * any one call. + */ + for (counter = 0; counter < limit; counter++) { + ctx = dplane_provider_dequeue_in_ctx(prov_p); + if (!ctx) + break; + + /* Just set 'success' status and return to the dataplane */ + dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS); + dplane_provider_enqueue_out_ctx(prov_p, ctx); + } + + return 0; +} + +/* + * Init entry point called during zebra startup. This is registered during + * module init. + */ +static int init_sample_plugin(struct thread_master *tm) +{ + int ret; + struct zebra_dplane_provider *prov = NULL; + + /* Note that we don't use or store the thread_master 'tm'. We + * don't use the zebra main pthread: our plugin code will run in + * the zebra dataplane pthread context. + */ + + /* Register the plugin with the dataplane infrastructure. We + * register to be called before the kernel, and we register + * our init, process work, and shutdown callbacks. + */ + ret = dplane_provider_register(plugin_name, DPLANE_PRIO_PRE_KERNEL, + DPLANE_PROV_FLAGS_DEFAULT, + sample_start, + sample_process, + sample_fini, + NULL, + &prov_p); + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("sample plugin register => %d", ret); + + return 0; +} + +/* + * Base FRR loadable module info: basic info including module entry-point. + */ +static int module_init(void) +{ + hook_register(frr_late_init, init_sample_plugin); + return 0; +} + +FRR_MODULE_SETUP( + .name = "dplane_sample", + .version = "0.0.1", + .description = "Dataplane Sample Plugin", + .init = module_init, + ) diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index a88b0a38da..7f993442a6 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3752,7 +3752,9 @@ void zebra_dplane_shutdown(void) zdplane_info.dg_run = false; - THREAD_OFF(zdplane_info.dg_t_update); + if (zdplane_info.dg_t_update) + thread_cancel_async(zdplane_info.dg_t_update->master, + &zdplane_info.dg_t_update, NULL); frr_pthread_stop(zdplane_info.dg_pthread, NULL); diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index ef1bd02608..6942a37989 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -2565,6 +2565,16 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, fec_print(rn->info, vty); } +static void mpls_zebra_nhg_update(struct route_entry *re, afi_t afi, + struct nexthop_group *new_grp) +{ + struct nhg_hash_entry *nhe; + + nhe = zebra_nhg_rib_find(0, new_grp, afi); + + zebra_nhg_re_update_ref(re, nhe); +} + static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop, enum lsp_types_t type, mpls_label_t label) { @@ -2591,7 +2601,6 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, struct route_entry *re; struct nexthop *nexthop; struct nexthop_group new_grp = {}; - struct nhg_hash_entry *nhe = NULL; bool found; afi_t afi = family2afi(prefix->family); @@ -2658,12 +2667,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, } if (found) { - nhe = zebra_nhg_rib_find(0, &new_grp, afi); - - zebra_nhg_re_update_ref(re, nhe); - SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); + + mpls_zebra_nhg_update(re, afi, &new_grp); + rib_queue_add(rn); } @@ -2680,10 +2688,11 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, struct route_node *rn; struct route_entry *re; struct nexthop *nexthop; + struct nexthop_group new_grp = {}; + afi_t afi = family2afi(prefix->family); /* Lookup table. */ - table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST, - zvrf_id(zvrf)); + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); if (!table) return -1; @@ -2698,11 +2707,18 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, if (re == NULL) return -1; - for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) + nexthop_group_copy(&new_grp, re->ng); + + for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) nexthop_del_labels(nexthop); SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); + + mpls_zebra_nhg_update(re, afi, &new_grp); + + nexthops_free(new_grp.nexthop); + rib_queue_add(rn); return 0; @@ -2904,7 +2920,6 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf, update = 0; RNODE_FOREACH_RE (rn, re) { struct nexthop_group new_grp = {}; - struct nhg_hash_entry *nhe = NULL; nexthop_group_copy(&new_grp, re->ng); @@ -2920,11 +2935,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf, update = 1; } - if (CHECK_FLAG(re->status, - ROUTE_ENTRY_LABELS_CHANGED)) { - nhe = zebra_nhg_rib_find(0, &new_grp, afi); - zebra_nhg_re_update_ref(re, nhe); - } + if (CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED)) + mpls_zebra_nhg_update(re, afi, &new_grp); nexthops_free(new_grp.nexthop); } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 05da25b2b8..d33f3a432a 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -360,6 +360,8 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) { const struct nhg_hash_entry *nhe1 = arg1; const struct nhg_hash_entry *nhe2 = arg2; + struct nexthop *nexthop1; + struct nexthop *nexthop2; /* No matter what if they equal IDs, assume equal */ if (nhe1->id && nhe2->id && (nhe1->id == nhe2->id)) @@ -371,12 +373,47 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) if (nhe1->afi != nhe2->afi) return false; - if (nexthop_group_active_nexthop_num_no_recurse(nhe1->nhg) - != nexthop_group_active_nexthop_num_no_recurse(nhe2->nhg)) - return false; + /* Nexthops should be sorted */ + for (nexthop1 = nhe1->nhg->nexthop, nexthop2 = nhe2->nhg->nexthop; + nexthop1 || nexthop2; + nexthop1 = nexthop1->next, nexthop2 = nexthop2->next) { + if (nexthop1 && !nexthop2) + return false; - if (!nexthop_group_equal_no_recurse(nhe1->nhg, nhe2->nhg)) - return false; + if (!nexthop1 && nexthop2) + return false; + + /* + * We have to check the active flag of each individual one, + * not just the overall active_num. This solves the special case + * issue of a route with a nexthop group with one nexthop + * resolving to itself and thus marking it inactive. If we + * have two different routes each wanting to mark a different + * nexthop inactive, they need to hash to two different groups. + * + * If we just hashed on num_active, they would hash the same + * which is incorrect. + * + * ex) + * 1.1.1.0/24 + * -> 1.1.1.1 dummy1 (inactive) + * -> 1.1.2.1 dummy2 + * + * 1.1.2.0/24 + * -> 1.1.1.1 dummy1 + * -> 1.1.2.1 dummy2 (inactive) + * + * Without checking each individual one, they would hash to + * the same group and both have 1.1.1.1 dummy1 marked inactive. + * + */ + if (CHECK_FLAG(nexthop1->flags, NEXTHOP_FLAG_ACTIVE) + != CHECK_FLAG(nexthop2->flags, NEXTHOP_FLAG_ACTIVE)) + return false; + + if (!nexthop_same(nexthop1, nexthop2)) + return false; + } return true; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index c24a518afb..781963793e 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -570,14 +570,6 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, nexthops_free(old->fib_ng.nexthop); old->fib_ng.nexthop = NULL; } - - if (!RIB_SYSTEM_ROUTE(old)) { - /* Clear old route's FIB flags */ - for (ALL_NEXTHOPS_PTR(old->ng, nexthop)) { - UNSET_FLAG(nexthop->flags, - NEXTHOP_FLAG_FIB); - } - } } if (zvrf) |
