Skip to content

Commit 85d2c83

Browse files
committed
schema mount UPDATE for shared schema use mounted yang-lib data
As is in the spec, use yang-library data mounted directly under the specific mount point, for shared schema. Inline schema still support only yang-library data of the parent context.
1 parent 04b6ed3 commit 85d2c83

File tree

5 files changed

+250
-408
lines changed

5 files changed

+250
-408
lines changed

src/plugins_exts/schema_mount.c

Lines changed: 160 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,13 @@ schema_mount_get_smount(const struct lysc_ext_instance *ext, const struct lyd_no
296296
* @brief Create schema (context) based on retrieved extension data.
297297
*
298298
* @param[in] ext Compiled extension instance.
299-
* @param[in] ext_data Extension data retrieved by the callback.
299+
* @param[in] ext_yl_data Extension data 'yang-library' subtree.
300300
* @param[in] config Whether the whole schema should keep its config or be set to false.
301301
* @param[out] ext_ctx Schema to use for parsing the data.
302302
* @return LY_ERR value.
303303
*/
304304
static LY_ERR
305-
schema_mount_create_ctx(const struct lysc_ext_instance *ext, const struct lyd_node *ext_data, ly_bool config,
305+
schema_mount_create_ctx(const struct lysc_ext_instance *ext, const struct lyd_node *ext_yl_data, ly_bool config,
306306
struct ly_ctx **ext_ctx)
307307
{
308308
LY_ERR rc = LY_SUCCESS;
@@ -325,7 +325,7 @@ schema_mount_create_ctx(const struct lysc_ext_instance *ext, const struct lyd_no
325325
}
326326

327327
/* create the context based on the data */
328-
if ((rc = ly_ctx_new_yldata(sdirs, ext_data, ly_ctx_get_options(ext->module->ctx), ext_ctx))) {
328+
if ((rc = ly_ctx_new_yldata(sdirs, ext_yl_data, ly_ctx_get_options(ext->module->ctx), ext_ctx))) {
329329
lyplg_ext_compile_log(NULL, ext, LY_LLERR, rc, "Failed to create context for the schema-mount data (%s).",
330330
ly_last_logmsg());
331331
goto cleanup;
@@ -357,35 +357,102 @@ schema_mount_create_ctx(const struct lysc_ext_instance *ext, const struct lyd_no
357357
return rc;
358358
}
359359

360+
/**
361+
* @brief Get ietf-yang-library from ext data specific for this extension.
362+
*
363+
* @param[in] ext Compiled extension instance.
364+
* @param[in] ext_data Extension data retrieved by the callback with the yang-library data.
365+
* @param[in] parent Optional data parent to use.
366+
* @param[in] shared Whether the 'mount-point' is shared or inline.
367+
* @param[out] ext_yl_data Data tree 'yang-library' of @p ext.
368+
* @return LY_ERR value.
369+
*/
370+
static LY_ERR
371+
schema_mount_get_yanglib(const struct lysc_ext_instance *ext, const struct lyd_node *ext_data,
372+
const struct lyd_node *parent, ly_bool shared, const struct lyd_node **ext_yl_data)
373+
{
374+
LY_ERR rc = LY_SUCCESS;
375+
char *parent_path = NULL;
376+
struct lyd_node *iter;
377+
struct ly_set *set = NULL;
378+
uint32_t i;
379+
380+
*ext_yl_data = NULL;
381+
382+
if (!shared) {
383+
/* inline context is built from the parent context 'yang-library' data */
384+
lyd_find_path(ext_data, "/ietf-yang-library:yang-library", 0, (struct lyd_node **)ext_yl_data);
385+
} else {
386+
if (parent) {
387+
/* path of the data parent in data */
388+
parent_path = lyd_path(parent, LYD_PATH_STD, NULL, 0);
389+
} else {
390+
/* path of the ext schema node parent */
391+
parent_path = lysc_path(ext->parent, LYSC_PATH_DATA, NULL, 0);
392+
}
393+
394+
/* get the parent(s) of 'yang-library' */
395+
if ((rc = lyd_find_xpath(ext_data, parent_path, &set))) {
396+
goto cleanup;
397+
}
398+
399+
/* find manually, may be from a different context */
400+
for (i = 0; i < set->count; ++i) {
401+
LY_LIST_FOR(lyd_child(set->dnodes[i]), iter) {
402+
if (!strcmp(LYD_NAME(iter), "yang-library") && !strcmp(lyd_node_module(iter)->name, "ietf-yang-library")) {
403+
/* first match should be fine */
404+
*ext_yl_data = iter;
405+
break;
406+
}
407+
}
408+
if (iter) {
409+
break;
410+
}
411+
}
412+
}
413+
414+
if (!*ext_yl_data) {
415+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EVALID, "Could not find 'yang-library' data in \"%s\".",
416+
parent_path ? parent_path : "<top-level>");
417+
rc = LY_EVALID;
418+
goto cleanup;
419+
}
420+
421+
cleanup:
422+
free(parent_path);
423+
ly_set_free(set, NULL);
424+
return rc;
425+
}
426+
360427
/**
361428
* @brief Get ietf-yang-library context-id from its data.
362429
*
363430
* @param[in] ext Compiled extension instance for logging.
364-
* @param[in] ext_data Extension data retrieved by the callback with the yang-library data.
365-
* @param[out] content_id Content ID in @p ext_data.
431+
* @param[in] ext_yl_data Extension data subtree 'yang-library'.
432+
* @param[out] content_id Content ID of @p ext_yl_data.
366433
* @return LY_ERR value.
367434
*/
368435
static LY_ERR
369-
schema_mount_get_content_id(struct lysc_ext_instance *ext, const struct lyd_node *ext_data, const char **content_id)
436+
schema_mount_get_content_id(struct lysc_ext_instance *ext, const struct lyd_node *ext_yl_data, const char **content_id)
370437
{
371438
struct lyd_node *node = NULL;
439+
const struct lysc_node *snode;
440+
441+
assert(ext_yl_data && !strcmp(LYD_NAME(ext_yl_data), "yang-library"));
372442

373443
*content_id = NULL;
374444

375-
/* get yang-library content-id or module-set-id */
376-
if (ext_data) {
377-
lyd_find_path(ext_data, "/ietf-yang-library:yang-library/content-id", 0, &node);
378-
if (!node) {
379-
lyd_find_path(ext_data, "/ietf-yang-library:modules-state/module-set-id", 0, &node);
380-
}
381-
if (node) {
382-
*content_id = lyd_get_value(node);
383-
}
445+
/* find the content-id node */
446+
snode = lys_find_child(ext_yl_data->schema, ext_yl_data->schema->module, "content-id", 0, 0, 0);
447+
assert(snode);
448+
449+
/* get yang-library content-id */
450+
if (!lyd_find_sibling_val(lyd_child(ext_yl_data), snode, NULL, 0, &node)) {
451+
*content_id = lyd_get_value(node);
384452
}
385453

386454
if (!*content_id) {
387-
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EVALID,
388-
"Missing \"content-id\" or \"module-set-id\" in ietf-yang-library data.");
455+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EVALID, "Missing \"content-id\" in ietf-yang-library data.");
389456
return LY_EVALID;
390457
}
391458
return LY_SUCCESS;
@@ -406,6 +473,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
406473
{
407474
struct lyplg_ext_sm *sm_data = ext->compiled;
408475
LY_ERR rc = LY_SUCCESS, r;
476+
const struct lyd_node *ext_yl_data;
409477
struct ly_ctx *new_ctx = NULL;
410478
uint32_t i;
411479
const char *content_id;
@@ -417,8 +485,13 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
417485
*ext_ctx = NULL;
418486
}
419487

488+
/* get yang-library data */
489+
if ((r = schema_mount_get_yanglib(ext, ext_data, NULL, 1, &ext_yl_data))) {
490+
return r;
491+
}
492+
420493
/* get yang-library content-id or module-set-id */
421-
if ((r = schema_mount_get_content_id(ext, ext_data, &content_id))) {
494+
if ((r = schema_mount_get_content_id(ext, ext_yl_data, &content_id))) {
422495
return r;
423496
}
424497

@@ -440,7 +513,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
440513
if (i < sm_data->shared->schema_count) {
441514
/* schema exists already */
442515
if (strcmp(content_id, sm_data->shared->schemas[i].content_id)) {
443-
lyplg_ext_compile_log_path("/ietf-yang-library:yang-library/content-id", ext, LY_LLERR, LY_EVALID,
516+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EVALID,
444517
"Shared-schema yang-library content-id \"%s\" differs from \"%s\" used previously.",
445518
content_id, sm_data->shared->schemas[i].content_id);
446519
rc = LY_EVALID;
@@ -458,7 +531,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
458531
}
459532

460533
/* no schema found, create it */
461-
if ((r = schema_mount_create_ctx(ext, ext_data, config, &new_ctx))) {
534+
if ((r = schema_mount_create_ctx(ext, ext_yl_data, config, &new_ctx))) {
462535
rc = r;
463536
goto cleanup;
464537
}
@@ -711,6 +784,7 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node
711784
{
712785
struct lyplg_ext_sm *sm_data = ext->compiled;
713786
struct ly_ctx *new_ctx = NULL;
787+
const struct lyd_node *ext_yl_data;
714788
uint32_t i;
715789
void *mem;
716790
LY_ERR rc = LY_SUCCESS, r;
@@ -746,8 +820,14 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node
746820
}
747821
}
748822

823+
/* find the 'yang-library' data */
824+
if ((r = schema_mount_get_yanglib(ext, ext_data, NULL, 0, &ext_yl_data))) {
825+
rc = r;
826+
goto cleanup;
827+
}
828+
749829
/* new schema required, create context */
750-
if ((r = schema_mount_create_ctx(ext, ext_data, config, &new_ctx))) {
830+
if ((r = schema_mount_create_ctx(ext, ext_yl_data, config, &new_ctx))) {
751831
rc = r;
752832
goto cleanup;
753833
}
@@ -786,7 +866,7 @@ LY_ERR
786866
lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct lyd_node *parent, const struct ly_ctx **ext_ctx)
787867
{
788868
LY_ERR ret = LY_SUCCESS, r;
789-
struct lyd_node *iter, *ext_data = NULL;
869+
struct lyd_node *ext_data = NULL, *sm_root = NULL;
790870
ly_bool ext_data_free = 0, config, shared;
791871

792872
*ext_ctx = NULL;
@@ -797,13 +877,27 @@ lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct lyd_n
797877
goto cleanup;
798878
}
799879

800-
LY_LIST_FOR(ext_data, iter) {
801-
if (iter->flags & LYD_NEW) {
802-
/* must be validated for the parent-reference prefix data to be stored */
803-
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Provided ext data have not been validated.");
804-
ret = LY_EINVAL;
805-
goto cleanup;
806-
}
880+
if (!ext_data) {
881+
*ext_ctx = ext->module->ctx;
882+
goto cleanup;
883+
}
884+
885+
if ((r = lyd_find_path(ext_data, "/ietf-yang-schema-mount:schema-mounts", 0, &sm_root))) {
886+
ret = r;
887+
goto cleanup;
888+
}
889+
if (!sm_root) {
890+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ENOT,
891+
"Missing \"ietf-yang-schema-mount:schema-mounts\" in provided extension data.");
892+
ret = LY_ENOT;
893+
goto cleanup;
894+
}
895+
896+
/* must be validated for the parent-reference prefix data to be stored, only sm data root check is sufficient */
897+
if (sm_root->flags & LYD_NEW) {
898+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Provided ext data have not been validated.");
899+
ret = LY_EINVAL;
900+
goto cleanup;
807901
}
808902

809903
/* learn about this mount point */
@@ -857,6 +951,12 @@ schema_mount_snode(struct lysc_ext_instance *ext, const struct lyd_node *parent,
857951
return LY_ENOT;
858952
}
859953

954+
if ((ext->module->ctx == ext_ctx) && strcmp(mod->name, "ietf-yang-library")) {
955+
/* without explicit 'ietf-yang-schema-mount' and 'ietf-yang-library' data we can parse only mounted
956+
* 'ietf-yang-library' data */
957+
return LY_ENOT;
958+
}
959+
860960
/* get the top-level schema node */
861961
*snode = lys_find_child(NULL, mod, name, name_len, 0, 0);
862962
return *snode ? LY_SUCCESS : LY_ENOT;
@@ -1060,7 +1160,7 @@ schema_mount_validate(struct lysc_ext_instance *ext, struct lyd_node *sibling, c
10601160
LY_ERR ret = LY_SUCCESS;
10611161
uint32_t i;
10621162
struct lyd_node *iter, *ext_data = NULL, *ref_first = NULL, *orig_parent = lyd_parent(sibling), *op_tree;
1063-
struct lyd_node *ext_diff = NULL, *diff_parent = NULL;
1163+
struct lyd_node *ext_diff = NULL, *diff_parent = NULL, *sm_root = NULL;
10641164
ly_bool ext_data_free = 0;
10651165
struct ly_set *ref_set = NULL;
10661166

@@ -1073,14 +1173,28 @@ schema_mount_validate(struct lysc_ext_instance *ext, struct lyd_node *sibling, c
10731173
if ((ret = lyplg_ext_get_data(ext->module->ctx, ext, lyd_parent(sibling), (void **)&ext_data, &ext_data_free))) {
10741174
goto cleanup;
10751175
}
1176+
if (!ext_data) {
1177+
/* ext data must have been provided */
1178+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "No ext data provided for schema mount validation.");
1179+
ret = LY_EINVAL;
1180+
goto cleanup;
1181+
}
10761182

1077-
LY_LIST_FOR(ext_data, iter) {
1078-
if (iter->flags & LYD_NEW) {
1079-
/* must be validated for the parent-reference prefix data to be stored */
1080-
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Provided ext data have not been validated.");
1081-
ret = LY_EINVAL;
1082-
goto cleanup;
1083-
}
1183+
if ((ret = lyd_find_path(ext_data, "/ietf-yang-schema-mount:schema-mounts", 0, &sm_root))) {
1184+
goto cleanup;
1185+
}
1186+
if (!sm_root) {
1187+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ENOT,
1188+
"Missing \"ietf-yang-schema-mount:schema-mounts\" in provided extension data.");
1189+
ret = LY_ENOT;
1190+
goto cleanup;
1191+
}
1192+
1193+
/* must be validated for the parent-reference prefix data to be stored, only sm data root check is sufficient */
1194+
if (sm_root->flags & LYD_NEW) {
1195+
lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Provided ext data have not been validated.");
1196+
ret = LY_EINVAL;
1197+
goto cleanup;
10841198
}
10851199

10861200
/* duplicate the referenced parent nodes into ext context */
@@ -1214,6 +1328,7 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const
12141328
LY_ERR rc = LY_SUCCESS;
12151329
uint32_t i;
12161330
ly_ext_data_clb ext_data_clb;
1331+
const struct lyd_node *ext_yl_data;
12171332

12181333
LY_CHECK_ARG_RET(NULL, ext, ctx, LY_EINVAL);
12191334

@@ -1275,8 +1390,15 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const
12751390
goto cleanup;
12761391
}
12771392

1393+
/* find 'yang-library' data */
1394+
if ((rc = schema_mount_get_yanglib(ext, ext_data, parent, shared, &ext_yl_data))) {
1395+
goto cleanup;
1396+
}
1397+
12781398
/* create the context */
1279-
rc = schema_mount_create_ctx(ext, ext_data, config, ctx);
1399+
if ((rc = schema_mount_create_ctx(ext, ext_yl_data, config, ctx))) {
1400+
goto cleanup;
1401+
}
12801402

12811403
cleanup:
12821404
if (ext_data_free) {

0 commit comments

Comments
 (0)