zebra: begin dataplane notifications

Add dataplane route notification type; add handler for zebra
routes.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2019-03-20 16:40:27 -04:00
parent 5695d9ac5d
commit 54818e3b01
3 changed files with 93 additions and 2 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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: