From b8e0423d91609f098eb7bce3f628e0cda7ebdd05 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 9 Jul 2018 16:00:09 -0400 Subject: [PATCH] zebra: start sketching dataplane provider api Initial WIP api to add providers into the zebra dataplane system, with some simple ordering/prioritization. Signed-off-by: Mark Stapp --- zebra/zebra_dplane.c | 92 ++++++++++++++++++++++++++++++++++++++++---- zebra/zebra_dplane.h | 1 + zebra/zebra_memory.h | 1 + 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 7ec0b6e9cb..03cad8fb35 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -29,6 +29,7 @@ /* Memory type for context blocks */ DEFINE_MTYPE(ZEBRA, DP_CTX, "Zebra DPlane Ctx") +DEFINE_MTYPE(ZEBRA, DP_PROV, "Zebra DPlane Provider") #ifndef AOK # define AOK 0 @@ -104,6 +105,8 @@ struct zebra_dplane_ctx_s { /* Nexthops */ struct nexthop_group zd_ng; + /* TODO -- use fixed array of nexthops, to avoid mallocs? */ + /* Embedded list linkage */ TAILQ_ENTRY(zebra_dplane_ctx_s) zd_q_entries; @@ -125,10 +128,12 @@ struct zebra_dplane_provider_s { uint32_t dp_id; /* Event pointer for use by the dplane thread */ - struct thread *dp_t_event; +// struct thread *dp_t_event; + + dplane_provider_process_fp dp_fp; /* Embedded list linkage */ - TAILQ_ENTRY(zebra_dplane_dest_s) dp_q_providers; + TAILQ_ENTRY(zebra_dplane_provider_s) dp_q_providers; }; @@ -148,6 +153,9 @@ static struct zebra_dplane_globals_s { /* Ordered list of providers */ TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider_s) dg_providers_q; + /* Counter used to assign ids to providers */ + uint32_t dg_provider_id; + /* Event-delivery context 'master' for the dplane */ struct thread_master *dg_master; @@ -171,12 +179,16 @@ static int dplane_route_process(struct thread *event); */ /* - * Allocate an opaque context block + * Allocate a dataplane update context */ dplane_ctx_h dplane_ctx_alloc(void) { struct zebra_dplane_ctx_s *p; + /* TODO -- just alloc'ing memory, but would like to maintain + * a pool + */ + p = XCALLOC(MTYPE_DP_CTX, sizeof(struct zebra_dplane_ctx_s)); if (p) { p->zd_magic = DPLANE_CTX_MAGIC; @@ -186,13 +198,17 @@ dplane_ctx_h dplane_ctx_alloc(void) } /* - * Free memory for a dataplane results context block. + * Free a dataplane results context. */ static void dplane_ctx_free(dplane_ctx_h *pctx) { if (pctx) { DPLANE_CTX_VALID(*pctx); + /* TODO -- just freeing memory, but would like to maintain + * a pool + */ + /* Free embedded nexthops */ if ((*pctx)->zd_ng.nexthop) { /* This deals with recursive nexthops too */ @@ -513,6 +529,8 @@ static int dplane_ctx_route_init(dplane_ctx_h ctx, /* Copy nexthops; recursive info is included too */ copy_nexthops(&(ctx->zd_ng.nexthop), re->ng.nexthop, NULL); + /* TODO -- maybe use array of nexthops to avoid allocs? */ + /* Trying out the sequence number idea, so we can try to detect * when a result is stale. */ @@ -595,7 +613,8 @@ dplane_route_update_internal(struct route_node *rn, /* Capture some extra info for update case * where there's a different 'old' route. */ - if ((op == DPLANE_OP_ROUTE_UPDATE) && old_re && (old_re != re)) { + if ((op == DPLANE_OP_ROUTE_UPDATE) && + old_re && (old_re != re)) { ctx->zd_is_update = true; old_re->dplane_sequence++; @@ -693,6 +712,8 @@ static int dplane_route_process(struct thread *event) break; } + /* TODO -- support series of providers */ + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { char dest_str[PREFIX_STRLEN]; @@ -704,12 +725,11 @@ static int dplane_route_process(struct thread *event) ctx, dplane_op2str(dplane_ctx_get_op(ctx))); } + /* Initially, just doing kernel-facing update here */ res = kernel_route_update(ctx); ctx->zd_status = res; - /* TODO -- support series of providers */ - /* Enqueue result to zebra main context */ (*zdplane_g.dg_results_cb)(ctx); @@ -719,6 +739,60 @@ static int dplane_route_process(struct thread *event) return (0); } +/* + * Provider registration + */ +int dplane_provider_register(const char *name, + dplane_provider_prio_e prio, + dplane_provider_process_fp fp) +{ + int ret = 0; + struct zebra_dplane_provider_s *p, *last; + + /* Validate */ + if (fp == NULL) { + ret = EINVAL; + goto done; + } + + if (prio <= DPLANE_PRIO_NONE || + prio >= DPLANE_PRIO_LAST) { + ret = EINVAL; + goto done; + } + + /* Allocate and init new provider struct */ + p = XCALLOC(MTYPE_DP_PROV, sizeof(struct zebra_dplane_provider_s)); + if (p == NULL) { + ret = ENOMEM; + goto done; + } + + strncpy(p->dp_name, name, DPLANE_PROVIDER_NAMELEN); + p->dp_name[DPLANE_PROVIDER_NAMELEN] = '\0'; + + p->dp_priority = prio; + p->dp_fp = fp; + + p->dp_id = ++zdplane_g.dg_provider_id; + + /* Insert into list ordered by priority */ + TAILQ_FOREACH(last, &zdplane_g.dg_providers_q, dp_q_providers) { + if (last->dp_priority > p->dp_priority) { + break; + } + } + + if (last) { + TAILQ_INSERT_BEFORE(last, p, dp_q_providers); + } else { + TAILQ_INSERT_TAIL(&zdplane_g.dg_providers_q, p, dp_q_providers); + } + +done: + return (ret); +} + /* * Zebra registers a results callback with the dataplane system */ @@ -740,6 +814,8 @@ static void zebra_dplane_init_internal(struct zebra_t *zebra) TAILQ_INIT(&zdplane_g.dg_route_ctx_q); TAILQ_INIT(&zdplane_g.dg_providers_q); + /* TODO -- register kernel 'provider' during init */ + /* TODO -- using zebra core event thread temporarily */ zdplane_g.dg_master = zebra->master; @@ -747,7 +823,7 @@ static void zebra_dplane_init_internal(struct zebra_t *zebra) } /* - * Initialize the dataplane module at startup. + * Initialize the dataplane module at startup; called by zebra rib_init() */ void zebra_dplane_init(void) { diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 364d77db43..fcc70e99bf 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -201,6 +201,7 @@ typedef enum { DPLANE_PRIO_PRE_KERNEL, DPLANE_PRIO_KERNEL, DPLANE_PRIO_POSTPROCESS, + DPLANE_PRIO_LAST } dplane_provider_prio_e; /* Provider's entry-point to process a context block */ diff --git a/zebra/zebra_memory.h b/zebra/zebra_memory.h index fcabab97c5..de55478de2 100644 --- a/zebra/zebra_memory.h +++ b/zebra/zebra_memory.h @@ -35,5 +35,6 @@ DECLARE_MTYPE(RIB_DEST) DECLARE_MTYPE(RIB_TABLE_INFO) DECLARE_MTYPE(RNH) DECLARE_MTYPE(DP_CTX) +DECLARE_MTYPE(DP_PROV) #endif /* _QUAGGA_ZEBRA_MEMORY_H */ -- 2.39.5