]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: dplane FPM LSP table walk 7617/head
authorDuncan Eastoe <duncan.eastoe@att.com>
Fri, 27 Nov 2020 16:12:22 +0000 (16:12 +0000)
committerDuncan Eastoe <duncan.eastoe@att.com>
Mon, 30 Nov 2020 12:13:43 +0000 (12:13 +0000)
Add routines to walk the LSP table and generate FPM updates for all
entries. A walk of the LSP table is triggered when (re-)connecting
to an FPM.

Signed-off-by: Duncan Eastoe <duncan.eastoe@att.com>
zebra/dplane_fpm_nl.c
zebra/zebra_mpls.h

index 94a35a8c1007f09948fee0924f0523f334352544..cd17cbf58f04822efd3ee1166ad7ebe97b045421 100644 (file)
@@ -104,6 +104,8 @@ struct fpm_nl_ctx {
        struct thread *t_dequeue;
 
        /* zebra events. */
+       struct thread *t_lspreset;
+       struct thread *t_lspwalk;
        struct thread *t_nhgreset;
        struct thread *t_nhgwalk;
        struct thread *t_ribreset;
@@ -156,6 +158,8 @@ enum fpm_nl_events {
        /* Reconnect request by our own code to avoid races. */
        FNE_INTERNAL_RECONNECT,
 
+       /* LSP walk finished. */
+       FNE_LSP_FINISHED,
        /* Next hop groups walk finished. */
        FNE_NHG_FINISHED,
        /* RIB walk finished. */
@@ -177,6 +181,8 @@ enum fpm_nl_events {
  */
 static int fpm_process_event(struct thread *t);
 static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx);
+static int fpm_lsp_send(struct thread *t);
+static int fpm_lsp_reset(struct thread *t);
 static int fpm_nhg_send(struct thread *t);
 static int fpm_nhg_reset(struct thread *t);
 static int fpm_rib_send(struct thread *t);
@@ -450,6 +456,8 @@ static int fpm_connect(struct thread *t);
 static void fpm_reconnect(struct fpm_nl_ctx *fnc)
 {
        /* Cancel all zebra threads first. */
+       thread_cancel_async(zrouter.master, &fnc->t_lspreset, NULL);
+       thread_cancel_async(zrouter.master, &fnc->t_lspwalk, NULL);
        thread_cancel_async(zrouter.master, &fnc->t_nhgreset, NULL);
        thread_cancel_async(zrouter.master, &fnc->t_nhgwalk, NULL);
        thread_cancel_async(zrouter.master, &fnc->t_ribreset, NULL);
@@ -678,13 +686,12 @@ static int fpm_connect(struct thread *t)
        thread_add_write(fnc->fthread->master, fpm_write, fnc, sock,
                         &fnc->t_write);
 
-       /* Mark all routes as unsent. */
-       if (fnc->use_nhg)
-               thread_add_timer(zrouter.master, fpm_nhg_reset, fnc, 0,
-                                &fnc->t_nhgreset);
-       else
-               thread_add_timer(zrouter.master, fpm_rib_reset, fnc, 0,
-                                &fnc->t_ribreset);
+       /*
+        * Starting with LSPs walk all FPM objects, marking them
+        * as unsent and then replaying them.
+        */
+       thread_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0,
+                        &fnc->t_lspreset);
 
        return 0;
 }
@@ -793,7 +800,8 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_LSP_DELETE:
                rv = netlink_lsp_msg_encoder(ctx, nl_buf, sizeof(nl_buf));
                if (rv <= 0) {
-                       zlog_err("%s: netlink_lsp_msg_encoder failed", __func__);
+                       zlog_err("%s: netlink_lsp_msg_encoder failed",
+                                __func__);
                        return 0;
                }
 
@@ -876,6 +884,70 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
        return 0;
 }
 
+/*
+ * LSP walk/send functions
+ */
+struct fpm_lsp_arg {
+       struct zebra_dplane_ctx *ctx;
+       struct fpm_nl_ctx *fnc;
+       bool complete;
+};
+
+static int fpm_lsp_send_cb(struct hash_bucket *bucket, void *arg)
+{
+       zebra_lsp_t *lsp = bucket->data;
+       struct fpm_lsp_arg *fla = arg;
+
+       /* Skip entries which have already been sent */
+       if (CHECK_FLAG(lsp->flags, LSP_FLAG_FPM))
+               return HASHWALK_CONTINUE;
+
+       dplane_ctx_reset(fla->ctx);
+       dplane_ctx_lsp_init(fla->ctx, DPLANE_OP_LSP_INSTALL, lsp);
+
+       if (fpm_nl_enqueue(fla->fnc, fla->ctx) == -1) {
+               fla->complete = false;
+               return HASHWALK_ABORT;
+       }
+
+       /* Mark entry as sent */
+       SET_FLAG(lsp->flags, LSP_FLAG_FPM);
+       return HASHWALK_CONTINUE;
+}
+
+static int fpm_lsp_send(struct thread *t)
+{
+       struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+       struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+       struct fpm_lsp_arg fla;
+
+       fla.fnc = fnc;
+       fla.ctx = dplane_ctx_alloc();
+       fla.complete = true;
+
+       hash_walk(zvrf->lsp_table, fpm_lsp_send_cb, &fla);
+
+       dplane_ctx_fini(&fla.ctx);
+
+       if (fla.complete) {
+               WALK_FINISH(fnc, FNE_LSP_FINISHED);
+
+               /* Now move onto routes */
+               if (fnc->use_nhg)
+                       thread_add_timer(zrouter.master, fpm_nhg_reset, fnc, 0,
+                                        &fnc->t_nhgreset);
+               else
+                       thread_add_timer(zrouter.master, fpm_rib_reset, fnc, 0,
+                                        &fnc->t_ribreset);
+       } else {
+               /* Didn't finish - reschedule LSP walk */
+               thread_add_timer(zrouter.master, fpm_lsp_send, fnc, 0,
+                                &fnc->t_lspwalk);
+       }
+
+       return 0;
+}
+
 /*
  * Next hop walk/send functions.
  */
@@ -1086,6 +1158,29 @@ static int fpm_nhg_reset(struct thread *t)
        return 0;
 }
 
+/*
+ * Resets the LSP FPM flag so we send all LSPs again.
+ */
+static void fpm_lsp_reset_cb(struct hash_bucket *bucket, void *arg)
+{
+       zebra_lsp_t *lsp = bucket->data;
+
+       UNSET_FLAG(lsp->flags, LSP_FLAG_FPM);
+}
+
+static int fpm_lsp_reset(struct thread *t)
+{
+       struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+       struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+
+       hash_iterate(zvrf->lsp_table, fpm_lsp_reset_cb, NULL);
+
+       /* Schedule next step: send LSPs */
+       thread_add_event(zrouter.master, fpm_lsp_send, fnc, 0, &fnc->t_lspwalk);
+
+       return 0;
+}
+
 /**
  * Resets the RIB FPM flags so we send all routes again.
  */
@@ -1248,6 +1343,10 @@ static int fpm_process_event(struct thread *t)
 
                fnc->rmac_complete = true;
                break;
+       case FNE_LSP_FINISHED:
+               if (IS_ZEBRA_DEBUG_FPM)
+                       zlog_debug("%s: LSP walk finished", __func__);
+               break;
 
        default:
                if (IS_ZEBRA_DEBUG_FPM)
@@ -1286,6 +1385,8 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov)
 static int fpm_nl_finish_early(struct fpm_nl_ctx *fnc)
 {
        /* Disable all events and close socket. */
+       THREAD_OFF(fnc->t_lspreset);
+       THREAD_OFF(fnc->t_lspwalk);
        THREAD_OFF(fnc->t_nhgreset);
        THREAD_OFF(fnc->t_nhgwalk);
        THREAD_OFF(fnc->t_ribreset);
index 51672330409d02c7407ae1ec5e495b75d1685952..dd2d2e5658ea1e5b2701baf2852305d57f76c358 100644 (file)
@@ -116,6 +116,7 @@ struct zebra_lsp_t_ {
 #define LSP_FLAG_SCHEDULED        (1 << 0)
 #define LSP_FLAG_INSTALLED        (1 << 1)
 #define LSP_FLAG_CHANGED          (1 << 2)
+#define LSP_FLAG_FPM              (1 << 3)
 
        /* Address-family of NHLFE - saved here for delete. All NHLFEs */
        /* have to be of the same AF */