]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_dplane.c
zebra: Add interface sysctl ignore on linkdown status
[mirror_frr.git] / zebra / zebra_dplane.c
index 4d32e54d1fb84524aa53125f4795cfe8e5d49f10..3a3bac6c74db9cbaa36032dc08f5d766ee335780 100644 (file)
@@ -28,6 +28,7 @@
 #include "lib/memory.h"
 #include "lib/queue.h"
 #include "lib/zebra.h"
+#include "zebra/netconf_netlink.h"
 #include "zebra/zebra_router.h"
 #include "zebra/zebra_dplane.h"
 #include "zebra/zebra_vxlan_private.h"
@@ -192,6 +193,9 @@ struct dplane_intf_info {
        uint32_t metric;
        uint32_t flags;
 
+       bool protodown;
+       bool pd_reason_val;
+
 #define DPLANE_INTF_CONNECTED   (1 << 0) /* Connected peer, p2p */
 #define DPLANE_INTF_SECONDARY   (1 << 1)
 #define DPLANE_INTF_BROADCAST   (1 << 2)
@@ -290,6 +294,18 @@ struct dplane_gre_ctx {
        unsigned int mtu;
        struct zebra_l2info_gre info;
 };
+
+
+/*
+ * Network interface configuration info - aligned with netlink's NETCONF
+ * info. The flags values are public, in the dplane.h file...
+ */
+struct dplane_netconf_info {
+       enum dplane_netconf_status_e mpls_val;
+       enum dplane_netconf_status_e mcast_val;
+       enum dplane_netconf_status_e linkdown_val;
+};
+
 /*
  * The context block used to exchange info about route updates across
  * the boundary between the zebra main context (and pthread) and the
@@ -347,6 +363,7 @@ struct zebra_dplane_ctx {
                } ipset_entry;
                struct dplane_neigh_table neightable;
                struct dplane_gre_ctx gre;
+               struct dplane_netconf_info netconf;
        } u;
 
        /* Namespace info, used especially for netlink kernel communication */
@@ -416,6 +433,9 @@ PREDECL_DLIST(zns_info_list);
 struct dplane_zns_info {
        struct zebra_dplane_info info;
 
+       /* Request data from the OS */
+       struct thread *t_request;
+
        /* Read event */
        struct thread *t_read;
 
@@ -508,6 +528,9 @@ static struct zebra_dplane_globals {
        _Atomic uint32_t dg_gre_set_in;
        _Atomic uint32_t dg_gre_set_errors;
 
+       _Atomic uint32_t dg_intfs_in;
+       _Atomic uint32_t dg_intf_errors;
+
        /* Dataplane pthread */
        struct frr_pthread *dg_pthread;
 
@@ -539,9 +562,7 @@ DECLARE_DLIST(zns_info_list, struct dplane_zns_info, link);
 #define DPLANE_PROV_UNLOCK(p) pthread_mutex_unlock(&((p)->dp_mutex))
 
 /* Prototypes */
-static int dplane_thread_loop(struct thread *event);
-static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
-                                struct zebra_ns *zns);
+static void dplane_thread_loop(struct thread *event);
 static enum zebra_dplane_result lsp_update_internal(struct zebra_lsp *lsp,
                                                    enum dplane_op_e op);
 static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
@@ -722,7 +743,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
                /* Maybe free label string, if allocated */
                if (ctx->u.intf.label != NULL &&
                    ctx->u.intf.label != ctx->u.intf.label_buf) {
-                       free(ctx->u.intf.label);
+                       XFREE(MTYPE_DP_CTX, ctx->u.intf.label);
                        ctx->u.intf.label = NULL;
                }
                break;
@@ -744,6 +765,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_NONE:
        case DPLANE_OP_IPSET_ADD:
        case DPLANE_OP_IPSET_DELETE:
+       case DPLANE_OP_INTF_INSTALL:
+       case DPLANE_OP_INTF_UPDATE:
+       case DPLANE_OP_INTF_DELETE:
                break;
 
        case DPLANE_OP_IPSET_ENTRY_ADD:
@@ -769,6 +793,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
                }
                break;
        case DPLANE_OP_GRE_SET:
+       case DPLANE_OP_INTF_NETCONFIG:
                break;
        }
 }
@@ -1053,6 +1078,19 @@ const char *dplane_op2str(enum dplane_op_e op)
 
        case DPLANE_OP_INTF_ADDR_DEL:
                return "INTF_ADDR_DEL";
+
+       case DPLANE_OP_INTF_NETCONFIG:
+               return "INTF_NETCONFIG";
+
+       case DPLANE_OP_INTF_INSTALL:
+               ret = "INTF_INSTALL";
+               break;
+       case DPLANE_OP_INTF_UPDATE:
+               ret = "INTF_UPDATE";
+               break;
+       case DPLANE_OP_INTF_DELETE:
+               ret = "INTF_DELETE";
+               break;
        }
 
        return ret;
@@ -1751,6 +1789,27 @@ void dplane_ctx_set_intf_metric(struct zebra_dplane_ctx *ctx, uint32_t metric)
        ctx->u.intf.metric = metric;
 }
 
+uint32_t dplane_ctx_get_intf_pd_reason_val(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.intf.pd_reason_val;
+}
+
+void dplane_ctx_set_intf_pd_reason_val(struct zebra_dplane_ctx *ctx, bool val)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       ctx->u.intf.pd_reason_val = val;
+}
+
+bool dplane_ctx_intf_is_protodown(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.intf.protodown;
+}
+
 /* Is interface addr p2p? */
 bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx)
 {
@@ -1854,7 +1913,7 @@ void dplane_ctx_set_intf_label(struct zebra_dplane_ctx *ctx, const char *label)
        DPLANE_CTX_VALID(ctx);
 
        if (ctx->u.intf.label && ctx->u.intf.label != ctx->u.intf.label_buf)
-               free(ctx->u.intf.label);
+               XFREE(MTYPE_DP_CTX, ctx->u.intf.label);
 
        ctx->u.intf.label = NULL;
 
@@ -1869,7 +1928,7 @@ void dplane_ctx_set_intf_label(struct zebra_dplane_ctx *ctx, const char *label)
                                sizeof(ctx->u.intf.label_buf));
                        ctx->u.intf.label = ctx->u.intf.label_buf;
                } else {
-                       ctx->u.intf.label = strdup(label);
+                       ctx->u.intf.label = XSTRDUP(MTYPE_DP_CTX, label);
                }
        } else {
                ctx->u.intf.flags &= ~DPLANE_INTF_HAS_LABEL;
@@ -2239,6 +2298,10 @@ uint32_t dplane_intf_extra_get_status(const struct dplane_intf_extra *ptr)
        return ptr->status;
 }
 
+/*
+ * End of interface extra info accessors
+ */
+
 uint8_t dplane_ctx_neightable_get_family(const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
@@ -2270,9 +2333,54 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx)
        return ctx->u.neightable.mcast_probes;
 }
 
-/*
- * End of interface extra info accessors
- */
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_mpls(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.netconf.mpls_val;
+}
+
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_mcast(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.netconf.mcast_val;
+}
+
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_linkdown(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.netconf.linkdown_val;
+}
+
+void dplane_ctx_set_netconf_mpls(struct zebra_dplane_ctx *ctx,
+                                enum dplane_netconf_status_e val)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       ctx->u.netconf.mpls_val = val;
+}
+
+void dplane_ctx_set_netconf_mcast(struct zebra_dplane_ctx *ctx,
+                                 enum dplane_netconf_status_e val)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       ctx->u.netconf.mcast_val = val;
+}
+
+void dplane_ctx_set_netconf_linkdown(struct zebra_dplane_ctx *ctx,
+                                    enum dplane_netconf_status_e val)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       ctx->u.netconf.linkdown_val = val;
+}
+
 
 /*
  * Retrieve the limit on the number of pending, unprocessed updates.
@@ -2305,6 +2413,22 @@ uint32_t dplane_get_in_queue_len(void)
                                    memory_order_seq_cst);
 }
 
+/*
+ * Internal helper that copies information from a zebra ns object; this is
+ * called in the zebra main pthread context as part of dplane ctx init.
+ */
+static void ctx_info_from_zns(struct zebra_dplane_info *ns_info,
+                             struct zebra_ns *zns)
+{
+       ns_info->ns_id = zns->ns_id;
+
+#if defined(HAVE_NETLINK)
+       ns_info->is_cmd = true;
+       ns_info->sock = zns->netlink_dplane_out.sock;
+       ns_info->seq = zns->netlink_dplane_out.seq;
+#endif /* NETLINK */
+}
+
 /*
  * Common dataplane context init with zebra namespace info.
  */
@@ -2312,7 +2436,7 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx,
                              struct zebra_ns *zns,
                              bool is_update)
 {
-       dplane_info_from_zns(&(ctx->zd_ns_info), zns);
+       ctx_info_from_zns(&(ctx->zd_ns_info), zns); /*  */
 
        ctx->zd_is_update = is_update;
 
@@ -2425,7 +2549,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
                }
 
                /* Check for available evpn encapsulations. */
-               if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE))
+               if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN))
                        continue;
 
                zl3vni = zl3vni_from_vrf(nexthop->vrf_id);
@@ -2541,6 +2665,73 @@ done:
        return ret;
 }
 
+/**
+ * dplane_ctx_intf_init() - Initialize a context block for a interface update
+ *
+ * @ctx:       Dataplane context to init
+ * @op:                Operation being performed
+ * @ifp:       Interface
+ *
+ * Return:     Result status
+ */
+int dplane_ctx_intf_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
+                        const struct interface *ifp)
+{
+       struct zebra_ns *zns;
+       struct zebra_if *zif;
+       int ret = EINVAL;
+       bool set_pdown, unset_pdown;
+
+       if (!ctx || !ifp)
+               goto done;
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+       ctx->zd_vrf_id = ifp->vrf->vrf_id;
+
+       strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+       ctx->zd_ifindex = ifp->ifindex;
+
+       zns = zebra_ns_lookup(ifp->vrf->vrf_id);
+       dplane_ctx_ns_init(ctx, zns, false);
+
+
+       /* Copy over ifp info */
+       ctx->u.intf.metric = ifp->metric;
+       ctx->u.intf.flags = ifp->flags;
+
+       /* Copy over extra zebra info, if available */
+       zif = (struct zebra_if *)ifp->info;
+
+       if (zif) {
+               set_pdown = !!(zif->flags & ZIF_FLAG_SET_PROTODOWN);
+               unset_pdown = !!(zif->flags & ZIF_FLAG_UNSET_PROTODOWN);
+
+               if (zif->protodown_rc &&
+                   ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zif) == false)
+                       ctx->u.intf.pd_reason_val = true;
+
+               /*
+                * See if we have new protodown state to set, otherwise keep
+                * current state
+                */
+               if (set_pdown)
+                       ctx->u.intf.protodown = true;
+               else if (unset_pdown)
+                       ctx->u.intf.protodown = false;
+               else
+                       ctx->u.intf.protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
+       }
+
+       dplane_ctx_ns_init(ctx, zns, (op == DPLANE_OP_INTF_UPDATE));
+       ctx->zd_is_update = (op == DPLANE_OP_INTF_UPDATE);
+
+       ret = AOK;
+
+done:
+       return ret;
+}
+
 /*
  * Capture information for an LSP update in a dplane context.
  */
@@ -3705,7 +3896,7 @@ static enum zebra_dplane_result intf_addr_update_internal(
                                sizeof(ctx->u.intf.label_buf));
                        ctx->u.intf.label = ctx->u.intf.label_buf;
                } else {
-                       ctx->u.intf.label = strdup(ifc->label);
+                       ctx->u.intf.label = XSTRDUP(MTYPE_DP_CTX, ifc->label);
                }
        }
 
@@ -3727,6 +3918,85 @@ static enum zebra_dplane_result intf_addr_update_internal(
        return result;
 }
 
+/**
+ * dplane_intf_update_internal() - Helper for enqueuing interface changes
+ *
+ * @ifp:       Interface where the change occured
+ * @op:                The operation to be enqued
+ *
+ * Return:     Result of the change
+ */
+static enum zebra_dplane_result
+dplane_intf_update_internal(const struct interface *ifp, enum dplane_op_e op)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       int ret = EINVAL;
+       struct zebra_dplane_ctx *ctx = NULL;
+
+       /* Obtain context block */
+       ctx = dplane_ctx_alloc();
+       if (!ctx) {
+               ret = ENOMEM;
+               goto done;
+       }
+
+       ret = dplane_ctx_intf_init(ctx, op, ifp);
+       if (ret == AOK)
+               ret = dplane_update_enqueue(ctx);
+
+done:
+       /* Update counter */
+       atomic_fetch_add_explicit(&zdplane_info.dg_intfs_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               atomic_fetch_add_explicit(&zdplane_info.dg_intf_errors, 1,
+                                         memory_order_relaxed);
+               if (ctx)
+                       dplane_ctx_free(&ctx);
+       }
+
+       return result;
+}
+
+/*
+ * Enqueue a interface add for the dataplane.
+ */
+enum zebra_dplane_result dplane_intf_add(const struct interface *ifp)
+{
+       enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
+
+       if (ifp)
+               ret = dplane_intf_update_internal(ifp, DPLANE_OP_INTF_INSTALL);
+       return ret;
+}
+
+/*
+ * Enqueue a interface update for the dataplane.
+ */
+enum zebra_dplane_result dplane_intf_update(const struct interface *ifp)
+{
+       enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
+
+       if (ifp)
+               ret = dplane_intf_update_internal(ifp, DPLANE_OP_INTF_UPDATE);
+       return ret;
+}
+
+/*
+ * Enqueue a interface delete for the dataplane.
+ */
+enum zebra_dplane_result dplane_intf_delete(const struct interface *ifp)
+{
+       enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
+
+       if (ifp)
+               ret = dplane_intf_update_internal(ifp, DPLANE_OP_INTF_DELETE);
+       return ret;
+}
+
 /*
  * Enqueue vxlan/evpn mac add (or update).
  */
@@ -4267,6 +4537,17 @@ iptable_update_internal(enum dplane_op_e op, struct zebra_pbr_iptable *iptable)
        struct zebra_dplane_ctx *ctx;
        int ret;
 
+       if ((op == DPLANE_OP_IPTABLE_ADD &&
+            CHECK_FLAG(iptable->internal_flags, IPTABLE_INSTALL_QUEUED)) ||
+           (op == DPLANE_OP_IPTABLE_DELETE &&
+            CHECK_FLAG(iptable->internal_flags, IPTABLE_UNINSTALL_QUEUED))) {
+               if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+                       zlog_debug(
+                               "update dplane ctx %s: iptable %s already in progress",
+                               dplane_op2str(op), iptable->ipset_name);
+               return result;
+       }
+
        ctx = dplane_ctx_alloc();
 
        ret = dplane_ctx_iptable_init(ctx, op, iptable);
@@ -4279,14 +4560,19 @@ done:
        atomic_fetch_add_explicit(&zdplane_info.dg_iptable_in, 1,
                                  memory_order_relaxed);
 
-       if (ret == AOK)
+       if (ret == AOK) {
                result = ZEBRA_DPLANE_REQUEST_QUEUED;
-       else {
+               if (op == DPLANE_OP_IPTABLE_ADD)
+                       SET_FLAG(iptable->internal_flags,
+                                IPTABLE_INSTALL_QUEUED);
+               else
+                       SET_FLAG(iptable->internal_flags,
+                                IPTABLE_UNINSTALL_QUEUED);
+       } else {
                atomic_fetch_add_explicit(&zdplane_info.dg_iptable_errors, 1,
                                          memory_order_relaxed);
                dplane_ctx_free(&ctx);
        }
-
        return result;
 }
 
@@ -4844,27 +5130,12 @@ bool dplane_provider_is_threaded(const struct zebra_dplane_provider *prov)
        return (prov->dp_flags & DPLANE_PROV_FLAG_THREADED);
 }
 
-/*
- * Internal helper that copies information from a zebra ns object; this is
- * called in the zebra main pthread context as part of dplane ctx init.
- */
-static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
-                                struct zebra_ns *zns)
-{
-       ns_info->ns_id = zns->ns_id;
-
-#if defined(HAVE_NETLINK)
-       ns_info->is_cmd = true;
-       ns_info->sock = zns->netlink_dplane_out.sock;
-#endif /* NETLINK */
-}
-
 #ifdef HAVE_NETLINK
 /*
  * Callback when an OS (netlink) incoming event read is ready. This runs
  * in the dplane pthread.
  */
-static int dplane_incoming_read(struct thread *event)
+static void dplane_incoming_read(struct thread *event)
 {
        struct dplane_zns_info *zi = THREAD_ARG(event);
 
@@ -4873,9 +5144,41 @@ static int dplane_incoming_read(struct thread *event)
        /* Re-start read task */
        thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi,
                        zi->info.sock, &zi->t_read);
+}
 
-       return 0;
+/*
+ * Callback in the dataplane pthread that requests info from the OS and
+ * initiates netlink reads.
+ */
+static void dplane_incoming_request(struct thread *event)
+{
+       struct dplane_zns_info *zi = THREAD_ARG(event);
+
+       /* Start read task */
+       thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi,
+                       zi->info.sock, &zi->t_read);
+
+       /* Send requests */
+       netlink_request_netconf(zi->info.sock);
 }
+
+/*
+ * Initiate requests for existing info from the OS. This is called by the
+ * main pthread, but we want all activity on the dplane netlink socket to
+ * take place on the dplane pthread, so we schedule an event to accomplish
+ * that.
+ */
+static void dplane_kernel_info_request(struct dplane_zns_info *zi)
+{
+       /* If we happen to encounter an enabled zns before the dplane
+        * pthread is running, we'll initiate this later on.
+        */
+       if (zdplane_info.dg_master)
+               thread_add_event(zdplane_info.dg_master,
+                                dplane_incoming_request, zi, 0,
+                                &zi->t_request);
+}
+
 #endif /* HAVE_NETLINK */
 
 /*
@@ -4919,11 +5222,10 @@ void zebra_dplane_ns_enable(struct zebra_ns *zns, bool enabled)
                zi->info.is_cmd = false;
                zi->info.sock = zns->netlink_dplane_in.sock;
 
-               /* Start read task for the dplane pthread. */
-               if (zdplane_info.dg_master)
-                       thread_add_read(zdplane_info.dg_master,
-                                       dplane_incoming_read, zi, zi->info.sock,
-                                       &zi->t_read);
+               /* Initiate requests for existing info from the OS, and
+                * begin reading from the netlink socket.
+                */
+               dplane_kernel_info_request(zi);
 #endif
        } else if (zi) {
                if (IS_ZEBRA_DEBUG_DPLANE)
@@ -4933,9 +5235,14 @@ void zebra_dplane_ns_enable(struct zebra_ns *zns, bool enabled)
                /* Stop reading, free memory */
                zns_info_list_del(&zdplane_info.dg_zns_list, zi);
 
-               if (zdplane_info.dg_master)
+               /* Stop any outstanding tasks */
+               if (zdplane_info.dg_master) {
+                       thread_cancel_async(zdplane_info.dg_master,
+                                           &zi->t_request, NULL);
+
                        thread_cancel_async(zdplane_info.dg_master, &zi->t_read,
                                            NULL);
+               }
 
                XFREE(MTYPE_DP_NS, zi);
        }
@@ -5115,6 +5422,23 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
                           dplane_ctx_get_ifname(ctx),
                           dplane_ctx_get_intf_addr(ctx));
                break;
+
+       case DPLANE_OP_INTF_NETCONFIG:
+               zlog_debug("%s: ifindex %d, mpls %d, mcast %d",
+                          dplane_op2str(dplane_ctx_get_op(ctx)),
+                          dplane_ctx_get_ifindex(ctx),
+                          dplane_ctx_get_netconf_mpls(ctx),
+                          dplane_ctx_get_netconf_mcast(ctx));
+               break;
+
+       case DPLANE_OP_INTF_INSTALL:
+       case DPLANE_OP_INTF_UPDATE:
+       case DPLANE_OP_INTF_DELETE:
+               zlog_debug("Dplane intf %s, idx %u, protodown %d",
+                          dplane_op2str(dplane_ctx_get_op(ctx)),
+                          dplane_ctx_get_ifindex(ctx),
+                          dplane_ctx_intf_is_protodown(ctx));
+               break;
        }
 }
 
@@ -5249,6 +5573,15 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
                                &zdplane_info.dg_gre_set_errors, 1,
                                memory_order_relaxed);
                break;
+
+       case DPLANE_OP_INTF_INSTALL:
+       case DPLANE_OP_INTF_UPDATE:
+       case DPLANE_OP_INTF_DELETE:
+               if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+                       atomic_fetch_add_explicit(&zdplane_info.dg_intf_errors,
+                                                 1, memory_order_relaxed);
+               break;
+
        /* Ignore 'notifications' - no-op */
        case DPLANE_OP_SYS_ROUTE_ADD:
        case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -5260,6 +5593,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
        /* TODO -- error counters for incoming events? */
        case DPLANE_OP_INTF_ADDR_ADD:
        case DPLANE_OP_INTF_ADDR_DEL:
+       case DPLANE_OP_INTF_NETCONFIG:
                break;
 
        case DPLANE_OP_NONE:
@@ -5595,7 +5929,7 @@ done:
  * final zebra shutdown.
  * This runs in the dplane pthread context.
  */
-static int dplane_check_shutdown_status(struct thread *event)
+static void dplane_check_shutdown_status(struct thread *event)
 {
        struct dplane_zns_info *zi;
 
@@ -5606,8 +5940,10 @@ static int dplane_check_shutdown_status(struct thread *event)
        frr_each_safe (zns_info_list, &zdplane_info.dg_zns_list, zi) {
                zns_info_list_del(&zdplane_info.dg_zns_list, zi);
 
-               if (zdplane_info.dg_master)
+               if (zdplane_info.dg_master) {
                        thread_cancel(&zi->t_read);
+                       thread_cancel(&zi->t_request);
+               }
 
                XFREE(MTYPE_DP_NS, zi);
        }
@@ -5627,8 +5963,6 @@ static int dplane_check_shutdown_status(struct thread *event)
                 */
                thread_add_event(zrouter.master, zebra_finalize, NULL, 0, NULL);
        }
-
-       return 0;
 }
 
 /*
@@ -5662,7 +5996,7 @@ void zebra_dplane_finish(void)
  * pthread can look for other pending work - such as i/o work on behalf of
  * providers.
  */
-static int dplane_thread_loop(struct thread *event)
+static void dplane_thread_loop(struct thread *event)
 {
        struct dplane_ctx_q work_list;
        struct dplane_ctx_q error_list;
@@ -5682,7 +6016,7 @@ static int dplane_thread_loop(struct thread *event)
 
        /* Check for zebra shutdown */
        if (!zdplane_info.dg_run)
-               goto done;
+               return;
 
        /* Dequeue some incoming work from zebra (if any) onto the temporary
         * working list.
@@ -5848,9 +6182,6 @@ static int dplane_thread_loop(struct thread *event)
        (zdplane_info.dg_results_cb)(&work_list);
 
        TAILQ_INIT(&work_list);
-
-done:
-       return 0;
 }
 
 /*
@@ -5942,11 +6273,12 @@ void zebra_dplane_start(void)
        thread_add_event(zdplane_info.dg_master, dplane_thread_loop, NULL, 0,
                         &zdplane_info.dg_t_update);
 
-       /* Enqueue reads if necessary */
+       /* Enqueue requests and reads if necessary */
        frr_each (zns_info_list, &zdplane_info.dg_zns_list, zi) {
 #if defined(HAVE_NETLINK)
                thread_add_read(zdplane_info.dg_master, dplane_incoming_read,
                                zi, zi->info.sock, &zi->t_read);
+               dplane_kernel_info_request(zi);
 #endif
        }