From: Mark Stapp Date: Wed, 20 Mar 2019 20:40:27 +0000 (-0400) Subject: zebra: begin dataplane notifications X-Git-Tag: base_7.2~300^2~9 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=54818e3b017943bddb113f2c62275119edd085fe;p=matthieu%2Ffrr.git zebra: begin dataplane notifications Add dataplane route notification type; add handler for zebra routes. Signed-off-by: Mark Stapp --- diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 92a401b7e8..3ded32ea19 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -394,6 +394,7 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx) case DPLANE_OP_ROUTE_DELETE: case DPLANE_OP_SYS_ROUTE_ADD: case DPLANE_OP_SYS_ROUTE_DELETE: + case DPLANE_OP_ROUTE_NOTIFY: /* Free allocated nexthops */ if ((*pctx)->u.rinfo.zd_ng.nexthop) { @@ -571,6 +572,9 @@ const char *dplane_op2str(enum dplane_op_e op) case DPLANE_OP_ROUTE_DELETE: ret = "ROUTE_DELETE"; break; + case DPLANE_OP_ROUTE_NOTIFY: + ret = "ROUTE_NOTIFY"; + break; case DPLANE_OP_LSP_INSTALL: ret = "LSP_INSTALL"; @@ -2211,9 +2215,10 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) res = kernel_dplane_address_update(ctx); break; - /* Ignore system 'notifications' - the kernel already knows */ + /* Ignore 'notifications' */ case DPLANE_OP_SYS_ROUTE_ADD: case DPLANE_OP_SYS_ROUTE_DELETE: + case DPLANE_OP_ROUTE_NOTIFY: res = ZEBRA_DPLANE_REQUEST_SUCCESS; break; @@ -2656,7 +2661,6 @@ static int dplane_thread_loop(struct thread *event) TAILQ_INIT(&error_list); - /* Call through to zebra main */ (zdplane_info.dg_results_cb)(&work_list); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 1d4056c815..cffcb94d45 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -105,6 +105,7 @@ enum dplane_op_e { DPLANE_OP_ROUTE_INSTALL, DPLANE_OP_ROUTE_UPDATE, DPLANE_OP_ROUTE_DELETE, + DPLANE_OP_ROUTE_NOTIFY, /* LSP update */ DPLANE_OP_LSP_INSTALL, diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 977316ef7c..51aef4747d 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2145,6 +2145,88 @@ done: dplane_ctx_fini(&ctx); } +/* + * Handle notification from async dataplane: the dataplane has detected + * some change to a route, and notifies zebra so that the control plane + * can reflect that change. + */ +static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) +{ + struct route_node *rn = NULL; + struct route_entry *re = NULL, *rib; + char dest_str[PREFIX_STRLEN] = ""; + const struct prefix *dest_pfx, *src_pfx; + bool changed_p = false; + + dest_pfx = dplane_ctx_get_dest(ctx); + + /* Note well: only capturing the prefix string if debug is enabled here; + * unconditional log messages will have to generate the string. + */ + if (IS_ZEBRA_DEBUG_DPLANE) + prefix2str(dest_pfx, dest_str, sizeof(dest_str)); + + /* Locate rn and re(s) from ctx */ + rn = rib_find_rn_from_ctx(ctx); + if (rn == NULL) { + if (IS_ZEBRA_DEBUG_DPLANE) { + zlog_debug("Failed to process dplane notification: no route for %u:%s", + dplane_ctx_get_vrf(ctx), dest_str); + } + goto done; + } + + route_unlock_node(rn); + + srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) + zlog_debug("%u:%s Processing dplane notif ctx %p", + dplane_ctx_get_vrf(ctx), dest_str, ctx); + + /* + * Take a pass through the routes, look for matches with the context + * info. + */ + RNODE_FOREACH_RE(rn, rib) { + + if (re == NULL) { + if (rib_route_match_ctx(rib, ctx, false)) + re = rib; + } + + /* Have we found the route we need to work on? */ + if (re) + break; + } + + /* No match? Nothing we can do */ + if (re == NULL) { + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("Unable to process dplane notification: no entry for %u:%s, type %d", + dplane_ctx_get_vrf(ctx), dest_str, + dplane_ctx_get_type(ctx)); + + goto done; + } + + /* Update zebra's nexthop FIB flags based on the context struct's + * nexthops. + */ + rib_update_re_from_ctx(re, rn, ctx); + + /* TODO -- we'd like to know about this possibility? */ + if (!changed_p) { + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) + zlog_debug("%u:%s No change from dplane notification", + dplane_ctx_get_vrf(ctx), dest_str); + } + +done: + /* Return context to dataplane module */ + dplane_ctx_fini(&ctx); +} + /* Take a list of route_node structs and return 1, if there was a record * picked from it and processed by rib_process(). Don't process more, * than one RN record; operate only in the specified sub-queue. @@ -3365,6 +3447,10 @@ static int rib_process_dplane_results(struct thread *thread) rib_process_result(ctx); break; + case DPLANE_OP_ROUTE_NOTIFY: + rib_process_dplane_notify(ctx); + break; + case DPLANE_OP_LSP_INSTALL: case DPLANE_OP_LSP_UPDATE: case DPLANE_OP_LSP_DELETE: