summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/rt_netlink.c7
-rw-r--r--zebra/sample_plugin.c134
-rw-r--r--zebra/zebra_dplane.c4
-rw-r--r--zebra/zebra_mpls.c40
-rw-r--r--zebra/zebra_nhg.c47
-rw-r--r--zebra/zebra_rib.c8
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)