summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zebra/main.c2
-rw-r--r--zebra/zebra_dplane.c108
-rw-r--r--zebra/zebra_dplane.h20
-rw-r--r--zebra/zebra_vty.c41
4 files changed, 156 insertions, 15 deletions
diff --git a/zebra/main.c b/zebra/main.c
index 148bcab7e4..33730be923 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -171,6 +171,8 @@ static void sigint(void)
route_map_finish();
list_delete(&zebrad.client_list);
+ zebra_dplane_finish();
+
work_queue_free_and_null(&zebrad.ribq);
meta_queue_free(zebrad.mq);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 4f54b3440b..468611e6f6 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -17,11 +17,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "lib/zebra.h"
#include "lib/libfrr.h"
-#include "lib/memory.h"
+#include "lib/debug.h"
+#include "lib/frratomic.h"
#include "lib/frr_pthread.h"
+#include "lib/memory.h"
#include "lib/queue.h"
+#include "lib/zebra.h"
#include "zebra/zebra_memory.h"
#include "zebra/zserv.h"
#include "zebra/zebra_dplane.h"
@@ -135,6 +137,9 @@ struct zebra_dplane_provider_s {
dplane_provider_fini_fp dp_fini;
+ _Atomic uint64_t dp_in_counter;
+ _Atomic uint64_t dp_error_counter;
+
/* Embedded list linkage */
TAILQ_ENTRY(zebra_dplane_provider_s) dp_q_providers;
@@ -150,15 +155,22 @@ static struct zebra_dplane_globals_s {
/* Results callback registered by zebra 'core' */
dplane_results_fp dg_results_cb;
+ /* Sentinel for shutdown */
+ volatile bool dg_run;
+
/* Route-update context queue inbound to the dataplane */
TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx_s) dg_route_ctx_q;
/* Ordered list of providers */
TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider_s) dg_providers_q;
- /* Counter used to assign ids to providers */
+ /* Counter used to assign internal ids to providers */
uint32_t dg_provider_id;
+ _Atomic uint64_t dg_routes_in;
+ _Atomic uint32_t dg_routes_queued;
+ _Atomic uint64_t dg_route_errors;
+
/* Event-delivery context 'master' for the dplane */
struct thread_master *dg_master;
@@ -653,10 +665,19 @@ dplane_route_update_internal(struct route_node *rn,
}
done:
- if (ret == AOK)
+ /* Update counters */
+ atomic_fetch_add_explicit(&zdplane_g.dg_routes_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK) {
+ atomic_fetch_add_explicit(&zdplane_g.dg_routes_queued, 1,
+ memory_order_relaxed);
result = ZEBRA_DPLANE_REQUEST_QUEUED;
- else if (ctx)
+ } else if (ctx) {
+ atomic_fetch_add_explicit(&zdplane_g.dg_route_errors, 1,
+ memory_order_relaxed);
dplane_ctx_free(&ctx);
+ }
return result;
}
@@ -724,12 +745,18 @@ static int dplane_route_process(struct thread *event)
dplane_ctx_h ctx;
while (1) {
+ /* Check for shutdown */
+ if (!zdplane_g.dg_run)
+ break;
+
/* TODO -- limit number of updates per cycle? */
ctx = dplane_route_dequeue();
if (ctx == NULL)
break;
- /* TODO -- support series of providers */
+ /* Update counter */
+ atomic_fetch_sub_explicit(&zdplane_g.dg_routes_queued, 1,
+ memory_order_relaxed);
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
char dest_str[PREFIX_STRLEN];
@@ -737,14 +764,20 @@ static int dplane_route_process(struct thread *event)
prefix2str(dplane_ctx_get_dest(ctx),
dest_str, sizeof(dest_str));
- zlog_debug("%u:%s Dplane update ctx %p op %s",
+ zlog_debug("%u:%s Dplane route update ctx %p op %s",
dplane_ctx_get_vrf(ctx), dest_str,
ctx, dplane_op2str(dplane_ctx_get_op(ctx)));
}
+ /* TODO -- support series of providers */
+
/* Initially, just doing kernel-facing update here */
res = kernel_route_update(ctx);
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(&zdplane_g.dg_route_errors, 1,
+ memory_order_relaxed);
+
ctx->zd_status = res;
/* Enqueue result to zebra main context */
@@ -757,6 +790,38 @@ static int dplane_route_process(struct thread *event)
}
/*
+ * Handler for 'show dplane'
+ */
+int dplane_show_helper(struct vty *vty, bool detailed)
+{
+ uint64_t queued, errs, incoming;
+
+ incoming = atomic_load_explicit(&zdplane_g.dg_routes_in,
+ memory_order_relaxed);
+ queued = atomic_load_explicit(&zdplane_g.dg_routes_queued,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_g.dg_route_errors,
+ memory_order_relaxed);
+
+ vty_out(vty, "Route updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "Route update errors: %"PRIu64"\n", errs);
+ vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued);
+
+ return CMD_SUCCESS;
+}
+
+/*
+ * Handler for 'show dplane providers'
+ */
+int dplane_show_provs_helper(struct vty *vty, bool detailed)
+{
+ vty_out(vty, "Zebra dataplane providers:%s\n",
+ (detailed ? " (detailed)" : ""));
+
+ return CMD_SUCCESS;
+}
+
+/*
* Provider registration
*/
int dplane_provider_register(const char *name,
@@ -839,6 +904,8 @@ static void zebra_dplane_init_internal(struct zebra_t *zebra)
/* TODO -- register default kernel 'provider' during init */
+ zdplane_g.dg_run = true;
+
/* TODO -- start dataplane pthread. We're using the zebra
* core/main thread temporarily
*/
@@ -846,13 +913,26 @@ static void zebra_dplane_init_internal(struct zebra_t *zebra)
}
/*
- * Shutdown, de-init hook callback. This runs pretty early during shutdown.
+ * Shutdown, de-init api. This runs pretty late during shutdown,
+ * because zebra tries to free/remove/uninstall all routes during shutdown.
+ * NB: This runs in the main zebra thread context.
*/
-static int zebra_dplane_fini(void)
+void zebra_dplane_finish(void)
{
- /* TODO -- stop thread, clean queues */
+ /* Wait until all pending updates are processed */
+
+ /* Stop dplane thread, if it's running */
+
+ zdplane_g.dg_run = false;
+
+ THREAD_OFF(zdplane_g.dg_t_update);
+
+ /* Notify provider(s) of shutdown */
+
+ /* Clean-up provider objects */
+
+ /* Clean queue(s) */
- return 0;
}
/*
@@ -862,6 +942,8 @@ void zebra_dplane_init(void)
{
zebra_dplane_init_internal(&zebrad);
- /* Register for shutdown/de-init */
- hook_register(frr_early_fini, zebra_dplane_fini);
+ /* Finalize/cleanup code is called quite late during zebra shutdown;
+ * zebra expects to try to clean up all vrfs and all routes during
+ * shutdown, so the dplane must be available until very late.
+ */
}
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 88e671e615..aa7443cf85 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -182,6 +182,17 @@ enum zebra_dplane_result dplane_route_update(struct route_node *rn,
enum zebra_dplane_result dplane_route_delete(struct route_node *rn,
struct route_entry *re);
+/*
+ * Vty/cli apis
+ */
+int dplane_show_helper(struct vty *vty, bool detailed);
+int dplane_show_provs_helper(struct vty *vty, bool detailed);
+
+
+/*
+ * Dataplane providers: modules that consume dataplane events.
+ */
+
/* Support string name for a dataplane provider */
#define DPLANE_PROVIDER_NAMELEN 64
@@ -224,8 +235,15 @@ typedef int (*dplane_results_fp)(const dplane_ctx_h ctx);
int dplane_results_register(dplane_results_fp fp);
/*
- * Initialize the dataplane modules at zebra startup.
+ * Initialize the dataplane modules at zebra startup. This is currently called
+ * by the rib module.
*/
void zebra_dplane_init(void);
+/* Finalize/cleanup api, called quite late during zebra shutdown.
+ * Zebra expects to try to clean up all vrfs and all routes during
+ * shutdown, so the dplane must be available until very late.
+ */
+void zebra_dplane_finish(void);
+
#endif /* _ZEBRA_DPLANE_H */
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index fdedb30f84..d9881b98c5 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -2567,6 +2567,44 @@ DEFUN (no_ipv6_forwarding,
return CMD_SUCCESS;
}
+/* Display dataplane info */
+DEFUN (show_dataplane,
+ show_dataplane_cmd,
+ "show zebra dplane [detailed]",
+ SHOW_STR
+ ZEBRA_STR
+ "Zebra dataplane information\n"
+ "Detailed output\n")
+{
+ int idx = 0;
+ bool detailed = false;
+
+ if (argv_find(argv, argc, "detailed", &idx))
+ detailed = true;
+
+ return dplane_show_helper(vty, detailed);
+}
+
+/* Display dataplane providers info */
+DEFUN (show_dataplane_providers,
+ show_dataplane_providers_cmd,
+ "show zebra dplane providers [detailed]",
+ SHOW_STR
+ ZEBRA_STR
+ "Zebra dataplane information\n"
+ "Zebra dataplane provider information\n"
+ "Detailed output\n")
+{
+ int idx = 0;
+ bool detailed = false;
+
+ if (argv_find(argv, argc, "detailed", &idx))
+ detailed = true;
+
+ return dplane_show_provs_helper(vty, detailed);
+}
+
+
/* Table configuration write function. */
static int config_write_table(struct vty *vty)
{
@@ -2697,5 +2735,6 @@ void zebra_vty_init(void)
install_element(VRF_NODE, &vrf_vni_mapping_cmd);
install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
-
+ install_element(VIEW_NODE, &show_dataplane_cmd);
+ install_element(VIEW_NODE, &show_dataplane_providers_cmd);
}