diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/if.c | 118 | ||||
| -rw-r--r-- | lib/mgmt_be_client.c | 92 | ||||
| -rw-r--r-- | lib/mgmt_be_client.h | 16 | ||||
| -rw-r--r-- | lib/mgmt_msg_native.h | 13 | ||||
| -rw-r--r-- | lib/northbound.c | 6 | ||||
| -rw-r--r-- | lib/northbound.h | 53 | ||||
| -rw-r--r-- | lib/northbound_oper.c | 8 | ||||
| -rw-r--r-- | lib/route_types.txt | 2 |
8 files changed, 208 insertions, 100 deletions
@@ -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 |
