]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: begin dataplane notifications
authorMark Stapp <mjs@voltanet.io>
Wed, 20 Mar 2019 20:40:27 +0000 (16:40 -0400)
committerMark Stapp <mjs@voltanet.io>
Tue, 28 May 2019 12:22:27 +0000 (08:22 -0400)
Add dataplane route notification type; add handler for zebra
routes.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_rib.c

index 92a401b7e8bb9f092b3ed4ff330fd2988e2061ce..3ded32ea1983217365584122fe00b1cb0497f569 100644 (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);
 
index 1d4056c815aba0c7400379beec5c2634f9cb5b81..cffcb94d45f93552e1f9ebe1bc186d10bcc56b48 100644 (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,
index 977316ef7c1e6561854ee8a82e620fbb5463360c..51aef4747d6e7d5fdf833d30e34ed1a5854ac49d 100644 (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: