]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: northbound/mgmtd: add backend model support
authorChristian Hopps <chopps@labn.net>
Mon, 6 Jan 2025 12:52:31 +0000 (07:52 -0500)
committerChristian Hopps <chopps@labn.net>
Tue, 14 Jan 2025 18:48:59 +0000 (18:48 +0000)
Signed-off-by: Christian Hopps <chopps@labn.net>
13 files changed:
lib/mgmt_be_client.c
lib/mgmt_be_client.h
lib/northbound.h
lib/northbound_oper.c
lib/subdir.am
mgmtd/mgmt_be_adapter.c
mgmtd/mgmt_main.c
ripd/rip_main.c
ripngd/ripng_main.c
staticd/static_main.c
yang/frr-backend.yang [new file with mode: 0644]
yang/subdir.am
zebra/main.c

index efd5d70a749ee69b0e4cef053a0f15e3b18b7d49..3a07a1d2d9c30141d886000a4e95bb1705a15abe 100644 (file)
@@ -99,12 +99,12 @@ struct mgmt_be_client {
        struct nb_config *candidate_config;
        struct nb_config *running_config;
 
-       unsigned long num_edit_nb_cfg;
-       unsigned long avg_edit_nb_cfg_tm;
-       unsigned long num_prep_nb_cfg;
-       unsigned long avg_prep_nb_cfg_tm;
-       unsigned long num_apply_nb_cfg;
-       unsigned long avg_apply_nb_cfg_tm;
+       uint64_t num_edit_nb_cfg;
+       uint64_t avg_edit_nb_cfg_tm;
+       uint64_t num_prep_nb_cfg;
+       uint64_t avg_prep_nb_cfg_tm;
+       uint64_t num_apply_nb_cfg;
+       uint64_t avg_apply_nb_cfg_tm;
 
        struct mgmt_be_txns_head txn_head;
 
@@ -117,7 +117,7 @@ struct mgmt_be_client {
 
 struct debug mgmt_dbg_be_client = {
        .conf = "debug mgmt client backend",
-       .desc = "Management backend client operations"
+       .desc = "Management backend client operations",
 };
 
 /* NOTE: only one client per proc for now. */
@@ -621,7 +621,7 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
        mgmt_be_send_cfgdata_create_reply(client_ctx, txn->txn_id,
                error ? false : true, error ? err_buf : NULL);
 
-       debug_be_client("Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u",
+       debug_be_client("Avg-nb-edit-duration %Lu uSec, nb-prep-duration %lu (avg: %Lu) uSec, batch size %u",
                        client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm,
                        client_ctx->avg_prep_nb_cfg_tm, (uint32_t)num_processed);
 
@@ -770,10 +770,9 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn)
        gettimeofday(&apply_nb_cfg_end, NULL);
 
        apply_nb_cfg_tm = timeval_elapsed(apply_nb_cfg_end, apply_nb_cfg_start);
-       client_ctx->avg_apply_nb_cfg_tm = ((client_ctx->avg_apply_nb_cfg_tm *
-                                           client_ctx->num_apply_nb_cfg) +
-                                          apply_nb_cfg_tm) /
-                                         (client_ctx->num_apply_nb_cfg + 1);
+       client_ctx->avg_apply_nb_cfg_tm =
+               ((client_ctx->avg_apply_nb_cfg_tm * client_ctx->num_apply_nb_cfg) + apply_nb_cfg_tm) /
+               (client_ctx->num_apply_nb_cfg + 1);
        client_ctx->num_apply_nb_cfg++;
        txn->nb_txn = NULL;
 
@@ -789,8 +788,8 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn)
 
        mgmt_be_send_apply_reply(client_ctx, txn->txn_id, true, NULL);
 
-       debug_be_client("Nb-apply-duration %lu (avg: %lu) uSec",
-                       apply_nb_cfg_tm, client_ctx->avg_apply_nb_cfg_tm);
+       debug_be_client("Nb-apply-duration %lu (avg: %Lu) uSec", apply_nb_cfg_tm,
+                       client_ctx->avg_apply_nb_cfg_tm);
 
        return 0;
 }
@@ -1333,6 +1332,190 @@ DEFPY(debug_mgmt_client_be, debug_mgmt_client_be_cmd,
        return CMD_SUCCESS;
 }
 
+/*
+ * XPath: /frr-backend:clients/client
+ *
+ * We only implement a list of one entry (for the this backend client) the
+ * results will be merged inside mgmtd.
+ */
+static const void *clients_client_get_next(struct nb_cb_get_next_args *args)
+{
+       if (args->list_entry == NULL)
+               return __be_client;
+       return NULL;
+}
+
+static int clients_client_get_keys(struct nb_cb_get_keys_args *args)
+{
+       args->keys->num = 1;
+       strlcpy(args->keys->key[0], __be_client->name, sizeof(args->keys->key[0]));
+
+       return NB_OK;
+}
+
+static const void *clients_client_lookup_entry(struct nb_cb_lookup_entry_args *args)
+{
+       const char *name = args->keys->key[0];
+
+       if (!strcmp(name, __be_client->name))
+               return __be_client;
+
+       return NULL;
+}
+
+/*
+ * XPath: /frr-backend:clients/client/name
+ */
+static enum nb_error clients_client_name_get(const struct nb_node *nb_node,
+                                            const void *parent_list_entry, struct lyd_node *parent)
+{
+       const struct lysc_node *snode = nb_node->snode;
+       LY_ERR err;
+
+       err = lyd_new_term(parent, snode->module, snode->name, __be_client->name, false, NULL);
+       if (err != LY_SUCCESS)
+               return NB_ERR_RESOURCE;
+
+       return NB_OK;
+}
+
+/*
+ * XPath: /frr-backend:clients/client/state/candidate-config-version
+ */
+static enum nb_error clients_client_state_candidate_config_version_get(
+       const struct nb_node *nb_node, const void *parent_list_entry, struct lyd_node *parent)
+{
+       const struct lysc_node *snode = nb_node->snode;
+       uint64_t value = __be_client->candidate_config->version;
+
+       if (lyd_new_term_bin(parent, snode->module, snode->name, &value, sizeof(value),
+                            LYD_NEW_PATH_UPDATE, NULL))
+               return NB_ERR_RESOURCE;
+
+       return NB_OK;
+}
+
+/*
+ * XPath: /frr-backend:clients/client/state/running-config-version
+ */
+static enum nb_error clients_client_state_running_config_version_get(const struct nb_node *nb_node,
+                                                                    const void *parent_list_entry,
+                                                                    struct lyd_node *parent)
+{
+       const struct lysc_node *snode = nb_node->snode;
+       uint64_t value = __be_client->running_config->version;
+
+       if (lyd_new_term_bin(parent, snode->module, snode->name, &value, sizeof(value),
+                            LYD_NEW_PATH_UPDATE, NULL))
+               return NB_ERR_RESOURCE;
+
+       return NB_OK;
+}
+
+/*
+ * XPath: /frr-backend:clients/client/state/notify-selectors
+ *
+ * Is this better in northbound_notif.c? Let's decide when we add more to this module.
+ */
+
+static enum nb_error clients_client_state_notify_selectors_get(const struct nb_node *nb_node,
+                                                              const void *parent_list_entry,
+                                                              struct lyd_node *parent)
+{
+       const struct lysc_node *snode = nb_node->snode;
+       const char **p;
+       LY_ERR err;
+
+       darr_foreach_p (nb_notif_filters, p) {
+               err = lyd_new_term(parent, snode->module, snode->name, *p, false, NULL);
+               if (err != LY_SUCCESS)
+                       return NB_ERR_RESOURCE;
+       }
+
+       return NB_OK;
+}
+
+/* clang-format off */
+const struct frr_yang_module_info frr_backend_info = {
+       .name = "frr-backend",
+       .nodes = {
+               {
+                       .xpath = "/frr-backend:clients/client",
+                       .cbs = {
+                               .get_next = clients_client_get_next,
+                               .get_keys = clients_client_get_keys,
+                               .lookup_entry = clients_client_lookup_entry,
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/name",
+                       .cbs.get = clients_client_name_get,
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/candidate-config-version",
+                       .cbs = {
+                               .get = clients_client_state_candidate_config_version_get,
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/running-config-version",
+                       .cbs = {
+                               .get = clients_client_state_running_config_version_get,
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/edit-count",
+                       .cbs = {
+                               .get = nb_oper_uint64_get,
+                               .get_elem = (void *)(intptr_t)offsetof(struct mgmt_be_client, num_edit_nb_cfg),
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/avg-edit-time",
+                       .cbs = {
+                               .get = nb_oper_uint64_get,
+                               .get_elem = (void *)(intptr_t)offsetof(struct mgmt_be_client, avg_edit_nb_cfg_tm),
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/prep-count",
+                       .cbs = {
+                               .get = nb_oper_uint64_get,
+                               .get_elem = (void *)(intptr_t)offsetof(struct mgmt_be_client, num_prep_nb_cfg),
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/avg-prep-time",
+                       .cbs = {
+                               .get = nb_oper_uint64_get,
+                               .get_elem = (void *)(intptr_t)offsetof(struct mgmt_be_client, avg_prep_nb_cfg_tm),
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/apply-count",
+                       .cbs = {
+                               .get = nb_oper_uint64_get,
+                               .get_elem = (void *)(intptr_t)offsetof(struct mgmt_be_client, num_apply_nb_cfg),
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/avg-apply-time",
+                       .cbs = {
+                               .get = nb_oper_uint64_get,
+                               .get_elem = (void *)(intptr_t)offsetof(struct mgmt_be_client, avg_apply_nb_cfg_tm),
+                       }
+               },
+               {
+                       .xpath = "/frr-backend:clients/client/state/notify-selectors",
+                       .cbs.get = clients_client_state_notify_selectors_get,
+               },
+               {
+                       .xpath = NULL,
+               },
+       }
+};
+/* clang-format on */
+
 struct mgmt_be_client *mgmt_be_client_create(const char *client_name,
                                             struct mgmt_be_client_cbs *cbs,
                                             uintptr_t user_data,
index a3e3896d52954896e89f19374bc0ec0b9dcc2847..5e78f0f433a7b5b58ead36064daa61ed1c8c0534 100644 (file)
@@ -85,6 +85,8 @@ struct mgmt_be_client_cbs {
 
 extern struct debug mgmt_dbg_be_client;
 
+extern const struct frr_yang_module_info frr_backend_info;
+
 /***************************************************************
  * API prototypes
  ***************************************************************/
index bd802e0888f94c4b77828c97ab109a456cd5f40c..ce59bfd01a43f2e6a598999bf0341dac4aec1b28 100644 (file)
@@ -836,6 +836,9 @@ extern struct debug nb_dbg_libyang;
 /* Global running configuration. */
 extern struct nb_config *running_config;
 
+/* Global notification filters */
+extern const char **nb_notif_filters;
+
 /* Wrappers for the northbound callbacks. */
 extern struct yang_data *nb_callback_has_new_get_elem(const struct nb_node *nb_node);
 
@@ -1521,6 +1524,13 @@ extern void *nb_oper_walk_finish_arg(void *walk);
  */
 extern void *nb_oper_walk_cb_arg(void *walk);
 
+/* Generic getter functions */
+extern enum nb_error nb_oper_uint32_get(const struct nb_node *nb_node,
+                                       const void *parent_list_entry, struct lyd_node *parent);
+
+extern enum nb_error nb_oper_uint64_get(const struct nb_node *nb_node,
+                                       const void *parent_list_entry, struct lyd_node *parent);
+
 /*
  * Validate if the northbound callback operation is valid for the given node.
  *
index a296b147acc3d6c6c86c10b30276b7fd3f7eaa7d..6336db502aaeb4ec4f7b9cd430011fdbaa939545 100644 (file)
@@ -1918,6 +1918,87 @@ enum nb_error nb_oper_iterate_legacy(const char *xpath,
        return ret;
 }
 
+static const char *__adjust_ptr(struct lysc_node_leaf *lsnode, const char *valuep, size_t *size)
+{
+       switch (lsnode->type->basetype) {
+       case LY_TYPE_INT8:
+       case LY_TYPE_UINT8:
+#ifdef BIG_ENDIAN
+               valuep += 7;
+#endif
+               *size = 1;
+               break;
+       case LY_TYPE_INT16:
+       case LY_TYPE_UINT16:
+#ifdef BIG_ENDIAN
+               valuep += 6;
+#endif
+               *size = 2;
+               break;
+       case LY_TYPE_INT32:
+       case LY_TYPE_UINT32:
+#ifdef BIG_ENDIAN
+               valuep += 4;
+#endif
+               *size = 4;
+               break;
+       case LY_TYPE_INT64:
+       case LY_TYPE_UINT64:
+               *size = 8;
+               break;
+       case LY_TYPE_UNKNOWN:
+       case LY_TYPE_BINARY:
+       case LY_TYPE_STRING:
+       case LY_TYPE_BITS:
+       case LY_TYPE_BOOL:
+       case LY_TYPE_DEC64:
+       case LY_TYPE_EMPTY:
+       case LY_TYPE_ENUM:
+       case LY_TYPE_IDENT:
+       case LY_TYPE_INST:
+       case LY_TYPE_LEAFREF:
+       case LY_TYPE_UNION:
+       default:
+               assert(0);
+       }
+       return valuep;
+}
+
+enum nb_error nb_oper_uint64_get(const struct nb_node *nb_node, const void *parent_list_entry,
+                                struct lyd_node *parent)
+{
+       struct lysc_node_leaf *lsnode = (struct lysc_node_leaf *)nb_node->snode;
+       struct lysc_node *snode = &lsnode->node;
+       ssize_t offset = (ssize_t)nb_node->cbs.get_elem;
+       uint64_t ubigval = *(uint64_t *)((char *)parent_list_entry + offset);
+       const char *valuep;
+       size_t size;
+
+       valuep = __adjust_ptr(lsnode, (const char *)&ubigval, &size);
+       if (lyd_new_term_bin(parent, snode->module, snode->name, valuep, size, LYD_NEW_PATH_UPDATE,
+                            NULL))
+               return NB_ERR_RESOURCE;
+       return NB_OK;
+}
+
+
+enum nb_error nb_oper_uint32_get(const struct nb_node *nb_node, const void *parent_list_entry,
+                                struct lyd_node *parent)
+{
+       struct lysc_node_leaf *lsnode = (struct lysc_node_leaf *)nb_node->snode;
+       struct lysc_node *snode = &lsnode->node;
+       ssize_t offset = (ssize_t)nb_node->cbs.get_elem;
+       uint64_t ubigval = *(uint64_t *)((char *)parent_list_entry + offset);
+       const char *valuep;
+       size_t size;
+
+       valuep = __adjust_ptr(lsnode, (const char *)&ubigval, &size);
+       if (lyd_new_term_bin(parent, snode->module, snode->name, valuep, size, LYD_NEW_PATH_UPDATE,
+                            NULL))
+               return NB_ERR_RESOURCE;
+       return NB_OK;
+}
+
 void nb_oper_init(struct event_loop *loop)
 {
        event_loop = loop;
index 984e92ff17fdc9107cf07b73c4fefcda05091cd1..a975eb2fc46fd2448b84469a5fe25403f1be7397 100644 (file)
@@ -145,6 +145,7 @@ lib_libfrr_la_SOURCES = \
 
 nodist_lib_libfrr_la_SOURCES = \
        yang/frr-affinity-map.yang.c \
+       yang/frr-backend.yang.c \
        yang/frr-filter.yang.c \
        yang/frr-if-rmap.yang.c \
        yang/frr-interface.yang.c \
index e159d68ec0e590428e25b1bef6850f3e9f6ac532..1c32f936b0220e5acccd7755770a908d899237af 100644 (file)
@@ -77,6 +77,7 @@ static const char *const zebra_config_xpaths[] = {
 };
 
 static const char *const zebra_oper_xpaths[] = {
+       "/frr-backend:clients",
        "/frr-interface:lib/interface",
        "/frr-vrf:lib/vrf/frr-zebra:zebra",
        "/frr-zebra:zebra",
@@ -94,6 +95,7 @@ static const char *const ripd_config_xpaths[] = {
        NULL,
 };
 static const char *const ripd_oper_xpaths[] = {
+       "/frr-backend:clients",
        "/frr-ripd:ripd",
        "/ietf-key-chain:key-chains",
        NULL,
@@ -114,6 +116,7 @@ static const char *const ripngd_config_xpaths[] = {
        NULL,
 };
 static const char *const ripngd_oper_xpaths[] = {
+       "/frr-backend:clients",
        "/frr-ripngd:ripngd",
        NULL,
 };
@@ -130,6 +133,11 @@ static const char *const staticd_config_xpaths[] = {
        "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
        NULL,
 };
+
+static const char *const staticd_oper_xpaths[] = {
+       "/frr-backend:clients",
+       NULL,
+};
 #endif
 
 static const char *const *be_client_config_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
@@ -151,6 +159,9 @@ static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
 #endif
 #ifdef HAVE_RIPNGD
        [MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_oper_xpaths,
+#endif
+#ifdef HAVE_STATICD
+       [MGMTD_BE_CLIENT_ID_STATICD] = staticd_oper_xpaths,
 #endif
        [MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths,
 };
index 1880d94415fa36906ab854aced10759701519fe5..7d909446c3bfdac687233feda2d512fc3041cb11 100644 (file)
@@ -159,6 +159,12 @@ const struct frr_yang_module_info ietf_netconf_with_defaults_info = {
  * clients into mgmtd. The modules are used by libyang in order to support
  * parsing binary data returns from the backend.
  */
+const struct frr_yang_module_info frr_backend_client_info = {
+       .name = "frr-backend",
+       .ignore_cfg_cbs = true,
+       .nodes = { { .xpath = NULL } },
+};
+
 const struct frr_yang_module_info zebra_route_map_info = {
        .name = "frr-zebra-route-map",
        .ignore_cfg_cbs = true,
@@ -183,6 +189,7 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
        /*
         * YANG module info used by backend clients get added here.
         */
+       &frr_backend_client_info,
 
        &frr_zebra_cli_info,
        &zebra_route_map_info,
index 67469f5fe52c2987a256b881243d4d6979f36c0e..cfe4a7e4376248ca92f7c3ad78a2b22a7281e7a7 100644 (file)
@@ -127,6 +127,7 @@ static struct frr_signal_t ripd_signals[] = {
 };
 
 static const struct frr_yang_module_info *const ripd_yang_modules[] = {
+       &frr_backend_info,
        &frr_filter_info,
        &frr_interface_info,
        &frr_ripd_info,
index ada9ad4e78b9ccccbf47c185182cce979549a7da..b3584b9c3a7e0f6555e7f8639eba501f5ca668e3 100644 (file)
@@ -120,6 +120,7 @@ struct frr_signal_t ripng_signals[] = {
 };
 
 static const struct frr_yang_module_info *const ripngd_yang_modules[] = {
+       &frr_backend_info,
        &frr_filter_info,
        &frr_interface_info,
        &frr_ripngd_info,
index 9468a98b833e6c8fa1a8e800df04a81a2484f2d3..5e74326e38be663eb920267e39ed0b854b1d87e6 100644 (file)
@@ -107,6 +107,7 @@ struct frr_signal_t static_signals[] = {
 };
 
 static const struct frr_yang_module_info *const staticd_yang_modules[] = {
+       &frr_backend_info,
        &frr_interface_info,
        &frr_vrf_info,
        &frr_routing_info,
diff --git a/yang/frr-backend.yang b/yang/frr-backend.yang
new file mode 100644 (file)
index 0000000..7149cbb
--- /dev/null
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: BSD-2-Clause
+module frr-backend {
+  yang-version 1.1;
+  namespace "http://frrouting.org/yang/oper";
+  prefix frr-backend;
+
+  organization
+    "FRRouting";
+  contact
+    "FRR Users List:       <mailto:frog@lists.frrouting.org>
+     FRR Development List: <mailto:dev@lists.frrouting.org>";
+  description
+    "This module defines a model for FRR backend management.
+
+     Copyright (c) 2024, LabN Consulting, L.L.C.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, are permitted provided that the following conditions
+     are met:
+
+     1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+     2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+     \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
+
+  revision 2024-12-29 {
+    description "Initial revision";
+    reference "FRR source code";
+  }
+
+  container clients {
+    config false;
+    description "The backend clients";
+
+    list client {
+      key name;
+      description "A backend client";
+
+      leaf name {
+        type string;
+        description "Name of the backend client";
+      }
+
+      container state {
+        description "FRR backend operational state";
+
+        leaf candidate-config-version {
+          type uint64;
+          description "Local candidate config version.";
+        }
+        leaf running-config-version {
+          type uint64;
+          description "Local running config version.";
+        }
+        leaf edit-count {
+          type uint64;
+          description "Number of config edits handled.";
+        }
+        leaf avg-edit-time {
+          type uint64;
+          description "Average edit time in microseconds.";
+        }
+        leaf prep-count {
+          type uint64;
+          description "Number of config preps handled.";
+        }
+        leaf avg-prep-time {
+          type uint64;
+          description "Average prep time in microseconds.";
+        }
+        leaf apply-count {
+          type uint64;
+          description "Number of config applies handled.";
+        }
+        leaf avg-apply-time {
+          type uint64;
+          description "Average apply time in microseconds.";
+        }
+        leaf-list notify-selectors {
+          type string;
+          description
+            "List of paths identifying which state to send change
+               notifications for.";
+        }
+      }
+    }
+  }
+}
index 786bd0bca65466712ad1109bfc11fde31257da35..9d4bc8e78d671c4caeb3d4d3768b9f9ec5c5f2de 100644 (file)
@@ -20,6 +20,7 @@ EXTRA_DIST += yang/embedmodel.py
 # without problems, as seen in libfrr.
 
 dist_yangmodels_DATA += yang/frr-affinity-map.yang
+dist_yangmodels_DATA += yang/frr-backend.yang
 dist_yangmodels_DATA += yang/frr-filter.yang
 dist_yangmodels_DATA += yang/frr-module-translator.yang
 dist_yangmodels_DATA += yang/frr-nexthop.yang
index 47b4a44082b9e66fc0901968995a76b3ecda5e9d..d189d1e0a0334568e2ca95d9ae775489d24580a7 100644 (file)
@@ -287,6 +287,7 @@ struct frr_signal_t zebra_signals[] = {
 
 /* clang-format off */
 static const struct frr_yang_module_info *const zebra_yang_modules[] = {
+       &frr_backend_info,
        &frr_filter_info,
        &frr_interface_info,
        &frr_route_map_info,