mirror of
https://github.com/FRRouting/frr.git
synced 2025-05-01 05:57:15 +02:00
mgmtd: simplify xpath registries
- move from client id indexed array of uints for register info per client to a u64 bitmask. - add bit walking FOREACH macro Walk the client IDs whose bits are set in a mask. Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
parent
e1b2381f40
commit
a65cda16b2
|
@ -103,6 +103,7 @@ ForEachMacros:
|
||||||
- 'FOREACH_AFI_SAFI'
|
- 'FOREACH_AFI_SAFI'
|
||||||
- 'FOREACH_AFI_SAFI_NSF'
|
- 'FOREACH_AFI_SAFI_NSF'
|
||||||
- 'FOREACH_BE_APPLY_BATCH_IN_LIST'
|
- 'FOREACH_BE_APPLY_BATCH_IN_LIST'
|
||||||
|
- 'FOREACH_BE_CLIENT_BITS'
|
||||||
- 'FOREACH_BE_TXN_BATCH_IN_LIST'
|
- 'FOREACH_BE_TXN_BATCH_IN_LIST'
|
||||||
- 'FOREACH_BE_TXN_IN_LIST'
|
- 'FOREACH_BE_TXN_IN_LIST'
|
||||||
- 'FOREACH_CMT_REC'
|
- 'FOREACH_CMT_REC'
|
||||||
|
|
24
lib/frrstr.c
24
lib/frrstr.c
|
@ -3,6 +3,7 @@
|
||||||
* FRR string processing utilities.
|
* FRR string processing utilities.
|
||||||
* Copyright (C) 2018 Cumulus Networks, Inc.
|
* Copyright (C) 2018 Cumulus Networks, Inc.
|
||||||
* Quentin Young
|
* Quentin Young
|
||||||
|
* Copyright (c) 2023, LabN Consulting, L.L.C.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "zebra.h"
|
#include "zebra.h"
|
||||||
|
@ -225,3 +226,26 @@ char *frrstr_hex(char *buff, size_t bufsiz, const uint8_t *str, size_t num)
|
||||||
|
|
||||||
return buff;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* FRR string processing utilities.
|
* FRR string processing utilities.
|
||||||
* Copyright (C) 2018 Cumulus Networks, Inc.
|
* Copyright (C) 2018 Cumulus Networks, Inc.
|
||||||
* Quentin Young
|
* Quentin Young
|
||||||
|
* Copyright (c) 2023, LabN Consulting, L.L.C.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _FRRSTR_H_
|
#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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -118,13 +118,6 @@ struct mgmt_be_client {
|
||||||
|
|
||||||
struct debug mgmt_dbg_be_client = {0, "Management backend client operations"};
|
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,
|
static int mgmt_be_client_send_msg(struct mgmt_be_client *client_ctx,
|
||||||
Mgmtd__BeMessage *be_msg)
|
Mgmtd__BeMessage *be_msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,27 +16,6 @@ extern "C" {
|
||||||
#include "mgmt_pb.h"
|
#include "mgmt_pb.h"
|
||||||
#include "mgmtd/mgmt_defines.h"
|
#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
|
* Constants
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
@ -108,29 +87,6 @@ struct mgmt_be_client_cbs {
|
||||||
* Global data exported
|
* 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;
|
extern struct debug mgmt_dbg_be_client;
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
#include "darr.h"
|
#include "darr.h"
|
||||||
#include "frrevent.h"
|
#include "frrevent.h"
|
||||||
|
#include "frrstr.h"
|
||||||
#include "sockopt.h"
|
#include "sockopt.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "libfrr.h"
|
#include "libfrr.h"
|
||||||
|
@ -28,29 +29,27 @@
|
||||||
#define FOREACH_ADAPTER_IN_LIST(adapter) \
|
#define FOREACH_ADAPTER_IN_LIST(adapter) \
|
||||||
frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter))
|
frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter))
|
||||||
|
|
||||||
|
/* ---------- */
|
||||||
|
/* Client IDs */
|
||||||
|
/* ---------- */
|
||||||
|
|
||||||
|
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",
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------- */
|
||||||
|
/* XPATH MAPPING */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mapping of YANG XPath regular expressions to
|
* Mapping of YANG XPath prefixes to their corresponding backend clients.
|
||||||
* their corresponding backend clients.
|
|
||||||
*/
|
*/
|
||||||
struct mgmt_be_xpath_map {
|
struct mgmt_be_xpath_map {
|
||||||
char *xpath_regexp;
|
char *xpath_prefix;
|
||||||
uint subscr_info[MGMTD_BE_CLIENT_ID_MAX];
|
uint64_t clients;
|
||||||
};
|
|
||||||
|
|
||||||
struct mgmt_be_client_xpath {
|
|
||||||
const char *xpath;
|
|
||||||
uint subscribed;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mgmt_be_client_xpath_map {
|
|
||||||
struct mgmt_be_client_xpath *xpaths;
|
|
||||||
uint nxpaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mgmt_be_get_adapter_config_params {
|
|
||||||
struct mgmt_be_client_adapter *adapter;
|
|
||||||
struct nb_config_cbs *cfg_chgs;
|
|
||||||
uint32_t seq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -58,31 +57,23 @@ struct mgmt_be_get_adapter_config_params {
|
||||||
* above map as well.
|
* above map as well.
|
||||||
*/
|
*/
|
||||||
#if HAVE_STATICD
|
#if HAVE_STATICD
|
||||||
static struct mgmt_be_client_xpath staticd_xpaths[] = {
|
static const char *const staticd_xpaths[] = {
|
||||||
{
|
"/frr-vrf:lib",
|
||||||
.xpath = "/frr-vrf:lib/*",
|
"/frr-interface:lib",
|
||||||
.subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG,
|
"/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
|
||||||
},
|
NULL,
|
||||||
{
|
|
||||||
.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,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct mgmt_be_client_xpath_map
|
static const char *const *be_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
|
||||||
mgmt_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
|
|
||||||
#ifdef HAVE_STATICD
|
#ifdef HAVE_STATICD
|
||||||
[MGMTD_BE_CLIENT_ID_STATICD] = {staticd_xpaths,
|
[MGMTD_BE_CLIENT_ID_STATICD] = staticd_xpaths,
|
||||||
array_size(staticd_xpaths)},
|
|
||||||
#endif
|
#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
|
* 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
|
* says this probably involves exact match/no-match on a stem in the map array
|
||||||
* or something like that.
|
* 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 event_loop *mgmt_loop;
|
||||||
static struct msg_server mgmt_be_server = {.fd = -1};
|
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
|
static struct mgmt_be_client_adapter
|
||||||
*mgmt_be_adapters_by_id[MGMTD_BE_CLIENT_ID_MAX];
|
*mgmt_be_adapters_by_id[MGMTD_BE_CLIENT_ID_MAX];
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static void
|
static void
|
||||||
mgmt_be_adapter_sched_init_event(struct mgmt_be_client_adapter *adapter);
|
mgmt_be_adapter_sched_init_event(struct mgmt_be_client_adapter *adapter);
|
||||||
|
|
||||||
static uint mgmt_be_get_subscr_for_xpath_and_client(
|
static bool be_is_client_interested(const char *xpath,
|
||||||
const char *xpath, enum mgmt_be_client_id client_id, uint subscr_mask);
|
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 *
|
static struct mgmt_be_client_adapter *
|
||||||
mgmt_be_find_adapter_by_fd(int conn_fd)
|
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,
|
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)
|
maps = config ? &be_cfg_xpath_map : &be_oper_xpath_map;
|
||||||
if (!strcmp(xpath, map->xpath_regexp)) {
|
|
||||||
map->subscr_info[id] = subscribed;
|
darr_foreach_p (*maps, map) {
|
||||||
|
if (!strcmp(xpath, map->xpath_prefix)) {
|
||||||
|
map->clients |= (1u << id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* we didn't find a matching entry */
|
/* we didn't find a matching entry */
|
||||||
map = darr_append(mgmt_xpath_map);
|
map = darr_append(*maps);
|
||||||
map->xpath_regexp = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
|
map->xpath_prefix = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
|
||||||
map->subscr_info[id] = subscribed;
|
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)
|
static void mgmt_be_xpath_map_init(void)
|
||||||
{
|
{
|
||||||
struct mgmt_be_client_xpath *init, *end;
|
|
||||||
enum mgmt_be_client_id id;
|
enum mgmt_be_client_id id;
|
||||||
|
const char *const *init;
|
||||||
|
|
||||||
MGMTD_BE_ADAPTER_DBG("Init XPath Maps");
|
MGMTD_BE_ADAPTER_DBG("Init XPath Maps");
|
||||||
|
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
||||||
init = mgmt_client_xpaths[id].xpaths;
|
/* Initialize the common config init map */
|
||||||
end = init + mgmt_client_xpaths[id].nxpaths;
|
for (init = be_client_xpaths[id]; init && *init; init++) {
|
||||||
for (; init < end; init++) {
|
MGMTD_BE_ADAPTER_DBG(" - CFG XPATH: '%s'", *init);
|
||||||
MGMTD_BE_ADAPTER_DBG(" - XPATH: '%s'", init->xpath);
|
mgmt_register_client_xpath(id, *init, true);
|
||||||
mgmt_register_client_xpath(id, init->xpath,
|
}
|
||||||
init->subscribed);
|
|
||||||
|
/* 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)
|
static void mgmt_be_xpath_map_cleanup(void)
|
||||||
{
|
{
|
||||||
struct mgmt_be_xpath_map *map;
|
struct mgmt_be_xpath_map *map;
|
||||||
|
|
||||||
darr_foreach_p (mgmt_xpath_map, map)
|
darr_foreach_p (be_cfg_xpath_map, map)
|
||||||
XFREE(MTYPE_MGMTD_XPATH, map->xpath_regexp);
|
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
|
||||||
darr_free(mgmt_xpath_map);
|
darr_free(be_cfg_xpath_map);
|
||||||
|
|
||||||
|
darr_foreach_p (be_oper_xpath_map, map)
|
||||||
|
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
|
||||||
|
darr_free(be_oper_xpath_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mgmt_be_eval_regexp_match(const char *xpath_regexp,
|
|
||||||
const char *xpath)
|
/*
|
||||||
|
* 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 match_len = 0, re_indx = 0, xp_indx = 0;
|
int xc, pc;
|
||||||
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);
|
while ((xc = *xpath++)) {
|
||||||
xpath_len = strlen(xpath);
|
if (xc == '[') {
|
||||||
|
xpath = frrstr_skip_over_char(xpath, ']');
|
||||||
/*
|
if (!xpath)
|
||||||
* Remove the trailing wildcard from the regexp and Xpath.
|
return false;
|
||||||
*/
|
continue;
|
||||||
if (rexp_len && xpath_regexp[rexp_len-1] == '*')
|
|
||||||
rexp_len--;
|
|
||||||
if (xpath_len && xpath[xpath_len-1] == '*')
|
|
||||||
xpath_len--;
|
|
||||||
|
|
||||||
if (!rexp_len || !xpath_len)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
pc = *path++;
|
||||||
|
if (!pc)
|
||||||
|
return true;
|
||||||
|
if (pc != xc)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Proceed to the next character in the RE/XP string as
|
|
||||||
* necessary.
|
|
||||||
*/
|
|
||||||
if (!re_wild)
|
|
||||||
re_indx++;
|
|
||||||
if (!xp_wild)
|
|
||||||
xp_indx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mgmt_be_adapter_delete(struct mgmt_be_client_adapter *adapter)
|
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);
|
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,
|
static void mgmt_be_iter_and_get_cfg(const char *xpath, struct lyd_node *node,
|
||||||
struct nb_node *nb_node, void *ctx)
|
struct nb_node *nb_node, void *ctx)
|
||||||
{
|
{
|
||||||
struct mgmt_be_get_adapter_config_params *parms = ctx;
|
struct mgmt_be_get_adapter_config_params *parms = ctx;
|
||||||
struct mgmt_be_client_adapter *adapter = parms->adapter;
|
struct mgmt_be_client_adapter *adapter = parms->adapter;
|
||||||
uint subscr;
|
|
||||||
|
|
||||||
subscr = mgmt_be_get_subscr_for_xpath_and_client(
|
if (be_is_client_interested(xpath, adapter->id, true))
|
||||||
xpath, adapter->id, MGMT_SUBSCR_NOTIFY_CFG);
|
|
||||||
if (subscr)
|
|
||||||
nb_config_diff_created(node, &parms->seq, parms->cfg_chgs);
|
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);
|
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,
|
int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
|
||||||
struct nb_config_cbs **cfg_chgs)
|
struct nb_config_cbs **cfg_chgs)
|
||||||
{
|
{
|
||||||
|
@ -780,72 +722,65 @@ int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mgmt_be_get_subscr_info_for_xpath(
|
uint64_t mgmt_be_interested_clients(const char *xpath, bool config)
|
||||||
const char *xpath, struct mgmt_be_client_subscr_info *subscr_info)
|
|
||||||
{
|
{
|
||||||
struct mgmt_be_xpath_map *map;
|
struct mgmt_be_xpath_map *maps, *map;
|
||||||
enum mgmt_be_client_id id;
|
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);
|
MGMTD_BE_ADAPTER_DBG("XPATH: '%s'", xpath);
|
||||||
darr_foreach_p (mgmt_xpath_map, map) {
|
darr_foreach_p (maps, map)
|
||||||
if (!mgmt_be_eval_regexp_match(map->xpath_regexp, xpath))
|
if (mgmt_be_xpath_prefix(map->xpath_prefix, xpath))
|
||||||
continue;
|
clients |= map->clients;
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
|
||||||
subscr_info->xpath_subscr[id] |= map->subscr_info[id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL)) {
|
if (DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL)) {
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
FOREACH_BE_CLIENT_BITS (id, clients)
|
||||||
if (!subscr_info->xpath_subscr[id])
|
MGMTD_BE_ADAPTER_DBG("Cient: %s: subscribed",
|
||||||
continue;
|
mgmt_be_client_id2name(id));
|
||||||
MGMTD_BE_ADAPTER_DBG("Cient: %s: subscribed: 0x%x",
|
|
||||||
mgmt_be_client_id2name(id),
|
|
||||||
subscr_info->xpath_subscr[id]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the subscription info bits for a given `xpath` for a given
|
* Return true if `client_id` is interested in `xpath` for `config`
|
||||||
* `client_id`.
|
* or oper (!`config`).
|
||||||
*
|
*
|
||||||
* Args:
|
* Args:
|
||||||
* xpath - the xpath to check for subscription information.
|
* xpath - the xpath to check for interest.
|
||||||
* client_id - the BE client being checked for.
|
* client_id - the BE client being checked for.
|
||||||
* subscr_mask - The subscr bits the caller is interested in seeing
|
* bool - check for config (vs oper) subscription.
|
||||||
* if set.
|
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* The subscription info bits.
|
* Interested or not.
|
||||||
*/
|
*/
|
||||||
static uint mgmt_be_get_subscr_for_xpath_and_client(
|
static bool be_is_client_interested(const char *xpath,
|
||||||
const char *xpath, enum mgmt_be_client_id client_id, uint subscr_mask)
|
enum mgmt_be_client_id id, bool config)
|
||||||
{
|
{
|
||||||
struct mgmt_be_client_xpath_map *map;
|
const char *const *xpaths;
|
||||||
uint subscr = 0;
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
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'",
|
MGMTD_BE_ADAPTER_DBG("Checking client: %s for xpath: '%s'",
|
||||||
mgmt_be_client_id2name(client_id), xpath);
|
mgmt_be_client_id2name(id), xpath);
|
||||||
|
|
||||||
map = &mgmt_client_xpaths[client_id];
|
xpaths = config ? be_client_xpaths[id] : be_client_oper_xpaths[id];
|
||||||
for (i = 0; i < map->nxpaths; i++) {
|
if (xpaths) {
|
||||||
if (!mgmt_be_eval_regexp_match(map->xpaths[i].xpath, xpath))
|
for (; *xpaths; xpaths++) {
|
||||||
continue;
|
if (mgmt_be_xpath_prefix(*xpaths, xpath)) {
|
||||||
MGMTD_BE_ADAPTER_DBG("xpath: %s: matched: %s",
|
MGMTD_BE_ADAPTER_DBG("xpath: %s: matched: %s",
|
||||||
map->xpaths[i].xpath, xpath);
|
*xpaths, xpath);
|
||||||
subscr |= map->xpaths[i].subscribed;
|
return true;
|
||||||
if ((subscr & subscr_mask) == subscr_mask)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
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)
|
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));
|
(int)mgmt_be_adapters_count(&mgmt_be_adapters));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void be_show_xpath_register(struct vty *vty,
|
||||||
|
struct mgmt_be_xpath_map *map)
|
||||||
|
{
|
||||||
|
enum mgmt_be_client_id id;
|
||||||
|
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)
|
void mgmt_be_xpath_register_write(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");
|
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);
|
||||||
|
|
||||||
darr_foreach_p (mgmt_xpath_map, map) {
|
vty_out(vty, "\nMGMTD Backend OPER XPath Registry: Count: %u\n",
|
||||||
vty_out(vty, " - XPATH: '%s'\n", map->xpath_regexp);
|
darr_len(be_oper_xpath_map));
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
darr_foreach_p (be_oper_xpath_map, map)
|
||||||
info = map->subscr_info[id];
|
be_show_xpath_register(vty, map);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vty_out(vty, "Total XPath Registries: %u\n", darr_len(mgmt_xpath_map));
|
void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath)
|
||||||
}
|
|
||||||
|
|
||||||
void mgmt_be_xpath_subscr_info_write(struct vty *vty, const char *xpath)
|
|
||||||
{
|
{
|
||||||
struct mgmt_be_client_subscr_info subscr;
|
|
||||||
enum mgmt_be_client_id id;
|
enum mgmt_be_client_id id;
|
||||||
struct mgmt_be_client_adapter *adapter;
|
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);
|
vty_out(vty, "XPath: '%s'\n", xpath);
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
FOREACH_BE_CLIENT_BITS (id, combined) {
|
||||||
info = subscr.xpath_subscr[id];
|
vty_out(vty, " -- Client: '%s'\tconfig:%d oper:%d\n",
|
||||||
if (!info)
|
mgmt_be_client_id2name(id), IS_IDBIT_SET(cclients, id),
|
||||||
continue;
|
IS_IDBIT_SET(oclients, id));
|
||||||
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);
|
adapter = mgmt_be_get_adapter_by_id(id);
|
||||||
if (adapter)
|
if (adapter)
|
||||||
vty_out(vty, " -- Adapter: %p\n", adapter);
|
vty_out(vty, " -- Adapter: %p\n", adapter);
|
||||||
|
|
|
@ -20,6 +20,22 @@
|
||||||
#define MGMTD_FIND_ADAPTER_BY_INDEX(adapter_index) \
|
#define MGMTD_FIND_ADAPTER_BY_INDEX(adapter_index) \
|
||||||
mgmt_adaptr_ref[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 {
|
enum mgmt_be_req_type {
|
||||||
MGMTD_BE_REQ_NONE = 0,
|
MGMTD_BE_REQ_NONE = 0,
|
||||||
MGMTD_BE_REQ_CFG_VALIDATE,
|
MGMTD_BE_REQ_CFG_VALIDATE,
|
||||||
|
@ -49,8 +65,6 @@ struct mgmt_be_client_adapter {
|
||||||
enum mgmt_be_client_id id;
|
enum mgmt_be_client_id id;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
char name[MGMTD_CLIENT_NAME_MAX_LEN];
|
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;
|
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_OPER_OWN 0x4
|
||||||
#define MGMT_SUBSCR_ALL 0x7
|
#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. */
|
/* Initialise backend adapter module. */
|
||||||
extern void mgmt_be_adapter_init(struct event_loop *tm);
|
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:
|
* Args:
|
||||||
* xpath - the xpath to check for subscription information.
|
* xpath - the xpath to check for subscription information.
|
||||||
* subscr_info - An array of uint indexed by client id
|
* config - true for config interest false for oper interest.
|
||||||
* each eleemnt holds the subscription info
|
|
||||||
* for that client.
|
|
||||||
*/
|
*/
|
||||||
extern void mgmt_be_get_subscr_info_for_xpath(
|
extern uint64_t mgmt_be_interested_clients(const char *xpath, bool config);
|
||||||
const char *xpath, struct mgmt_be_client_subscr_info *subscr_info);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dump backend client information for a given xpath to vty.
|
* Dump backend client information for a given xpath to vty.
|
||||||
*/
|
*/
|
||||||
extern void mgmt_be_xpath_subscr_info_write(struct vty *vty,
|
extern void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath);
|
||||||
const char *xpath);
|
|
||||||
|
|
||||||
#endif /* _FRR_MGMTD_BE_ADAPTER_H_ */
|
#endif /* _FRR_MGMTD_BE_ADAPTER_H_ */
|
||||||
|
|
|
@ -80,7 +80,6 @@ struct mgmt_txn_be_cfg_batch {
|
||||||
uint64_t batch_id;
|
uint64_t batch_id;
|
||||||
enum mgmt_be_client_id be_id;
|
enum mgmt_be_client_id be_id;
|
||||||
struct mgmt_be_client_adapter *be_adapter;
|
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_data[MGMTD_MAX_CFG_CHANGES_IN_BATCH];
|
||||||
Mgmtd__YangCfgDataReq *cfg_datap[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];
|
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
|
* Details on all the Backend Clients associated with
|
||||||
* this commit.
|
* this commit.
|
||||||
*/
|
*/
|
||||||
struct mgmt_be_client_subscr_info subscr_info;
|
uint64_t clients;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of backend batches for this commit to be validated
|
* 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
|
* send a txn delete message
|
||||||
*/
|
*/
|
||||||
adapter = mgmt_be_get_adapter_by_id(id);
|
adapter = mgmt_be_get_adapter_by_id(id);
|
||||||
if (adapter && cleanup &&
|
if (adapter && cleanup && IS_IDBIT_SET(ccreq->clients, id))
|
||||||
ccreq->subscr_info.xpath_subscr[id])
|
|
||||||
mgmt_txn_send_be_txn_delete((*txn_req)->txn,
|
mgmt_txn_send_be_txn_delete((*txn_req)->txn,
|
||||||
adapter);
|
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.
|
* Check if all clients has moved to next phase or not.
|
||||||
*/
|
*/
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
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])) {
|
mgmt_txn_batches_count(&cmtcfg_req->curr_batches[id])) {
|
||||||
/*
|
/*
|
||||||
* There's atleast once client who hasn't moved to
|
* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the real workhorse
|
||||||
|
*/
|
||||||
static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
|
static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
|
||||||
struct nb_config_cbs *changes)
|
struct nb_config_cbs *changes)
|
||||||
{
|
{
|
||||||
struct nb_config_cb *cb, *nxt;
|
struct nb_config_cb *cb, *nxt;
|
||||||
struct nb_config_change *chg;
|
struct nb_config_change *chg;
|
||||||
struct mgmt_txn_be_cfg_batch *batch;
|
struct mgmt_txn_be_cfg_batch *batch;
|
||||||
struct mgmt_be_client_subscr_info subscr_info;
|
|
||||||
char *xpath = NULL, *value = NULL;
|
char *xpath = NULL, *value = NULL;
|
||||||
char err_buf[1024];
|
char err_buf[1024];
|
||||||
enum mgmt_be_client_id id;
|
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;
|
bool found_validator;
|
||||||
int num_chgs = 0;
|
int num_chgs = 0;
|
||||||
int xpath_len, value_len;
|
int xpath_len, value_len;
|
||||||
|
uint64_t clients;
|
||||||
|
|
||||||
cmtcfg_req = &txn_req->req.commit_cfg;
|
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,
|
MGMTD_TXN_DBG("XPATH: %s, Value: '%s'", xpath,
|
||||||
value ? value : "NIL");
|
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;
|
xpath_len = strlen(xpath) + 1;
|
||||||
value_len = strlen(value) + 1;
|
value_len = strlen(value) + 1;
|
||||||
found_validator = false;
|
FOREACH_BE_CLIENT_BITS (id, clients) {
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
|
||||||
if (!(subscr_info.xpath_subscr[id] &
|
|
||||||
(MGMT_SUBSCR_VALIDATE_CFG |
|
|
||||||
MGMT_SUBSCR_NOTIFY_CFG)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
adapter = mgmt_be_get_adapter_by_id(id);
|
adapter = mgmt_be_get_adapter_by_id(id);
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
continue;
|
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);
|
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(
|
mgmt_yang_cfg_data_req_init(
|
||||||
&batch->cfg_data[batch->num_cfg_data]);
|
&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;
|
||||||
value = NULL;
|
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",
|
MGMTD_TXN_DBG(" -- %s, batch-id: %" PRIu64 " item:%d",
|
||||||
adapter->name, batch->batch_id,
|
adapter->name, batch->batch_id,
|
||||||
(int)batch->num_cfg_data);
|
(int)batch->num_cfg_data);
|
||||||
|
@ -1318,7 +1309,7 @@ static int mgmt_txn_send_be_txn_create(struct mgmt_txn_ctx *txn)
|
||||||
|
|
||||||
cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg;
|
cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg;
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
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);
|
adapter = mgmt_be_get_adapter_by_id(id);
|
||||||
if (mgmt_be_send_txn_req(adapter, txn->txn_id, true)) {
|
if (mgmt_be_send_txn_req(adapter, txn->txn_id, true)) {
|
||||||
(void)mgmt_txn_send_commit_cfg_reply(
|
(void)mgmt_txn_send_commit_cfg_reply(
|
||||||
|
@ -1364,7 +1355,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);
|
assert(txn->type == MGMTD_TXN_TYPE_CONFIG && txn->commit_cfg_req);
|
||||||
|
|
||||||
cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg;
|
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;
|
indx = 0;
|
||||||
num_batches =
|
num_batches =
|
||||||
|
@ -1417,7 +1408,7 @@ static int mgmt_txn_send_be_txn_delete(struct mgmt_txn_ctx *txn,
|
||||||
assert(txn->type == MGMTD_TXN_TYPE_CONFIG);
|
assert(txn->type == MGMTD_TXN_TYPE_CONFIG);
|
||||||
assert(!mgmt_txn_batches_count(&cmtcfg_req->curr_batches[adapter->id]));
|
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 0;
|
||||||
|
|
||||||
return mgmt_be_send_txn_req(adapter, txn->txn_id, false);
|
return mgmt_be_send_txn_req(adapter, txn->txn_id, false);
|
||||||
|
@ -1476,8 +1467,7 @@ static int mgmt_txn_send_be_cfg_apply(struct mgmt_txn_ctx *txn)
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
FOREACH_MGMTD_BE_CLIENT_ID (id) {
|
||||||
if (cmtcfg_req->subscr_info.xpath_subscr[id] &
|
if (IS_IDBIT_SET(cmtcfg_req->clients, id)) {
|
||||||
MGMT_SUBSCR_NOTIFY_CFG) {
|
|
||||||
adapter = mgmt_be_get_adapter_by_id(id);
|
adapter = mgmt_be_get_adapter_by_id(id);
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2365,9 +2355,8 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter,
|
||||||
? &txn->commit_cfg_req->req
|
? &txn->commit_cfg_req->req
|
||||||
.commit_cfg
|
.commit_cfg
|
||||||
: NULL;
|
: NULL;
|
||||||
if (cmtcfg_req &&
|
if (cmtcfg_req && IS_IDBIT_SET(cmtcfg_req->clients,
|
||||||
cmtcfg_req->subscr_info
|
adapter->id)) {
|
||||||
.xpath_subscr[adapter->id]) {
|
|
||||||
mgmt_txn_send_commit_cfg_reply(
|
mgmt_txn_send_commit_cfg_reply(
|
||||||
txn, MGMTD_INTERNAL_ERROR,
|
txn, MGMTD_INTERNAL_ERROR,
|
||||||
"Backend daemon disconnected while processing commit!");
|
"Backend daemon disconnected while processing commit!");
|
||||||
|
|
|
@ -273,7 +273,7 @@ DEFPY(show_mgmt_map_xpath,
|
||||||
"Get YANG Backend Subscription\n"
|
"Get YANG Backend Subscription\n"
|
||||||
"XPath expression specifying the YANG data path\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;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -563,6 +563,7 @@ our $Iterators = qr{
|
||||||
SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE|
|
SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE|
|
||||||
SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE|
|
SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE|
|
||||||
AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI|
|
AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI|
|
||||||
|
FOREACH_BE_CLIENT_BITS|FOREACH_MGMTD_BE_CLIENT_ID|
|
||||||
LSDB_LOOP
|
LSDB_LOOP
|
||||||
}x;
|
}x;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue