summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format1
-rw-r--r--lib/frrstr.c24
-rw-r--r--lib/frrstr.h8
-rw-r--r--lib/mgmt_be_client.c7
-rw-r--r--lib/mgmt_be_client.h44
-rw-r--r--lib/yang.c9
-rw-r--r--mgmtd/mgmt_be_adapter.c462
-rw-r--r--mgmtd/mgmt_be_adapter.h61
-rw-r--r--mgmtd/mgmt_txn.c51
-rw-r--r--mgmtd/mgmt_vty.c2
-rwxr-xr-xtools/checkpatch.pl3
-rwxr-xr-xtools/checkpatch.sh3
12 files changed, 303 insertions, 372 deletions
diff --git a/.clang-format b/.clang-format
index 3971384a36..5f21a3f324 100644
--- a/.clang-format
+++ b/.clang-format
@@ -103,6 +103,7 @@ ForEachMacros:
- 'FOREACH_AFI_SAFI'
- 'FOREACH_AFI_SAFI_NSF'
- 'FOREACH_BE_APPLY_BATCH_IN_LIST'
+ - 'FOREACH_BE_CLIENT_BITS'
- 'FOREACH_BE_TXN_BATCH_IN_LIST'
- 'FOREACH_BE_TXN_IN_LIST'
- 'FOREACH_CMT_REC'
diff --git a/lib/frrstr.c b/lib/frrstr.c
index e5440c5093..bb112afef7 100644
--- a/lib/frrstr.c
+++ b/lib/frrstr.c
@@ -3,6 +3,7 @@
* FRR string processing utilities.
* Copyright (C) 2018 Cumulus Networks, Inc.
* Quentin Young
+ * Copyright (c) 2023, LabN Consulting, L.L.C.
*/
#include "zebra.h"
@@ -225,3 +226,26 @@ char *frrstr_hex(char *buff, size_t bufsiz, const uint8_t *str, size_t num)
return buff;
}
+
+const char *frrstr_skip_over_char(const char *s, int skipc)
+{
+ int c, quote = 0;
+
+ while ((c = *s++)) {
+ if (c == '\\') {
+ if (!*s++)
+ return NULL;
+ continue;
+ }
+ if (quote) {
+ if (c == quote)
+ quote = 0;
+ continue;
+ }
+ if (c == skipc)
+ return s;
+ if (c == '"' || c == '\'')
+ quote = c;
+ }
+ return NULL;
+}
diff --git a/lib/frrstr.h b/lib/frrstr.h
index 19ba09e213..9a4fe257a2 100644
--- a/lib/frrstr.h
+++ b/lib/frrstr.h
@@ -3,6 +3,7 @@
* FRR string processing utilities.
* Copyright (C) 2018 Cumulus Networks, Inc.
* Quentin Young
+ * Copyright (c) 2023, LabN Consulting, L.L.C.
*/
#ifndef _FRRSTR_H_
@@ -166,6 +167,13 @@ int all_digit(const char *str);
*/
char *frrstr_hex(char *buff, size_t bufsiz, const uint8_t *str, size_t num);
+
+/*
+ * Advance past a given char `skipc` in a string, while honoring quoting and
+ * backslash escapes (i.e., ignore `skipc` which occur in quoted sections).
+ */
+const char *frrstr_skip_over_char(const char *s, int skipc);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c
index be10dcf6a1..762ace1361 100644
--- a/lib/mgmt_be_client.c
+++ b/lib/mgmt_be_client.c
@@ -118,13 +118,6 @@ struct mgmt_be_client {
struct debug mgmt_dbg_be_client = {0, "Management backend client operations"};
-const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1] = {
-#ifdef HAVE_STATICD
- [MGMTD_BE_CLIENT_ID_STATICD] = "staticd",
-#endif
- [MGMTD_BE_CLIENT_ID_MAX] = "Unknown/Invalid",
-};
-
static int mgmt_be_client_send_msg(struct mgmt_be_client *client_ctx,
Mgmtd__BeMessage *be_msg)
{
diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h
index 4ad5ca5957..051c908a37 100644
--- a/lib/mgmt_be_client.h
+++ b/lib/mgmt_be_client.h
@@ -17,27 +17,6 @@ extern "C" {
#include "mgmtd/mgmt_defines.h"
/***************************************************************
- * Client IDs
- ***************************************************************/
-
-/*
- * Add enum value for each supported component, wrap with
- * #ifdef HAVE_COMPONENT
- */
-enum mgmt_be_client_id {
- MGMTD_BE_CLIENT_ID_MIN = 0,
- MGMTD_BE_CLIENT_ID_INIT = -1,
-#ifdef HAVE_STATICD
- MGMTD_BE_CLIENT_ID_STATICD,
-#endif
- MGMTD_BE_CLIENT_ID_MAX
-};
-
-#define FOREACH_MGMTD_BE_CLIENT_ID(id) \
- for ((id) = MGMTD_BE_CLIENT_ID_MIN; \
- (id) < MGMTD_BE_CLIENT_ID_MAX; (id)++)
-
-/***************************************************************
* Constants
***************************************************************/
@@ -108,29 +87,6 @@ struct mgmt_be_client_cbs {
* Global data exported
***************************************************************/
-extern const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1];
-
-static inline const char *mgmt_be_client_id2name(enum mgmt_be_client_id id)
-{
- if (id > MGMTD_BE_CLIENT_ID_MAX)
- id = MGMTD_BE_CLIENT_ID_MAX;
- return mgmt_be_client_names[id];
-}
-
-static inline enum mgmt_be_client_id
-mgmt_be_client_name2id(const char *name)
-{
- enum mgmt_be_client_id id;
-
- FOREACH_MGMTD_BE_CLIENT_ID (id) {
- if (!strncmp(mgmt_be_client_names[id], name,
- MGMTD_CLIENT_NAME_MAX_LEN))
- return id;
- }
-
- return MGMTD_BE_CLIENT_ID_MAX;
-}
-
extern struct debug mgmt_dbg_be_client;
/***************************************************************
diff --git a/lib/yang.c b/lib/yang.c
index 4dd8654217..7046091baa 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -254,15 +254,8 @@ struct lysc_node *yang_find_snode(struct ly_ctx *ly_ctx, const char *xpath,
uint32_t options)
{
struct lysc_node *snode;
- struct ly_set *set;
- LY_ERR err;
- err = lys_find_xpath(ly_native_ctx, NULL, xpath, options, &set);
- if (err || !set->count)
- return NULL;
-
- snode = set->snodes[0];
- ly_set_free(set, NULL);
+ snode = (struct lysc_node *)lys_find_path(ly_ctx, NULL, xpath, 0);
return snode;
}
diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c
index 5ab11ea491..8330f6f36b 100644
--- a/mgmtd/mgmt_be_adapter.c
+++ b/mgmtd/mgmt_be_adapter.c
@@ -10,6 +10,7 @@
#include <zebra.h>
#include "darr.h"
#include "frrevent.h"
+#include "frrstr.h"
#include "sockopt.h"
#include "network.h"
#include "libfrr.h"
@@ -28,29 +29,27 @@
#define FOREACH_ADAPTER_IN_LIST(adapter) \
frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter))
-/*
- * Mapping of YANG XPath regular expressions to
- * their corresponding backend clients.
- */
-struct mgmt_be_xpath_map {
- char *xpath_regexp;
- uint subscr_info[MGMTD_BE_CLIENT_ID_MAX];
-};
+/* ---------- */
+/* Client IDs */
+/* ---------- */
-struct mgmt_be_client_xpath {
- const char *xpath;
- uint subscribed;
+const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1] = {
+#ifdef HAVE_STATICD
+ [MGMTD_BE_CLIENT_ID_STATICD] = "staticd",
+#endif
+ [MGMTD_BE_CLIENT_ID_MAX] = "Unknown/Invalid",
};
-struct mgmt_be_client_xpath_map {
- struct mgmt_be_client_xpath *xpaths;
- uint nxpaths;
-};
+/* ------------- */
+/* XPATH MAPPING */
+/* ------------- */
-struct mgmt_be_get_adapter_config_params {
- struct mgmt_be_client_adapter *adapter;
- struct nb_config_cbs *cfg_chgs;
- uint32_t seq;
+/*
+ * Mapping of YANG XPath prefixes to their corresponding backend clients.
+ */
+struct mgmt_be_xpath_map {
+ char *xpath_prefix;
+ uint64_t clients;
};
/*
@@ -58,31 +57,23 @@ struct mgmt_be_get_adapter_config_params {
* above map as well.
*/
#if HAVE_STATICD
-static struct mgmt_be_client_xpath staticd_xpaths[] = {
- {
- .xpath = "/frr-vrf:lib/*",
- .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG,
- },
- {
- .xpath = "/frr-interface:lib/*",
- .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG,
- },
- {
- .xpath =
- "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/*",
- .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG,
- },
+static const char *const staticd_xpaths[] = {
+ "/frr-vrf:lib",
+ "/frr-interface:lib",
+ "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
+ NULL,
};
#endif
-static struct mgmt_be_client_xpath_map
- mgmt_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+static const char *const *be_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+
#ifdef HAVE_STATICD
- [MGMTD_BE_CLIENT_ID_STATICD] = {staticd_xpaths,
- array_size(staticd_xpaths)},
+ [MGMTD_BE_CLIENT_ID_STATICD] = staticd_xpaths,
#endif
};
+static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {};
+
/*
* We would like to have a better ADT than one with O(n) comparisons
*
@@ -91,7 +82,9 @@ static struct mgmt_be_client_xpath_map
* says this probably involves exact match/no-match on a stem in the map array
* or something like that.
*/
-static struct mgmt_be_xpath_map *mgmt_xpath_map;
+
+static struct mgmt_be_xpath_map *be_cfg_xpath_map;
+static struct mgmt_be_xpath_map *be_oper_xpath_map;
static struct event_loop *mgmt_loop;
static struct msg_server mgmt_be_server = {.fd = -1};
@@ -101,12 +94,34 @@ static struct mgmt_be_adapters_head mgmt_be_adapters;
static struct mgmt_be_client_adapter
*mgmt_be_adapters_by_id[MGMTD_BE_CLIENT_ID_MAX];
+
/* Forward declarations */
static void
mgmt_be_adapter_sched_init_event(struct mgmt_be_client_adapter *adapter);
-static uint mgmt_be_get_subscr_for_xpath_and_client(
- const char *xpath, enum mgmt_be_client_id client_id, uint subscr_mask);
+static bool be_is_client_interested(const char *xpath,
+ enum mgmt_be_client_id id, bool config);
+
+
+static const char *mgmt_be_client_id2name(enum mgmt_be_client_id id)
+{
+ if (id > MGMTD_BE_CLIENT_ID_MAX)
+ return "invalid client id";
+ return mgmt_be_client_names[id];
+}
+
+static enum mgmt_be_client_id mgmt_be_client_name2id(const char *name)
+{
+ enum mgmt_be_client_id id;
+
+ FOREACH_MGMTD_BE_CLIENT_ID (id) {
+ if (!strncmp(mgmt_be_client_names[id], name,
+ MGMTD_CLIENT_NAME_MAX_LEN))
+ return id;
+ }
+
+ return MGMTD_BE_CLIENT_ID_MAX;
+}
static struct mgmt_be_client_adapter *
mgmt_be_find_adapter_by_fd(int conn_fd)
@@ -135,178 +150,91 @@ mgmt_be_find_adapter_by_name(const char *name)
}
static void mgmt_register_client_xpath(enum mgmt_be_client_id id,
- const char *xpath, uint subscribed)
+ const char *xpath, bool config)
{
- struct mgmt_be_xpath_map *map;
+ struct mgmt_be_xpath_map **maps, *map;
- darr_foreach_p (mgmt_xpath_map, map)
- if (!strcmp(xpath, map->xpath_regexp)) {
- map->subscr_info[id] = subscribed;
+ maps = config ? &be_cfg_xpath_map : &be_oper_xpath_map;
+
+ darr_foreach_p (*maps, map) {
+ if (!strcmp(xpath, map->xpath_prefix)) {
+ map->clients |= (1u << id);
return;
}
+ }
/* we didn't find a matching entry */
- map = darr_append(mgmt_xpath_map);
- map->xpath_regexp = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
- map->subscr_info[id] = subscribed;
+ map = darr_append(*maps);
+ map->xpath_prefix = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
+ map->clients = (1ul << id);
}
/*
- * Load the initial mapping from static init map
+ * initial the combined maps from per client maps
*/
static void mgmt_be_xpath_map_init(void)
{
- struct mgmt_be_client_xpath *init, *end;
enum mgmt_be_client_id id;
+ const char *const *init;
MGMTD_BE_ADAPTER_DBG("Init XPath Maps");
FOREACH_MGMTD_BE_CLIENT_ID (id) {
- init = mgmt_client_xpaths[id].xpaths;
- end = init + mgmt_client_xpaths[id].nxpaths;
- for (; init < end; init++) {
- MGMTD_BE_ADAPTER_DBG(" - XPATH: '%s'", init->xpath);
- mgmt_register_client_xpath(id, init->xpath,
- init->subscribed);
+ /* Initialize the common config init map */
+ for (init = be_client_xpaths[id]; init && *init; init++) {
+ MGMTD_BE_ADAPTER_DBG(" - CFG XPATH: '%s'", *init);
+ mgmt_register_client_xpath(id, *init, true);
+ }
+
+ /* Initialize the common oper init map */
+ for (init = be_client_oper_xpaths[id]; init && *init; init++) {
+ MGMTD_BE_ADAPTER_DBG(" - OPER XPATH: '%s'", *init);
+ mgmt_register_client_xpath(id, *init, false);
}
}
- MGMTD_BE_ADAPTER_DBG("Total XPath Maps: %u", darr_len(mgmt_xpath_map));
+ MGMTD_BE_ADAPTER_DBG("Total Cfg XPath Maps: %u",
+ darr_len(be_cfg_xpath_map));
+ MGMTD_BE_ADAPTER_DBG("Total Oper XPath Maps: %u",
+ darr_len(be_oper_xpath_map));
}
static void mgmt_be_xpath_map_cleanup(void)
{
struct mgmt_be_xpath_map *map;
- darr_foreach_p (mgmt_xpath_map, map)
- XFREE(MTYPE_MGMTD_XPATH, map->xpath_regexp);
- darr_free(mgmt_xpath_map);
-}
-
-static int mgmt_be_eval_regexp_match(const char *xpath_regexp,
- const char *xpath)
-{
- int match_len = 0, re_indx = 0, xp_indx = 0;
- int rexp_len, xpath_len;
- bool match = true, re_wild = false, xp_wild = false;
- bool delim = false, enter_wild_match = false;
- char wild_delim = 0;
-
- rexp_len = strlen(xpath_regexp);
- xpath_len = strlen(xpath);
-
- /*
- * Remove the trailing wildcard from the regexp and Xpath.
- */
- if (rexp_len && xpath_regexp[rexp_len-1] == '*')
- rexp_len--;
- if (xpath_len && xpath[xpath_len-1] == '*')
- xpath_len--;
+ darr_foreach_p (be_cfg_xpath_map, map)
+ XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
+ darr_free(be_cfg_xpath_map);
- if (!rexp_len || !xpath_len)
- return 0;
+ darr_foreach_p (be_oper_xpath_map, map)
+ XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
+ darr_free(be_oper_xpath_map);
+}
- for (re_indx = 0, xp_indx = 0;
- match && re_indx < rexp_len && xp_indx < xpath_len;) {
- match = (xpath_regexp[re_indx] == xpath[xp_indx]);
- /*
- * Check if we need to enter wildcard matching.
- */
- if (!enter_wild_match && !match &&
- (xpath_regexp[re_indx] == '*'
- || xpath[xp_indx] == '*')) {
- /*
- * Found wildcard
- */
- enter_wild_match =
- (xpath_regexp[re_indx-1] == '/'
- || xpath_regexp[re_indx-1] == '\''
- || xpath[xp_indx-1] == '/'
- || xpath[xp_indx-1] == '\'');
- if (enter_wild_match) {
- if (xpath_regexp[re_indx] == '*') {
- /*
- * Begin RE wildcard match.
- */
- re_wild = true;
- wild_delim = xpath_regexp[re_indx-1];
- } else if (xpath[xp_indx] == '*') {
- /*
- * Begin XP wildcard match.
- */
- xp_wild = true;
- wild_delim = xpath[xp_indx-1];
- }
- }
- }
-
- /*
- * Check if we need to exit wildcard matching.
- */
- if (enter_wild_match) {
- if (re_wild && xpath[xp_indx] == wild_delim) {
- /*
- * End RE wildcard matching.
- */
- re_wild = false;
- if (re_indx < rexp_len-1)
- re_indx++;
- enter_wild_match = false;
- } else if (xp_wild
- && xpath_regexp[re_indx] == wild_delim) {
- /*
- * End XP wildcard matching.
- */
- xp_wild = false;
- if (xp_indx < xpath_len-1)
- xp_indx++;
- enter_wild_match = false;
- }
- }
-
- match = (xp_wild || re_wild
- || xpath_regexp[re_indx] == xpath[xp_indx]);
+/*
+ * Check if either path or xpath is a prefix of the other. Before checking the
+ * xpath is converted to a regular path string (e..g, removing key value
+ * specifiers).
+ */
+static bool mgmt_be_xpath_prefix(const char *path, const char *xpath)
+{
+ int xc, pc;
- /*
- * Check if we found a delimiter in both the Xpaths
- */
- if ((xpath_regexp[re_indx] == '/'
- && xpath[xp_indx] == '/')
- || (xpath_regexp[re_indx] == ']'
- && xpath[xp_indx] == ']')
- || (xpath_regexp[re_indx] == '['
- && xpath[xp_indx] == '[')) {
- /*
- * Increment the match count if we have a
- * new delimiter.
- */
- if (match && re_indx && xp_indx && !delim)
- match_len++;
- delim = true;
- } else {
- delim = false;
+ while ((xc = *xpath++)) {
+ if (xc == '[') {
+ xpath = frrstr_skip_over_char(xpath, ']');
+ if (!xpath)
+ return false;
+ continue;
}
-
- /*
- * Proceed to the next character in the RE/XP string as
- * necessary.
- */
- if (!re_wild)
- re_indx++;
- if (!xp_wild)
- xp_indx++;
+ pc = *path++;
+ if (!pc)
+ return true;
+ if (pc != xc)
+ return false;
}
-
- /*
- * If we finished matching and the last token was a full match
- * increment the match count appropriately.
- */
- if (match && !delim &&
- (xpath_regexp[re_indx] == '/'
- || xpath_regexp[re_indx] == ']'))
- match_len++;
-
- return match_len;
+ return true;
}
static void mgmt_be_adapter_delete(struct mgmt_be_client_adapter *adapter)
@@ -596,16 +524,26 @@ static void mgmt_be_adapter_process_msg(uint8_t version, uint8_t *data,
mgmtd__be_message__free_unpacked(be_msg, NULL);
}
+/*
+ * Args for callback
+ */
+struct mgmt_be_get_adapter_config_params {
+ struct mgmt_be_client_adapter *adapter;
+ struct nb_config_cbs *cfg_chgs;
+ uint32_t seq;
+};
+
+/*
+ * Callback to store the change a node in the datastore if it should be sync'd
+ * to the adapter (i.e., if the adapter is subscribed to it).
+ */
static void mgmt_be_iter_and_get_cfg(const char *xpath, struct lyd_node *node,
struct nb_node *nb_node, void *ctx)
{
struct mgmt_be_get_adapter_config_params *parms = ctx;
struct mgmt_be_client_adapter *adapter = parms->adapter;
- uint subscr;
- subscr = mgmt_be_get_subscr_for_xpath_and_client(
- xpath, adapter->id, MGMT_SUBSCR_NOTIFY_CFG);
- if (subscr)
+ if (be_is_client_interested(xpath, adapter->id, true))
nb_config_diff_created(node, &parms->seq, parms->cfg_chgs);
}
@@ -752,6 +690,10 @@ mgmt_be_get_adapter_by_name(const char *name)
return mgmt_be_find_adapter_by_name(name);
}
+/*
+ * Get a full set of changes for all the config that an adapter is subscribed to
+ * receive.
+ */
int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
struct nb_config_cbs **cfg_chgs)
{
@@ -780,72 +722,65 @@ int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
return 0;
}
-void mgmt_be_get_subscr_info_for_xpath(
- const char *xpath, struct mgmt_be_client_subscr_info *subscr_info)
+uint64_t mgmt_be_interested_clients(const char *xpath, bool config)
{
- struct mgmt_be_xpath_map *map;
+ struct mgmt_be_xpath_map *maps, *map;
enum mgmt_be_client_id id;
+ uint64_t clients;
- memset(subscr_info, 0, sizeof(*subscr_info));
+ maps = config ? be_cfg_xpath_map : be_oper_xpath_map;
+
+ clients = 0;
MGMTD_BE_ADAPTER_DBG("XPATH: '%s'", xpath);
- darr_foreach_p (mgmt_xpath_map, map) {
- if (!mgmt_be_eval_regexp_match(map->xpath_regexp, xpath))
- continue;
- FOREACH_MGMTD_BE_CLIENT_ID (id) {
- subscr_info->xpath_subscr[id] |= map->subscr_info[id];
- }
- }
+ darr_foreach_p (maps, map)
+ if (mgmt_be_xpath_prefix(map->xpath_prefix, xpath))
+ clients |= map->clients;
if (DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL)) {
- FOREACH_MGMTD_BE_CLIENT_ID (id) {
- if (!subscr_info->xpath_subscr[id])
- continue;
- MGMTD_BE_ADAPTER_DBG("Cient: %s: subscribed: 0x%x",
- mgmt_be_client_id2name(id),
- subscr_info->xpath_subscr[id]);
- }
+ FOREACH_BE_CLIENT_BITS (id, clients)
+ MGMTD_BE_ADAPTER_DBG("Cient: %s: subscribed",
+ mgmt_be_client_id2name(id));
}
+ return clients;
}
/**
- * Return the subscription info bits for a given `xpath` for a given
- * `client_id`.
+ * Return true if `client_id` is interested in `xpath` for `config`
+ * or oper (!`config`).
*
* Args:
- * xpath - the xpath to check for subscription information.
+ * xpath - the xpath to check for interest.
* client_id - the BE client being checked for.
- * subscr_mask - The subscr bits the caller is interested in seeing
- * if set.
+ * bool - check for config (vs oper) subscription.
*
* Returns:
- * The subscription info bits.
+ * Interested or not.
*/
-static uint mgmt_be_get_subscr_for_xpath_and_client(
- const char *xpath, enum mgmt_be_client_id client_id, uint subscr_mask)
+static bool be_is_client_interested(const char *xpath,
+ enum mgmt_be_client_id id, bool config)
{
- struct mgmt_be_client_xpath_map *map;
- uint subscr = 0;
- uint i;
+ const char *const *xpaths;
- assert(client_id < MGMTD_BE_CLIENT_ID_MAX);
+ assert(id < MGMTD_BE_CLIENT_ID_MAX);
MGMTD_BE_ADAPTER_DBG("Checking client: %s for xpath: '%s'",
- mgmt_be_client_id2name(client_id), xpath);
-
- map = &mgmt_client_xpaths[client_id];
- for (i = 0; i < map->nxpaths; i++) {
- if (!mgmt_be_eval_regexp_match(map->xpaths[i].xpath, xpath))
- continue;
- MGMTD_BE_ADAPTER_DBG("xpath: %s: matched: %s",
- map->xpaths[i].xpath, xpath);
- subscr |= map->xpaths[i].subscribed;
- if ((subscr & subscr_mask) == subscr_mask)
- break;
+ mgmt_be_client_id2name(id), xpath);
+
+ xpaths = config ? be_client_xpaths[id] : be_client_oper_xpaths[id];
+ if (xpaths) {
+ for (; *xpaths; xpaths++) {
+ if (mgmt_be_xpath_prefix(*xpaths, xpath)) {
+ MGMTD_BE_ADAPTER_DBG("xpath: %s: matched: %s",
+ *xpaths, xpath);
+ return true;
+ }
+ }
}
- MGMTD_BE_ADAPTER_DBG("client: %s: subscribed: 0x%x",
- mgmt_be_client_id2name(client_id), subscr);
- return subscr;
+
+ MGMTD_BE_ADAPTER_DBG("client: %s: not interested",
+ mgmt_be_client_id2name(id));
+ return false;
}
void mgmt_be_adapter_status_write(struct vty *vty)
@@ -872,56 +807,49 @@ void mgmt_be_adapter_status_write(struct vty *vty)
(int)mgmt_be_adapters_count(&mgmt_be_adapters));
}
-void mgmt_be_xpath_register_write(struct vty *vty)
+static void be_show_xpath_register(struct vty *vty,
+ struct mgmt_be_xpath_map *map)
{
- struct mgmt_be_xpath_map *map;
enum mgmt_be_client_id id;
- struct mgmt_be_client_adapter *adapter;
- uint info;
-
- vty_out(vty, "MGMTD Backend XPath Registry\n");
-
- darr_foreach_p (mgmt_xpath_map, map) {
- vty_out(vty, " - XPATH: '%s'\n", map->xpath_regexp);
- FOREACH_MGMTD_BE_CLIENT_ID (id) {
- info = map->subscr_info[id];
- if (!info)
- continue;
- vty_out(vty,
- " -- Client: '%s'\tValidate:%d, Notify:%d, Own:%d\n",
- mgmt_be_client_id2name(id),
- (info & MGMT_SUBSCR_VALIDATE_CFG) != 0,
- (info & MGMT_SUBSCR_NOTIFY_CFG) != 0,
- (info & MGMT_SUBSCR_OPER_OWN) != 0);
- adapter = mgmt_be_get_adapter_by_id(id);
- if (adapter)
- vty_out(vty, " -- Adapter: %p\n", adapter);
- }
+ const char *astr;
+
+ vty_out(vty, " - xpath: '%s'\n", map->xpath_prefix);
+ FOREACH_BE_CLIENT_BITS (id, map->clients) {
+ astr = mgmt_be_get_adapter_by_id(id) ? "active" : "inactive";
+ vty_out(vty, " -- %s-client: '%s'\n", astr,
+ mgmt_be_client_id2name(id));
}
+}
+void mgmt_be_xpath_register_write(struct vty *vty)
+{
+ struct mgmt_be_xpath_map *map;
- vty_out(vty, "Total XPath Registries: %u\n", darr_len(mgmt_xpath_map));
+ vty_out(vty, "MGMTD Backend CFG XPath Registry: Count: %u\n",
+ darr_len(be_oper_xpath_map));
+ darr_foreach_p (be_cfg_xpath_map, map)
+ be_show_xpath_register(vty, map);
+
+ vty_out(vty, "\nMGMTD Backend OPER XPath Registry: Count: %u\n",
+ darr_len(be_oper_xpath_map));
+ darr_foreach_p (be_oper_xpath_map, map)
+ be_show_xpath_register(vty, map);
}
-void mgmt_be_xpath_subscr_info_write(struct vty *vty, const char *xpath)
+void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath)
{
- struct mgmt_be_client_subscr_info subscr;
enum mgmt_be_client_id id;
struct mgmt_be_client_adapter *adapter;
- uint info;
+ uint64_t cclients, oclients, combined;
- mgmt_be_get_subscr_info_for_xpath(xpath, &subscr);
+ cclients = mgmt_be_interested_clients(xpath, true);
+ oclients = mgmt_be_interested_clients(xpath, false);
+ combined = cclients | oclients;
vty_out(vty, "XPath: '%s'\n", xpath);
- FOREACH_MGMTD_BE_CLIENT_ID (id) {
- info = subscr.xpath_subscr[id];
- if (!info)
- continue;
- vty_out(vty,
- " -- Client: '%s'\tValidate:%d, Notify:%d, Own:%d\n",
- mgmt_be_client_id2name(id),
- (info & MGMT_SUBSCR_VALIDATE_CFG) != 0,
- (info & MGMT_SUBSCR_NOTIFY_CFG) != 0,
- (info & MGMT_SUBSCR_OPER_OWN) != 0);
+ FOREACH_BE_CLIENT_BITS (id, combined) {
+ vty_out(vty, " -- Client: '%s'\tconfig:%d oper:%d\n",
+ mgmt_be_client_id2name(id), IS_IDBIT_SET(cclients, id),
+ IS_IDBIT_SET(oclients, id));
adapter = mgmt_be_get_adapter_by_id(id);
if (adapter)
vty_out(vty, " -- Adapter: %p\n", adapter);
diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h
index ca8f55c457..0597136c8a 100644
--- a/mgmtd/mgmt_be_adapter.h
+++ b/mgmtd/mgmt_be_adapter.h
@@ -20,6 +20,22 @@
#define MGMTD_FIND_ADAPTER_BY_INDEX(adapter_index) \
mgmt_adaptr_ref[adapter_index]
+/**
+ * CLIENT-ID
+ *
+ * Add enum value for each supported component, wrap with
+ * #ifdef HAVE_COMPONENT
+ */
+enum mgmt_be_client_id {
+ MGMTD_BE_CLIENT_ID_MIN = 0,
+ MGMTD_BE_CLIENT_ID_INIT = -1,
+#ifdef HAVE_STATICD
+ MGMTD_BE_CLIENT_ID_STATICD,
+#endif
+ MGMTD_BE_CLIENT_ID_MAX
+};
+
+
enum mgmt_be_req_type {
MGMTD_BE_REQ_NONE = 0,
MGMTD_BE_REQ_CFG_VALIDATE,
@@ -49,8 +65,6 @@ struct mgmt_be_client_adapter {
enum mgmt_be_client_id id;
uint32_t flags;
char name[MGMTD_CLIENT_NAME_MAX_LEN];
- uint8_t num_xpath_reg;
- char xpath_reg[MGMTD_MAX_NUM_XPATH_REG][MGMTD_MAX_XPATH_LEN];
int refcount;
@@ -81,9 +95,36 @@ DECLARE_LIST(mgmt_be_adapters, struct mgmt_be_client_adapter, list_linkage);
#define MGMT_SUBSCR_OPER_OWN 0x4
#define MGMT_SUBSCR_ALL 0x7
-struct mgmt_be_client_subscr_info {
- uint xpath_subscr[MGMTD_BE_CLIENT_ID_MAX];
-};
+/* --------- */
+/* CLIENT-ID */
+/* --------- */
+
+#define FOREACH_MGMTD_BE_CLIENT_ID(id) \
+ for ((id) = MGMTD_BE_CLIENT_ID_MIN; (id) < MGMTD_BE_CLIENT_ID_MAX; \
+ (id)++)
+
+#define IS_IDBIT_SET(v, id) (!IS_IDBIT_UNSET(v, id))
+#define IS_IDBIT_UNSET(v, id) (!((v) & (1ull << (id))))
+
+#define __GET_NEXT_SET(id, bits) \
+ ({ \
+ enum mgmt_be_client_id __id = (id); \
+ \
+ for (; __id < MGMTD_BE_CLIENT_ID_MAX && \
+ IS_IDBIT_UNSET(bits, __id); \
+ __id++) \
+ ; \
+ __id; \
+ })
+
+#define FOREACH_BE_CLIENT_BITS(id, bits) \
+ for ((id) = __GET_NEXT_SET(MGMTD_BE_CLIENT_ID_MIN, bits); \
+ (id) < MGMTD_BE_CLIENT_ID_MAX; \
+ (id) = __GET_NEXT_SET((id) + 1, bits))
+
+/* ---------- */
+/* Prototypes */
+/* ---------- */
/* Initialise backend adapter module. */
extern void mgmt_be_adapter_init(struct event_loop *tm);
@@ -177,17 +218,13 @@ extern void mgmt_be_xpath_register_write(struct vty *vty);
*
* Args:
* xpath - the xpath to check for subscription information.
- * subscr_info - An array of uint indexed by client id
- * each eleemnt holds the subscription info
- * for that client.
+ * config - true for config interest false for oper interest.
*/
-extern void mgmt_be_get_subscr_info_for_xpath(
- const char *xpath, struct mgmt_be_client_subscr_info *subscr_info);
+extern uint64_t mgmt_be_interested_clients(const char *xpath, bool config);
/*
* Dump backend client information for a given xpath to vty.
*/
-extern void mgmt_be_xpath_subscr_info_write(struct vty *vty,
- const char *xpath);
+extern void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath);
#endif /* _FRR_MGMTD_BE_ADAPTER_H_ */
diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c
index 52d24be77d..765def7bac 100644
--- a/mgmtd/mgmt_txn.c
+++ b/mgmtd/mgmt_txn.c
@@ -80,7 +80,6 @@ struct mgmt_txn_be_cfg_batch {
uint64_t batch_id;
enum mgmt_be_client_id be_id;
struct mgmt_be_client_adapter *be_adapter;
- uint xp_subscr[MGMTD_MAX_CFG_CHANGES_IN_BATCH];
Mgmtd__YangCfgDataReq cfg_data[MGMTD_MAX_CFG_CHANGES_IN_BATCH];
Mgmtd__YangCfgDataReq *cfg_datap[MGMTD_MAX_CFG_CHANGES_IN_BATCH];
Mgmtd__YangData data[MGMTD_MAX_CFG_CHANGES_IN_BATCH];
@@ -125,7 +124,7 @@ struct mgmt_commit_cfg_req {
* Details on all the Backend Clients associated with
* this commit.
*/
- struct mgmt_be_client_subscr_info subscr_info;
+ uint64_t clients;
/*
* List of backend batches for this commit to be validated
@@ -546,8 +545,7 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req)
* send a txn delete message
*/
adapter = mgmt_be_get_adapter_by_id(id);
- if (adapter && cleanup &&
- ccreq->subscr_info.xpath_subscr[id])
+ if (adapter && cleanup && IS_IDBIT_SET(ccreq->clients, id))
mgmt_txn_send_be_txn_delete((*txn_req)->txn,
adapter);
}
@@ -915,7 +913,7 @@ mgmt_try_move_commit_to_next_phase(struct mgmt_txn_ctx *txn,
* Check if all clients has moved to next phase or not.
*/
FOREACH_MGMTD_BE_CLIENT_ID (id) {
- if (cmtcfg_req->subscr_info.xpath_subscr[id] &&
+ if (IS_IDBIT_SET(cmtcfg_req->clients, id) &&
mgmt_txn_batches_count(&cmtcfg_req->curr_batches[id])) {
/*
* There's atleast once client who hasn't moved to
@@ -991,13 +989,15 @@ mgmt_move_be_commit_to_next_phase(struct mgmt_txn_ctx *txn,
return 0;
}
+/*
+ * This is the real workhorse
+ */
static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
struct nb_config_cbs *changes)
{
struct nb_config_cb *cb, *nxt;
struct nb_config_change *chg;
struct mgmt_txn_be_cfg_batch *batch;
- struct mgmt_be_client_subscr_info subscr_info;
char *xpath = NULL, *value = NULL;
char err_buf[1024];
enum mgmt_be_client_id id;
@@ -1006,6 +1006,7 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
bool found_validator;
int num_chgs = 0;
int xpath_len, value_len;
+ uint64_t clients;
cmtcfg_req = &txn_req->req.commit_cfg;
@@ -1032,17 +1033,16 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
MGMTD_TXN_DBG("XPATH: %s, Value: '%s'", xpath,
value ? value : "NIL");
- mgmt_be_get_subscr_info_for_xpath(xpath, &subscr_info);
+ clients = mgmt_be_interested_clients(xpath, true);
+ cmtcfg_req->clients |= clients;
+ if (clients)
+ found_validator = true;
+ else
+ found_validator = false;
xpath_len = strlen(xpath) + 1;
value_len = strlen(value) + 1;
- found_validator = false;
- FOREACH_MGMTD_BE_CLIENT_ID (id) {
- if (!(subscr_info.xpath_subscr[id] &
- (MGMT_SUBSCR_VALIDATE_CFG |
- MGMT_SUBSCR_NOTIFY_CFG)))
- continue;
-
+ FOREACH_BE_CLIENT_BITS (id, clients) {
adapter = mgmt_be_get_adapter_by_id(id);
if (!adapter)
continue;
@@ -1058,9 +1058,6 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
}
batch->buf_space_left -= (xpath_len + value_len);
- memcpy(&batch->xp_subscr[batch->num_cfg_data],
- &subscr_info.xpath_subscr[id],
- sizeof(batch->xp_subscr[0]));
mgmt_yang_cfg_data_req_init(
&batch->cfg_data[batch->num_cfg_data]);
@@ -1089,12 +1086,6 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
value;
value = NULL;
- if (subscr_info.xpath_subscr[id] &
- MGMT_SUBSCR_VALIDATE_CFG)
- found_validator = true;
-
- cmtcfg_req->subscr_info.xpath_subscr[id] |=
- subscr_info.xpath_subscr[id];
MGMTD_TXN_DBG(" -- %s, batch-id: %" PRIu64 " item:%d",
adapter->name, batch->batch_id,
(int)batch->num_cfg_data);
@@ -1304,7 +1295,7 @@ static int mgmt_txn_send_be_txn_create(struct mgmt_txn_ctx *txn)
cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg;
FOREACH_MGMTD_BE_CLIENT_ID (id) {
- if (cmtcfg_req->subscr_info.xpath_subscr[id]) {
+ if (IS_IDBIT_SET(cmtcfg_req->clients, id)) {
adapter = mgmt_be_get_adapter_by_id(id);
if (mgmt_be_send_txn_req(adapter, txn->txn_id, true)) {
(void)mgmt_txn_send_commit_cfg_reply(
@@ -1350,7 +1341,7 @@ static int mgmt_txn_send_be_cfg_data(struct mgmt_txn_ctx *txn,
assert(txn->type == MGMTD_TXN_TYPE_CONFIG && txn->commit_cfg_req);
cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg;
- assert(cmtcfg_req->subscr_info.xpath_subscr[adapter->id]);
+ assert(IS_IDBIT_SET(cmtcfg_req->clients, adapter->id));
indx = 0;
num_batches =
@@ -1403,7 +1394,7 @@ static int mgmt_txn_send_be_txn_delete(struct mgmt_txn_ctx *txn,
assert(txn->type == MGMTD_TXN_TYPE_CONFIG);
assert(!mgmt_txn_batches_count(&cmtcfg_req->curr_batches[adapter->id]));
- if (!cmtcfg_req->subscr_info.xpath_subscr[adapter->id])
+ if (IS_IDBIT_UNSET(cmtcfg_req->clients, adapter->id))
return 0;
return mgmt_be_send_txn_req(adapter, txn->txn_id, false);
@@ -1462,8 +1453,7 @@ static int mgmt_txn_send_be_cfg_apply(struct mgmt_txn_ctx *txn)
}
FOREACH_MGMTD_BE_CLIENT_ID (id) {
- if (cmtcfg_req->subscr_info.xpath_subscr[id] &
- MGMT_SUBSCR_NOTIFY_CFG) {
+ if (IS_IDBIT_SET(cmtcfg_req->clients, id)) {
adapter = mgmt_be_get_adapter_by_id(id);
if (!adapter)
return -1;
@@ -2351,9 +2341,8 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter,
? &txn->commit_cfg_req->req
.commit_cfg
: NULL;
- if (cmtcfg_req &&
- cmtcfg_req->subscr_info
- .xpath_subscr[adapter->id]) {
+ if (cmtcfg_req && IS_IDBIT_SET(cmtcfg_req->clients,
+ adapter->id)) {
mgmt_txn_send_commit_cfg_reply(
txn, MGMTD_INTERNAL_ERROR,
"Backend daemon disconnected while processing commit!");
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index d8f5976f4d..e7d6966710 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -273,7 +273,7 @@ DEFPY(show_mgmt_map_xpath,
"Get YANG Backend Subscription\n"
"XPath expression specifying the YANG data path\n")
{
- mgmt_be_xpath_subscr_info_write(vty, path);
+ mgmt_be_show_xpath_registries(vty, path);
return CMD_SUCCESS;
}
diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl
index d007c1d325..e3788bde16 100755
--- a/tools/checkpatch.pl
+++ b/tools/checkpatch.pl
@@ -547,7 +547,7 @@ our $Operators = qr{
our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
our $Iterators = qr{
- frr_each|frr_each_safe|frr_each_from|
+ darr_foreach_p|darr_foreach_i|frr_each|frr_each_safe|frr_each_from|
frr_with_mutex|frr_with_privs|
LIST_FOREACH|LIST_FOREACH_SAFE|
SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR|
@@ -563,6 +563,7 @@ our $Iterators = qr{
SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE|
SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE|
AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI|
+ FOREACH_BE_CLIENT_BITS|FOREACH_MGMTD_BE_CLIENT_ID|
LSDB_LOOP
}x;
diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh
index 6071f4804d..bf63057b02 100755
--- a/tools/checkpatch.sh
+++ b/tools/checkpatch.sh
@@ -3,7 +3,8 @@
usage="./checkpatch.sh <patch> <tree>"
patch=$1
tree=$2
-checkpatch="$tree/tools/checkpatch.pl --no-tree -f"
+scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
+checkpatch="$scriptdir/checkpatch.pl --no-tree -f"
ignore="ldpd\|babeld"
cwd=${PWD##*/}
dirty=0