summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/if.c118
-rw-r--r--lib/mgmt_be_client.c92
-rw-r--r--lib/mgmt_be_client.h16
-rw-r--r--lib/mgmt_msg_native.h13
-rw-r--r--lib/northbound.c6
-rw-r--r--lib/northbound.h53
-rw-r--r--lib/northbound_oper.c8
-rw-r--r--lib/route_types.txt2
8 files changed, 208 insertions, 100 deletions
diff --git a/lib/if.c b/lib/if.c
index 378ca16e49..586fc1d5cd 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1649,90 +1649,90 @@ static int lib_interface_description_destroy(struct nb_cb_destroy_args *args)
return NB_OK;
}
-/*
- * XPath: /frr-interface:lib/interface/vrf
- */
-static struct yang_data *
-lib_interface_vrf_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error __return_ok(const struct nb_node *nb_node, const void *list_entry,
+ struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
-
- return yang_data_new_string(args->xpath, ifp->vrf->name);
+ return NB_OK;
}
/*
- * XPath: /frr-interface:lib/interface/state/if-index
+ * XPath: /frr-interface:lib/interface/vrf
*/
-static struct yang_data *
-lib_interface_state_if_index_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_vrf_get(const struct nb_node *nb_node, const void *list_entry,
+ struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
- return yang_data_new_int32(args->xpath, ifp->ifindex);
+ if (lyd_new_term(parent, snode->module, snode->name, ifp->vrf->name, LYD_NEW_PATH_UPDATE,
+ NULL))
+ return NB_ERR_RESOURCE;
+ return NB_OK;
}
/*
- * XPath: /frr-interface:lib/interface/state/mtu
+ * XPath: /frr-interface:lib/interface/state/if-index
*/
-static struct yang_data *
-lib_interface_state_mtu_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_if_index_get(const struct nb_node *nb_node,
+ const void *list_entry,
+ struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ int32_t value = ifp->ifindex;
- return yang_data_new_uint32(args->xpath, ifp->mtu);
+ 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-interface:lib/interface/state/mtu6
+ * XPath: /frr-interface:lib/interface/state/mtu[6]
*/
-static struct yang_data *
-lib_interface_state_mtu6_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_mtu_get(const struct nb_node *nb_node,
+ const void *list_entry, struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ uint32_t value = ifp->mtu;
- return yang_data_new_uint32(args->xpath, ifp->mtu6);
+ 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-interface:lib/interface/state/speed
*/
-static struct yang_data *
-lib_interface_state_speed_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_speed_get(const struct nb_node *nb_node,
+ const void *list_entry, struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ uint32_t value = ifp->speed;
- return yang_data_new_uint32(args->xpath, ifp->speed);
+ 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-interface:lib/interface/state/metric
*/
-static struct yang_data *
-lib_interface_state_metric_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_metric_get(const struct nb_node *nb_node,
+ const void *list_entry, struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
-
- return yang_data_new_uint32(args->xpath, ifp->metric);
-}
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ uint32_t value = ifp->metric;
-/*
- * XPath: /frr-interface:lib/interface/state/flags
- */
-static struct yang_data *
-lib_interface_state_flags_get_elem(struct nb_cb_get_elem_args *args)
-{
- /* TODO: implement me. */
- return NULL;
-}
-
-/*
- * XPath: /frr-interface:lib/interface/state/type
- */
-static struct yang_data *
-lib_interface_state_type_get_elem(struct nb_cb_get_elem_args *args)
-{
- /* TODO: implement me. */
- return NULL;
+ 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;
}
/*
@@ -1779,49 +1779,49 @@ const struct frr_yang_module_info frr_interface_info = {
{
.xpath = "/frr-interface:lib/interface/vrf",
.cbs = {
- .get_elem = lib_interface_vrf_get_elem,
+ .get = lib_interface_vrf_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/if-index",
.cbs = {
- .get_elem = lib_interface_state_if_index_get_elem,
+ .get = lib_interface_state_if_index_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/mtu",
.cbs = {
- .get_elem = lib_interface_state_mtu_get_elem,
+ .get = lib_interface_state_mtu_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/mtu6",
.cbs = {
- .get_elem = lib_interface_state_mtu6_get_elem,
+ .get = lib_interface_state_mtu_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/speed",
.cbs = {
- .get_elem = lib_interface_state_speed_get_elem,
+ .get = lib_interface_state_speed_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/metric",
.cbs = {
- .get_elem = lib_interface_state_metric_get_elem,
+ .get = lib_interface_state_metric_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/flags",
.cbs = {
- .get_elem = lib_interface_state_flags_get_elem,
+ .get = __return_ok,
}
},
{
.xpath = "/frr-interface:lib/interface/state/type",
.cbs = {
- .get_elem = lib_interface_state_type_get_elem,
+ .get = __return_ok,
}
},
{
diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c
index f03006ad0e..05949fd62d 100644
--- a/lib/mgmt_be_client.c
+++ b/lib/mgmt_be_client.c
@@ -312,11 +312,11 @@ static int be_client_send_error(struct mgmt_be_client *client, uint64_t txn_id,
return ret;
}
-static int mgmt_be_send_notification(void *__be_client, const char *xpath,
- const struct lyd_node *tree)
+static int __send_notification(struct mgmt_be_client *client, const char *xpath,
+ const struct lyd_node *tree, uint8_t op)
{
- struct mgmt_be_client *client = __be_client;
struct mgmt_msg_notify_data *msg = NULL;
+ // LYD_FORMAT format = LYD_LYB;
LYD_FORMAT format = LYD_JSON;
uint8_t **darrp;
LY_ERR err;
@@ -324,37 +324,91 @@ static int mgmt_be_send_notification(void *__be_client, const char *xpath,
assert(tree);
- debug_be_client("%s: sending YANG notification: %s", __func__,
- tree->schema->name);
+ debug_be_client("%s: sending %sYANG %snotification: %s", __func__,
+ op == NOTIFY_OP_DS_DELETE ? "delete "
+ : op == NOTIFY_OP_DS_REPLACE ? "replace "
+ : op == NOTIFY_OP_DS_PATCH ? "patch "
+ : "",
+ op == NOTIFY_OP_NOTIFICATION ? "" : "DS ", xpath ?: tree->schema->name);
/*
* Allocate a message and append the data to it using `format`
*/
- msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_notify_data, 0,
- MTYPE_MSG_NATIVE_NOTIFY);
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_notify_data, 0, MTYPE_MSG_NATIVE_NOTIFY);
msg->code = MGMT_MSG_CODE_NOTIFY;
msg->result_type = format;
+ msg->op = op;
mgmt_msg_native_xpath_encode(msg, xpath);
- darrp = mgmt_msg_native_get_darrp(msg);
- err = yang_print_tree_append(darrp, tree, format,
- (LYD_PRINT_SHRINK | LYD_PRINT_WD_EXPLICIT |
- LYD_PRINT_WITHSIBLINGS));
- if (err) {
- flog_err(EC_LIB_LIBYANG,
- "%s: error creating notification data: %s", __func__,
- ly_strerrcode(err));
- ret = 1;
- goto done;
+ if (tree) {
+ darrp = mgmt_msg_native_get_darrp(msg);
+ err = yang_print_tree_append(darrp, tree, format,
+ (LYD_PRINT_SHRINK | LYD_PRINT_WD_EXPLICIT |
+ LYD_PRINT_WITHSIBLINGS));
+ if (err) {
+ flog_err(EC_LIB_LIBYANG, "%s: error creating notification data: %s",
+ __func__, ly_strerrcode(err));
+ ret = 1;
+ goto done;
+ }
}
- (void)be_client_send_native_msg(client, msg,
- mgmt_msg_native_get_msg_len(msg), false);
+ ret = be_client_send_native_msg(client, msg, mgmt_msg_native_get_msg_len(msg), false);
done:
mgmt_msg_native_free_msg(msg);
return ret;
}
+/**
+ * mgmt_be_send_ds_delete_notification() - Send DS notification to mgmtd
+ */
+int mgmt_be_send_ds_delete_notification(const char *path)
+{
+ if (!__be_client) {
+ debug_be_client("%s: No mgmtd connection for DS delete notification: %s", __func__,
+ path);
+ return 1;
+ }
+ return __send_notification(__be_client, path, NULL, NOTIFY_OP_DS_DELETE);
+}
+
+/**
+ * mgmt_be_send_ds_patch_notification() - Send a YANG patch DS notification to mgmtd
+ */
+int mgmt_be_send_ds_patch_notification(const char *path, const struct lyd_node *patch)
+{
+ if (!__be_client) {
+ debug_be_client("%s: No mgmtd connection for DS delete notification: %s", __func__,
+ path);
+ return 1;
+ }
+ return __send_notification(__be_client, path, patch, NOTIFY_OP_DS_PATCH);
+}
+
+/**
+ * mgmt_be_send_ds_replace_notification() - Send a replace DS notification to mgmtd
+ */
+int mgmt_be_send_ds_replace_notification(const char *path, const struct lyd_node *tree)
+{
+ if (!__be_client) {
+ debug_be_client("%s: No mgmtd connection for DS delete notification: %s", __func__,
+ path);
+ return 1;
+ }
+ return __send_notification(__be_client, path, tree, NOTIFY_OP_DS_REPLACE);
+}
+
+/**
+ * mgmt_be_send_notification() - Send notification to mgmtd
+ *
+ * This function is attached to the northbound notification hook.
+ */
+static int mgmt_be_send_notification(void *__client, const char *path, const struct lyd_node *tree)
+{
+ __send_notification(__client, path, tree, NOTIFY_OP_NOTIFICATION);
+ return 0;
+}
+
static int mgmt_be_send_txn_reply(struct mgmt_be_client *client_ctx,
uint64_t txn_id, bool create)
{
diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h
index 6ed8c2a39f..a3e3896d52 100644
--- a/lib/mgmt_be_client.h
+++ b/lib/mgmt_be_client.h
@@ -112,6 +112,22 @@ extern struct mgmt_be_client *
mgmt_be_client_create(const char *name, struct mgmt_be_client_cbs *cbs,
uintptr_t user_data, struct event_loop *event_loop);
+
+/**
+ * mgmt_be_send_ds_delete_notification() - Send a datastore delete notification.
+ */
+extern int mgmt_be_send_ds_delete_notification(const char *path);
+
+/**
+ * mgmt_be_send_ds_patch_notification() - Send a datastore YANG patch notification.
+ */
+extern int mgmt_be_send_ds_patch_notification(const char *path, const struct lyd_node *tree);
+
+/**
+ * mgmt_be_send_ds_replace_notification() - Send a datastore replace notification.
+ */
+extern int mgmt_be_send_ds_replace_notification(const char *path, const struct lyd_node *tree);
+
/*
* Initialize library vty (adds debug support).
*
diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h
index 587a002801..4076977a22 100644
--- a/lib/mgmt_msg_native.h
+++ b/lib/mgmt_msg_native.h
@@ -323,22 +323,29 @@ _Static_assert(sizeof(struct mgmt_msg_get_data) ==
offsetof(struct mgmt_msg_get_data, xpath),
"Size mismatch");
+
+#define NOTIFY_OP_NOTIFICATION 0
+#define NOTIFY_OP_DS_REPLACE 1
+#define NOTIFY_OP_DS_DELETE 2
+#define NOTIFY_OP_DS_PATCH 3
+
/**
* struct mgmt_msg_notify_data - Message carrying notification data.
*
* @result_type: ``LYD_FORMAT`` for format of the @result value.
* @data: The xpath string of the notification followed by the tree data in
* @result_type format.
+ * @op: notify operation type.
*/
struct mgmt_msg_notify_data {
struct mgmt_msg_header;
uint8_t result_type;
- uint8_t resv2[7];
+ uint8_t op;
+ uint8_t resv2[6];
alignas(8) char data[];
};
-_Static_assert(sizeof(struct mgmt_msg_notify_data) ==
- offsetof(struct mgmt_msg_notify_data, data),
+_Static_assert(sizeof(struct mgmt_msg_notify_data) == offsetof(struct mgmt_msg_notify_data, data),
"Size mismatch");
#define EDIT_FLAG_IMPLICIT_LOCK 0x01
diff --git a/lib/northbound.c b/lib/northbound.c
index a385cc9ece..c67ed924a9 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -273,9 +273,11 @@ static unsigned int nb_node_validate_cbs(const struct nb_node *nb_node)
error += nb_node_validate_cb(nb_node, NB_CB_APPLY_FINISH,
!!nb_node->cbs.apply_finish, true);
error += nb_node_validate_cb(nb_node, NB_CB_GET_ELEM,
- !!nb_node->cbs.get_elem, false);
+ (nb_node->cbs.get_elem || nb_node->cbs.get), false);
error += nb_node_validate_cb(nb_node, NB_CB_GET_NEXT,
- !!nb_node->cbs.get_next, false);
+ (nb_node->cbs.get_next ||
+ (nb_node->snode->nodetype == LYS_LEAFLIST && nb_node->cbs.get)),
+ false);
error += nb_node_validate_cb(nb_node, NB_CB_GET_KEYS,
!!nb_node->cbs.get_keys, false);
error += nb_node_validate_cb(nb_node, NB_CB_LOOKUP_ENTRY,
diff --git a/lib/northbound.h b/lib/northbound.h
index 97a1d31e57..42f763c3ef 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -21,6 +21,7 @@ extern "C" {
/* Forward declaration(s). */
struct vty;
struct debug;
+struct nb_node;
struct nb_yang_xpath_tag {
uint32_t ns;
@@ -102,6 +103,20 @@ enum nb_cb_operation {
NB_CB_NOTIFY,
};
+/* Northbound error codes. */
+enum nb_error {
+ NB_OK = 0,
+ NB_ERR,
+ NB_ERR_NO_CHANGES,
+ NB_ERR_NOT_FOUND,
+ NB_ERR_EXISTS,
+ NB_ERR_LOCKED,
+ NB_ERR_VALIDATION,
+ NB_ERR_RESOURCE,
+ NB_ERR_INCONSISTENCY,
+ NB_YIELD,
+};
+
union nb_resource {
int fd;
void *ptr;
@@ -426,6 +441,25 @@ struct nb_callbacks {
void (*apply_finish)(struct nb_cb_apply_finish_args *args);
/*
+ * Operational data callback (new direct tree add method).
+ *
+ * The callback function should create a new lyd_node (leaf) or
+ * lyd_node's (leaf list) for the value and attach to parent.
+ *
+ * nb_node
+ * The node representing the leaf or leaf list
+ * list_entry
+ * List entry from get_next (or NULL).
+ * parent
+ * The parent lyd_node to attach the leaf data to.
+ *
+ * Returns:
+ * Returns an nb_error if the data could not be added to the tree.
+ */
+ enum nb_error (*get)(const struct nb_node *nb_node, const void *list_entry,
+ struct lyd_node *parent);
+
+ /*
* Operational data callback.
*
* The callback function should return the value of a specific leaf,
@@ -672,20 +706,6 @@ struct frr_yang_module_info {
#endif
};
-/* Northbound error codes. */
-enum nb_error {
- NB_OK = 0,
- NB_ERR,
- NB_ERR_NO_CHANGES,
- NB_ERR_NOT_FOUND,
- NB_ERR_EXISTS,
- NB_ERR_LOCKED,
- NB_ERR_VALIDATION,
- NB_ERR_RESOURCE,
- NB_ERR_INCONSISTENCY,
- NB_YIELD,
-};
-
/* Default priority. */
#define NB_DFLT_PRIORITY (UINT32_MAX / 2)
@@ -814,8 +834,9 @@ extern struct debug nb_dbg_libyang;
extern struct nb_config *running_config;
/* Wrappers for the northbound callbacks. */
-extern struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
- const char *xpath,
+extern struct yang_data *nb_callback_has_new_get_elem(const struct nb_node *nb_node);
+
+extern struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node, const char *xpath,
const void *list_entry);
extern const void *nb_callback_get_next(const struct nb_node *nb_node,
const void *parent_list_entry,
diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c
index 2c72d8ecef..0364870486 100644
--- a/lib/northbound_oper.c
+++ b/lib/northbound_oper.c
@@ -654,6 +654,10 @@ static enum nb_error nb_op_iter_leaf(struct nb_op_yield_state *ys,
if (lysc_is_key(snode))
return NB_OK;
+ /* Check for new simple get */
+ if (nb_node->cbs.get)
+ return nb_node->cbs.get(nb_node, ni->list_entry, ni->inner);
+
data = nb_callback_get_elem(nb_node, xpath, ni->list_entry);
if (data == NULL)
return NB_OK;
@@ -687,6 +691,10 @@ static enum nb_error nb_op_iter_leaflist(struct nb_op_yield_state *ys,
if (CHECK_FLAG(snode->flags, LYS_CONFIG_W))
return NB_OK;
+ /* Check for new simple get */
+ if (nb_node->cbs.get)
+ return nb_node->cbs.get(nb_node, ni->list_entry, ni->inner);
+
do {
struct yang_data *data;
diff --git a/lib/route_types.txt b/lib/route_types.txt
index 93cbc36e97..b5f8b6fdf3 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -88,7 +88,7 @@ ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP", vr
ZEBRA_ROUTE_NHG, zebra, none, '-', 0, 0, 0, "Nexthop Group", none
ZEBRA_ROUTE_SRTE, srte, none, '-', 0, 0, 0, "SR-TE", none
ZEBRA_ROUTE_TABLE_DIRECT, table-direct, zebra, 't', 1, 1, 1, "Table-Direct", zebra
-ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-", none
+ZEBRA_ROUTE_ALL, any, none, '-', 0, 0, 0, "-", none
## help strings