Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mgmtd backend yang model (depends on #17796) #17799

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 197 additions & 14 deletions lib/mgmt_be_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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. */
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions lib/mgmt_be_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
***************************************************************/
Expand Down
10 changes: 10 additions & 0 deletions lib/northbound.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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.
*
Expand Down
81 changes: 81 additions & 0 deletions lib/northbound_oper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lib/subdir.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
Loading
Loading