]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: move LSP updates into dataplane subsystem
authorMark Stapp <mjs@voltanet.io>
Thu, 15 Nov 2018 14:11:01 +0000 (09:11 -0500)
committerMark Stapp <mjs@voltanet.io>
Tue, 22 Jan 2019 18:56:48 +0000 (13:56 -0500)
Start performing LSP updates through the async dataplane
subsystem. This is plumbed through for linux/netlink.

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

index db2fcae5b75dc4c932e27c6752d247529c2f5876..9806f6836c74bac886abe2e3b699be2ba01e0a9d 100644 (file)
@@ -887,6 +887,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
        zebra_nhlfe_t *oldbest, *newbest;
        char buf[BUFSIZ], buf2[BUFSIZ];
        struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+       enum zebra_dplane_result res;
 
        lsp = (zebra_lsp_t *)data;
        if (!lsp) // unexpected
@@ -916,13 +917,20 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
                if (newbest) {
 
                        UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
-                       switch (kernel_add_lsp(lsp)) {
+
+                       switch (dplane_lsp_add(lsp)) {
                        case ZEBRA_DPLANE_REQUEST_QUEUED:
-                               flog_err(
-                                       EC_ZEBRA_DP_INVALID_RC,
-                                       "No current DataPlane interfaces can return this, please fix");
+                               /* Set 'installed' flag so we will know
+                                * that an install is in-flight.
+                                */
+                               SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+
+                               zvrf->lsp_installs_queued++;
                                break;
                        case ZEBRA_DPLANE_REQUEST_FAILURE:
+                               flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
+                                         "LSP Install Failure: %u",
+                                         lsp->ile.in_label);
                                break;
                        case ZEBRA_DPLANE_REQUEST_SUCCESS:
                                zvrf->lsp_installs++;
@@ -932,14 +940,22 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
        } else {
                /* Installed, may need an update and/or delete. */
                if (!newbest) {
+                       res = dplane_lsp_delete(lsp);
+
+                       /* We do some of the lsp cleanup immediately for
+                        * deletes.
+                        */
+                       UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+                       clear_nhlfe_installed(lsp);
 
-                       switch (kernel_del_lsp(lsp)) {
+                       switch (res) {
                        case ZEBRA_DPLANE_REQUEST_QUEUED:
-                               flog_err(
-                                       EC_ZEBRA_DP_INVALID_RC,
-                                       "No current DataPlane interfaces can return this, please fix");
+                               zvrf->lsp_removals_queued++;
                                break;
                        case ZEBRA_DPLANE_REQUEST_FAILURE:
+                               flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
+                                         "LSP Deletion Failure: %u",
+                                         lsp->ile.in_label);
                                break;
                        case ZEBRA_DPLANE_REQUEST_SUCCESS:
                                zvrf->lsp_removals++;
@@ -950,7 +966,10 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
                        struct nexthop *nexthop;
 
                        UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
-                       UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+
+                       /* We leave the INSTALLED flag set here
+                        * so we know an update in in-flight.
+                        */
 
                        /*
                         * Any NHLFE that was installed but is not
@@ -973,13 +992,14 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
                                }
                        }
 
-                       switch (kernel_upd_lsp(lsp)) {
+                       switch (dplane_lsp_update(lsp)) {
                        case ZEBRA_DPLANE_REQUEST_QUEUED:
-                               flog_err(
-                                       EC_ZEBRA_DP_INVALID_RC,
-                                       "No current DataPlane interfaces can return this, please fix");
+                               zvrf->lsp_installs_queued++;
                                break;
                        case ZEBRA_DPLANE_REQUEST_FAILURE:
+                               flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
+                                         "LSP Update Failure: %u",
+                                         lsp->ile.in_label);
                                break;
                        case ZEBRA_DPLANE_REQUEST_SUCCESS:
                                zvrf->lsp_installs++;
@@ -1755,6 +1775,87 @@ void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res)
        }
 }
 
+/*
+ * Process LSP update results from zebra dataplane.
+ */
+void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
+{
+       struct zebra_vrf *zvrf;
+       zebra_ile_t tmp_ile;
+       struct hash *lsp_table;
+       zebra_lsp_t *lsp;
+       zebra_nhlfe_t *nhlfe;
+       struct nexthop *nexthop;
+       enum dplane_op_e op;
+       enum zebra_dplane_status status;
+
+       op = dplane_ctx_get_op(ctx);
+       status = dplane_ctx_get_status(ctx);
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+               zlog_debug("LSP dplane ctx %p, op %s, in-label %u, result %s",
+                          ctx, dplane_op2str(op),
+                          dplane_ctx_get_in_label(ctx),
+                          dplane_res2str(status));
+
+       switch (op) {
+       case DPLANE_OP_LSP_INSTALL:
+       case DPLANE_OP_LSP_UPDATE:
+               /* Look for zebra LSP object */
+               zvrf = vrf_info_lookup(VRF_DEFAULT);
+               if (zvrf == NULL)
+                       break;
+
+               lsp_table = zvrf->lsp_table;
+
+               tmp_ile.in_label = dplane_ctx_get_in_label(ctx);
+               lsp = hash_lookup(lsp_table, &tmp_ile);
+               if (lsp == NULL) {
+                       if (IS_ZEBRA_DEBUG_DPLANE)
+                               zlog_debug("LSP ctx %p: in-label %u not found",
+                                          ctx, dplane_ctx_get_in_label(ctx));
+                       break;
+               }
+
+               /* TODO -- Confirm that this result is still 'current' */
+
+               if (dplane_ctx_get_status(ctx) ==
+                   ZEBRA_DPLANE_REQUEST_SUCCESS) {
+                       /* Update zebra object */
+                       SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+                       for (nhlfe = lsp->nhlfe_list; nhlfe;
+                            nhlfe = nhlfe->next) {
+                               nexthop = nhlfe->nexthop;
+                               if (!nexthop)
+                                       continue;
+
+                               SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+                               SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+                       }
+               } else {
+                       UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+                       clear_nhlfe_installed(lsp);
+                       flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
+                                 "LSP Install Failure: in-label %u",
+                                 lsp->ile.in_label);
+               }
+
+               break;
+
+       case DPLANE_OP_LSP_DELETE:
+               flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
+                         "LSP Deletion Failure: in-label %u",
+                         dplane_ctx_get_in_label(ctx));
+               break;
+
+       default:
+               break;
+
+       } /* Switch */
+
+       dplane_ctx_fini(&ctx);
+}
+
 /*
  * Install dynamic LSP entry.
  */
index 2c95d22c4eb759ed8d5e81dc1ba4bd8ea858756c..fb32adde315ff93ce55c72739665c7eef30328ff 100644 (file)
@@ -341,6 +341,14 @@ int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label,
                              enum nexthop_types_t gtype, union g_addr *gate,
                              ifindex_t ifindex);
 
+/*
+ * Process LSP update results from zebra dataplane.
+ */
+/* Forward ref of dplane update context type */
+struct zebra_dplane_ctx;
+
+void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx);
+
 /*
  * Schedule all MPLS label forwarding entries for processing.
  * Called upon changes that may affect one or more of them such as
index 2a21f8686bde6491c9f33ac7153158c8db543f33..63f518ffc37bf5dbe9abf5678597512b95ff5984 100644 (file)
@@ -22,6 +22,7 @@
 
 #ifdef HAVE_NETLINK
 
+#include "zebra/debug.h"
 #include "zebra/rt.h"
 #include "zebra/rt_netlink.h"
 #include "zebra/zebra_mpls.h"
@@ -98,9 +99,38 @@ enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp)
        return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
+/*
+ * LSP forwarding update using dataplane context information.
+ */
 enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
 {
-       return ZEBRA_DPLANE_REQUEST_FAILURE;
+       int cmd, ret = -1;
+
+       /* Call to netlink layer based on type of update */
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_DELETE) {
+               cmd = RTM_DELROUTE;
+       } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_INSTALL ||
+                  dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_UPDATE) {
+
+               /* Validate */
+               if (dplane_ctx_get_best_nhlfe(ctx) == NULL) {
+                       if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_MPLS)
+                               zlog_debug("LSP in-label %u: update fails, no best NHLFE",
+                                          dplane_ctx_get_in_label(ctx));
+                       goto done;
+               }
+
+               cmd = RTM_NEWROUTE;
+       } else
+               /* Invalid op? */
+               goto done;
+
+       ret = netlink_mpls_multipath_ctx(cmd, ctx);
+
+done:
+
+       return (ret == 0 ?
+               ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
 }
 
 int mpls_kernel_init(void)
index 7e4ac1ddd22bf22ee9bd9446e600f7f6140325d8..34bf513bfb41cc2bd56968bc03763b11132cce24 100644 (file)
@@ -1811,7 +1811,7 @@ done:
 /*
  * Route-update results processing after async dataplane update.
  */
-static void rib_process_after(struct zebra_dplane_ctx *ctx)
+static void rib_process_result(struct zebra_dplane_ctx *ctx)
 {
        struct route_table *table = NULL;
        struct zebra_vrf *zvrf = NULL;
@@ -1931,8 +1931,6 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx)
        }
 
        switch (op) {
-       case DPLANE_OP_NONE:
-               break;
        case DPLANE_OP_ROUTE_INSTALL:
        case DPLANE_OP_ROUTE_UPDATE:
                if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
@@ -2015,6 +2013,8 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx)
                                             dest_str, sizeof(dest_str)));
                }
                break;
+       default:
+               break;
        }
 done:
 
@@ -3191,7 +3191,8 @@ void rib_close_table(struct route_table *table)
 }
 
 /*
- *
+ * Handle results from the dataplane system. Dequeue update context
+ * structs, dispatch to appropriate internal handlers.
  */
 static int rib_process_dplane_results(struct thread *thread)
 {
@@ -3200,13 +3201,15 @@ static int rib_process_dplane_results(struct thread *thread)
 
        /* Dequeue a list of completed updates with one lock/unlock cycle */
 
+       /* TODO -- dequeue a list with one lock/unlock cycle? */
+
        do {
                TAILQ_INIT(&ctxlist);
 
                /* Take lock controlling queue of results */
                pthread_mutex_lock(&dplane_mutex);
                {
-                       /* Dequeue context block */
+                       /* Dequeue list of context structs */
                        dplane_ctx_list_append(&ctxlist, &rib_dplane_q);
                }
                pthread_mutex_unlock(&dplane_mutex);
@@ -3219,7 +3222,24 @@ static int rib_process_dplane_results(struct thread *thread)
                        break;
 
                while (ctx) {
-                       rib_process_after(ctx);
+                       switch (dplane_ctx_get_op(ctx)) {
+                       case DPLANE_OP_ROUTE_INSTALL:
+                       case DPLANE_OP_ROUTE_UPDATE:
+                       case DPLANE_OP_ROUTE_DELETE:
+                               rib_process_result(ctx);
+                               break;
+
+                       case DPLANE_OP_LSP_INSTALL:
+                       case DPLANE_OP_LSP_UPDATE:
+                       case DPLANE_OP_LSP_DELETE:
+                               zebra_mpls_lsp_dplane_result(ctx);
+                               break;
+
+                       default:
+                               /* Don't expect this: just return the struct? */
+                               dplane_ctx_fini(&ctx);
+                               break;
+                       } /* Dispatch by op code */
 
                        ctx = dplane_ctx_dequeue(&ctxlist);
                }
index c28025403b48fbb184269e200b58a2588af251fa..2473299d1763e06db5b90c54185533ba85b38530 100644 (file)
@@ -137,12 +137,14 @@ struct zebra_vrf {
         */
        enum vxlan_flood_control vxlan_flood_ctrl;
 
-       /* Route Installs */
+       /* Install stats */
        uint64_t installs;
        uint64_t removals;
        uint64_t installs_queued;
        uint64_t removals_queued;
        uint64_t neigh_updates;
+       uint64_t lsp_installs_queued;
+       uint64_t lsp_removals_queued;
        uint64_t lsp_installs;
        uint64_t lsp_removals;
 };