From b0c95a7026ce21435cbb03b3044ea3b43c53533a Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 8 Apr 2024 12:15:08 +0200 Subject: [PATCH 01/17] build UPDATE generate headers with install dir structure --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b89fb04de..74bde893f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11") endif() -include_directories(${PROJECT_BINARY_DIR}/src ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/plugins_exts) +include_directories(${PROJECT_BINARY_DIR}/libyang ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/plugins_exts) # type plugins are separate because they have their documentation generated set(type_plugins @@ -205,8 +205,8 @@ set(internal_headers src/xpath.h) set(gen_headers - src/version.h - src/ly_config.h) + version.h + ly_config.h) # files to generate doxygen from set(doxy_files @@ -214,7 +214,7 @@ set(doxy_files doc/transition_1_2.dox doc/transition_2_3.dox ${headers} - ${PROJECT_BINARY_DIR}/src/version.h + ${PROJECT_BINARY_DIR}/libyang/version.h ${type_plugins}) # project (doxygen) logo @@ -322,8 +322,8 @@ if ("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") endif() # generate files -configure_file(${PROJECT_SOURCE_DIR}/src/ly_config.h.in ${PROJECT_BINARY_DIR}/src/ly_config.h @ONLY) -configure_file(${PROJECT_SOURCE_DIR}/src/version.h.in ${PROJECT_BINARY_DIR}/src/version.h @ONLY) +configure_file(${PROJECT_SOURCE_DIR}/src/ly_config.h.in ${PROJECT_BINARY_DIR}/libyang/ly_config.h @ONLY) +configure_file(${PROJECT_SOURCE_DIR}/src/version.h.in ${PROJECT_BINARY_DIR}/libyang/version.h @ONLY) # DOC-only target with no extra dependencies if("${BUILD_TYPE_UPPER}" STREQUAL "DOCONLY") @@ -409,7 +409,7 @@ target_link_libraries(yang ${PCRE2_LIBRARIES}) # generated header list foreach(h IN LISTS gen_headers) - list(APPEND g_headers ${PROJECT_BINARY_DIR}/${h}) + list(APPEND g_headers ${PROJECT_BINARY_DIR}/libyang/${h}) endforeach() # install the modules From 3299b5c340e7aba2ec9b70e942a12c03891353cc Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 8 Apr 2024 13:30:20 +0200 Subject: [PATCH 02/17] build UPDATE allow disabling common targets --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74bde893f..108dc670c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,6 +246,7 @@ option(ENABLE_FUZZ_TARGETS "Build target programs suitable for fuzzing with AFL" option(ENABLE_INTERNAL_DOCS "Generate doxygen documentation also from internal headers" OFF) option(ENABLE_YANGLINT_INTERACTIVE "Enable interactive CLI yanglint" ON) option(ENABLE_TOOLS "Build binary tools 'yanglint' and 'yangre'" ON) +option(ENABLE_COMMON_TARGETS "Define common custom target names such as 'doc' or 'uninstall', may cause conflicts when using add_subdirectory() to build this project" ON) option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON) set(YANG_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules/libyang" CACHE STRING "Directory where to copy the YANG modules to") @@ -462,10 +463,12 @@ if(ENABLE_TOOLS) endif() # generate doxygen documentation for libyang API -gen_doc("${doxy_files}" ${LIBYANG_VERSION} ${LIBYANG_DESCRIPTION} ${project_logo}) +if(ENABLE_COMMON_TARGETS) + gen_doc("${doxy_files}" ${LIBYANG_VERSION} ${LIBYANG_DESCRIPTION} ${project_logo}) +endif() # generate API/ABI report -if ("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK") +if("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK") lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} dae82c1a652bdca0074544c62469a7f51d92c5e8) endif() @@ -474,7 +477,9 @@ endif() source_format(${format_sources}) # uninstall -add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake") +if(ENABLE_COMMON_TARGETS) + add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake") +endif() # clean cmake cache add_custom_target(cclean From 8d42c357ca16996ed02d4beb4abadf146cd07c20 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 8 Apr 2024 13:45:17 +0200 Subject: [PATCH 03/17] build UPDATE copy all public headers into a binary dir ... to allow standard include paths to work even if the library is not installed. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 108dc670c..2081b9c01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,9 +322,10 @@ if ("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") source_format_enable(0.77) endif() -# generate files +# generate and copy all public header files configure_file(${PROJECT_SOURCE_DIR}/src/ly_config.h.in ${PROJECT_BINARY_DIR}/libyang/ly_config.h @ONLY) configure_file(${PROJECT_SOURCE_DIR}/src/version.h.in ${PROJECT_BINARY_DIR}/libyang/version.h @ONLY) +file(COPY ${headers} DESTINATION ${PROJECT_BINARY_DIR}/libyang) # DOC-only target with no extra dependencies if("${BUILD_TYPE_UPPER}" STREQUAL "DOCONLY") From 350ed0d3908fa6391db66e26194a37706218d604 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 8 Apr 2024 14:13:04 +0200 Subject: [PATCH 04/17] doc UPDATE improve opaque node docs --- src/tree_data.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tree_data.h b/src/tree_data.h index 9f918af22..ff25b8b18 100644 --- a/src/tree_data.h +++ b/src/tree_data.h @@ -56,11 +56,11 @@ struct rb_node; * it can be cast to several other structures. * * In case the ::lyd_node.schema pointer is NULL, the node is actually __opaq__ and can be safely cast to ::lyd_node_opaq. - * The opaq node represent an unknown node which wasn't mapped to any [(compiled) schema](@ref howtoSchema) node in the - * context. Such a node can appear in several places in the data tree. + * The opaq node represents an **unknown node** which wasn't mapped to any [(compiled) schema](@ref howtoSchema) node in the + * context. But it may represent a schema node data instance which is invalid. That may happen if the value (leaf/leaf-list) + * is invalid or there are invalid/missing keys of a list instance. Such a node can appear in several places in the data tree. * - As a part of the tree structure, but only in the case the ::LYD_PARSE_OPAQ option was used when input data were - * [parsed](@ref howtoDataParsers), because unknown data instances are ignored by default. The same way, the opaq nodes can - * appear as a node's attributes. + * [parsed](@ref howtoDataParsers), because unknown data instances are ignored and invalid data produce errors by default. * - As a representation of YANG anydata/anyxml content. * - As envelopes of standard data tree instances (RPCs, actions or Notifications). * @@ -1281,7 +1281,8 @@ LIBYANG_API_DECL LY_ERR lyd_new_ext_inner(const struct lysc_ext_instance *ext, c no error set. */ #define LYD_NEW_PATH_OPAQ 0x40 /**< Enables the creation of opaque nodes with some specific rules. If the __last node__ in the path is not uniquely defined ((leaf-)list without a predicate) or has an - invalid value (leaf/leaf-list), it is created as opaque. */ + invalid value (leaf/leaf-list), it is created as opaque. Otherwise a regular node + is created. */ #define LYD_NEW_PATH_WITH_OPAQ 0x80 /**< Consider opaque nodes normally when searching for existing nodes. */ #define LYD_NEW_ANY_USE_VALUE 0x100 /**< Whether to use dynamic @p value or make a copy. */ From b077a760920c390cc2f4e3b74c970e6ca086a481 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 9 Apr 2024 15:13:52 +0200 Subject: [PATCH 05/17] tests BUGFIX sort cb return value must be compared with 0 ... instead of expecting only -1, 0, or 1. Refs #2222 --- tests/utests/types/binary.c | 4 ++-- tests/utests/types/enumeration.c | 4 ++-- tests/utests/types/leafref.c | 4 ++-- tests/utests/types/union.c | 8 ++++---- tests/utests/types/yang_types.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/utests/types/binary.c b/tests/utests/types/binary.c index 4d0cfbcc5..efdc8f112 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -327,8 +327,8 @@ test_plugin_sort(void **state) v2 = "YWhv"; /* aho */ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2), 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err)); - assert_int_equal(1, type->sort(UTEST_LYCTX, &val1, &val2)); - assert_int_equal(-1, type->sort(UTEST_LYCTX, &val2, &val1)); + assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2)); + assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1)); type->free(UTEST_LYCTX, &val1); type->free(UTEST_LYCTX, &val2); } diff --git a/tests/utests/types/enumeration.c b/tests/utests/types/enumeration.c index 0d42c54f6..8ff1c8ca9 100644 --- a/tests/utests/types/enumeration.c +++ b/tests/utests/types/enumeration.c @@ -108,9 +108,9 @@ test_plugin_sort(void **state) v2 = "black"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2), 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err)); - assert_int_equal(1, type->sort(UTEST_LYCTX, &val1, &val2)); + assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2)); assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1)); - assert_int_equal(-1, type->sort(UTEST_LYCTX, &val2, &val1)); + assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1)); type->free(UTEST_LYCTX, &val1); type->free(UTEST_LYCTX, &val2); } diff --git a/tests/utests/types/leafref.c b/tests/utests/types/leafref.c index 81e8ded83..002763ca1 100644 --- a/tests/utests/types/leafref.c +++ b/tests/utests/types/leafref.c @@ -239,9 +239,9 @@ test_plugin_sort(void **state) v2 = "str2"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2), 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err)); - assert_int_equal(-1, type->sort(UTEST_LYCTX, &val1, &val2)); + assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2)); assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1)); - assert_int_equal(1, type->sort(UTEST_LYCTX, &val2, &val1)); + assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1)); type->free(UTEST_LYCTX, &val1); type->free(UTEST_LYCTX, &val2); } diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 0d6ad2145..50593dc32 100644 --- a/tests/utests/types/union.c +++ b/tests/utests/types/union.c @@ -168,9 +168,9 @@ test_plugin_sort(void **state) v2 = "-1"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2), 0, LY_VALUE_JSON, NULL, LYD_VALHINT_DECNUM, NULL, &val2, NULL, &err)); - assert_int_equal(1, type->sort(UTEST_LYCTX, &val1, &val2)); + assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2)); assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1)); - assert_int_equal(-1, type->sort(UTEST_LYCTX, &val2, &val1)); + assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1)); type->free(UTEST_LYCTX, &val1); type->free(UTEST_LYCTX, &val2); @@ -180,8 +180,8 @@ test_plugin_sort(void **state) v2 = "-2"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2), 0, LY_VALUE_JSON, NULL, LYD_VALHINT_DECNUM, NULL, &val2, NULL, &err)); - assert_int_equal(1, type->sort(UTEST_LYCTX, &val1, &val2)); - assert_int_equal(-1, type->sort(UTEST_LYCTX, &val2, &val1)); + assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2)); + assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1)); type->free(UTEST_LYCTX, &val1); type->free(UTEST_LYCTX, &val2); } diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c index 42e1f3289..f79238eb5 100644 --- a/tests/utests/types/yang_types.c +++ b/tests/utests/types/yang_types.c @@ -301,8 +301,8 @@ test_sort(void **state) v2 = "2005-05-25T23:15:15.0001Z"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2), 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err)); - assert_int_equal(-1, type->sort(UTEST_LYCTX, &val1, &val2)); - assert_int_equal(1, type->sort(UTEST_LYCTX, &val2, &val1)); + assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2)); + assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1)); assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1)); type->free(UTEST_LYCTX, &val1); type->free(UTEST_LYCTX, &val2); From 0ef18baf9512218cc854349e8e466f4b225ddb80 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 9 Apr 2024 15:15:11 +0200 Subject: [PATCH 06/17] SOVERSION bump to version 3.0.9 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2081b9c01..f9fc9d8e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_ # set version of the library set(LIBYANG_MAJOR_SOVERSION 3) set(LIBYANG_MINOR_SOVERSION 0) -set(LIBYANG_MICRO_SOVERSION 8) +set(LIBYANG_MICRO_SOVERSION 9) set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION}) set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION}) From 9784492f473c0a59b1691a9320377b8a95d2a945 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 9 Apr 2024 15:15:25 +0200 Subject: [PATCH 07/17] VERSION bump to version 2.2.9 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f9fc9d8e3..0ab114431 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # set version of the project set(LIBYANG_MAJOR_VERSION 2) set(LIBYANG_MINOR_VERSION 2) -set(LIBYANG_MICRO_VERSION 8) +set(LIBYANG_MICRO_VERSION 9) set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION}) # set version of the library set(LIBYANG_MAJOR_SOVERSION 3) From 6845e81b91f4f81e9d04ec109ce83de32bc36357 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 10 Apr 2024 12:17:06 +0200 Subject: [PATCH 08/17] union REFACTOR better macro name --- src/plugins_types/union.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index 8dbc68bbf..c973a286a 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -41,9 +41,9 @@ */ /** - * @brief Size in bytes of the index in the LYB Binary Format. + * @brief Size in bytes of the used type index in the LYB Binary Format. */ -#define IDX_SIZE 4 +#define TYPE_IDX_SIZE 4 /** * @brief Assign a value to the union subvalue. @@ -95,14 +95,14 @@ lyb_union_validate(const void *lyb_data, size_t lyb_data_len, const struct lysc_ uint64_t type_idx = 0; /* Basic validation. */ - if (lyb_data_len < IDX_SIZE) { + if (lyb_data_len < TYPE_IDX_SIZE) { ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid LYB union value size %zu (expected at least 4).", lyb_data_len); return ret; } /* Get index in correct byte order. */ - memcpy(&type_idx, lyb_data, IDX_SIZE); + memcpy(&type_idx, lyb_data, TYPE_IDX_SIZE); type_idx = le64toh(type_idx); if (type_idx >= LY_ARRAY_COUNT(type_u->types)) { ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, @@ -132,7 +132,7 @@ lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, c assert(lyb_data && !(lyb_value && !lyb_value_len)); if (type_idx) { - memcpy(&num, lyb_data, IDX_SIZE); + memcpy(&num, lyb_data, TYPE_IDX_SIZE); num = le64toh(num); *type_idx = num; @@ -140,12 +140,12 @@ lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, c if (lyb_value && lyb_value_len && lyb_data_len) { /* Get lyb_value and its length. */ - if (lyb_data_len == IDX_SIZE) { + if (lyb_data_len == TYPE_IDX_SIZE) { *lyb_value_len = 0; *lyb_value = ""; } else { - *lyb_value_len = lyb_data_len - IDX_SIZE; - *lyb_value = (char *)lyb_data + IDX_SIZE; + *lyb_value_len = lyb_data_len - TYPE_IDX_SIZE; + *lyb_value = (char *)lyb_data + TYPE_IDX_SIZE; } } } @@ -505,14 +505,14 @@ lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct LY_CHECK_RET(!pval, NULL); /* Create LYB data. */ - *value_len = IDX_SIZE + pval_len; + *value_len = TYPE_IDX_SIZE + pval_len; ret = malloc(*value_len); LY_CHECK_RET(!ret, NULL); num = type_idx; num = htole64(num); - memcpy(ret, &num, IDX_SIZE); - memcpy((char *)ret + IDX_SIZE, pval, pval_len); + memcpy(ret, &num, TYPE_IDX_SIZE); + memcpy((char *)ret + TYPE_IDX_SIZE, pval, pval_len); if (dynamic) { free(pval); From cf43fa7e69fb18088ae9ff1e19bf2c8fe0756afe Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 10 Apr 2024 12:17:43 +0200 Subject: [PATCH 09/17] union BUGFIX proper LYB value validation Fixes #1560 --- src/plugins_types/union.c | 142 +++++++++++++++++++++++++------------ tests/utests/types/union.c | 68 ++++++++++++++++++ 2 files changed, 163 insertions(+), 47 deletions(-) diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index c973a286a..bd6105fa2 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -151,13 +151,14 @@ lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, c } /** - * @brief Store subvalue as a specific type. + * @brief Store (and validate) subvalue as a specific type. * * @param[in] ctx libyang context. - * @param[in] type Specific union type to use for storing. - * @param[in] subvalue Union subvalue structure. + * @param[in] type_u Union type. + * @param[in] type_idx Union type index to use for storing (and validating). + * @param[in,out] subvalue Union subvalue structure, its value needs to be filled. * @param[in] options The store options. - * @param[in] resolve Whether the value needs to be resolved (validated by a callback). + * @param[in] validate Whether the value needs to be validated. * @param[in] ctx_node Context node for prefix resolution. * @param[in] tree Data tree for resolving (validation). * @param[in,out] unres Global unres structure. @@ -165,50 +166,88 @@ lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, c * @return LY_ERR value. */ static LY_ERR -union_store_type(const struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value_union *subvalue, uint32_t options, - ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lys_glob_unres *unres, - struct ly_err_item **err) +union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint32_t type_idx, struct lyd_value_union *subvalue, + uint32_t options, ly_bool validate, const struct lyd_node *ctx_node, const struct lyd_node *tree, + struct lys_glob_unres *unres, struct ly_err_item **err) { - LY_ERR ret; + LY_ERR rc = LY_SUCCESS; + struct lysc_type *type = type_u->types[type_idx]; const void *value = NULL; size_t value_len = 0; - uint32_t opts; + ly_bool dynamic = 0; + LY_VALUE_FORMAT format; + void *prefix_data; + uint32_t opts = 0, ti; *err = NULL; if (subvalue->format == LY_VALUE_LYB) { - lyb_parse_union(subvalue->original, subvalue->orig_len, NULL, &value, &value_len); + lyb_parse_union(subvalue->original, subvalue->orig_len, &ti, &value, &value_len); + if (ti != type_idx) { + /* value of another type, first store the value properly and then use its JSON value for parsing */ + rc = type_u->types[ti]->plugin->store(ctx, type_u->types[ti], value, value_len, LYPLG_TYPE_STORE_ONLY, + subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err); + if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) { + /* clear any leftover/freed garbage */ + memset(&subvalue->value, 0, sizeof subvalue->value); + return rc; + } + + assert(subvalue->value.realtype); + value = subvalue->value.realtype->plugin->print(ctx, &subvalue->value, LY_VALUE_JSON, NULL, &dynamic, &value_len); + + /* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */ + if (!dynamic) { + value = strndup(value, value_len); + dynamic = 1; + } + type_u->types[ti]->plugin->free(ctx, &subvalue->value); + + format = LY_VALUE_JSON; + prefix_data = NULL; + } else { + format = subvalue->format; + prefix_data = subvalue->prefix_data; + } } else { value = subvalue->original; value_len = subvalue->orig_len; + format = subvalue->format; + prefix_data = subvalue->prefix_data; + } + + if (options & LYPLG_TYPE_STORE_ONLY) { + opts |= LYPLG_TYPE_STORE_ONLY; + } + if (dynamic) { + opts |= LYPLG_TYPE_STORE_DYNAMIC; } - opts = (options & LYPLG_TYPE_STORE_ONLY) ? LYPLG_TYPE_STORE_ONLY : 0; - ret = type->plugin->store(ctx, type, value, value_len, opts, subvalue->format, subvalue->prefix_data, subvalue->hints, + rc = type->plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err); - if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) { + if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) { /* clear any leftover/freed garbage */ memset(&subvalue->value, 0, sizeof subvalue->value); - return ret; + return rc; } - if (resolve && (ret == LY_EINCOMPLETE)) { - /* we need the value resolved */ - ret = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err); - if (ret) { - /* resolve failed, we need to free the stored value */ + if (validate && (rc == LY_EINCOMPLETE)) { + /* we need the value validated */ + rc = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err); + if (rc) { + /* validate failed, we need to free the stored value */ type->plugin->free(ctx, &subvalue->value); } } - return ret; + return rc; } /** * @brief Find the first valid type for a union value. * * @param[in] ctx libyang context. - * @param[in] types Sized array of union types. + * @param[in] type_u Union type. * @param[in] subvalue Union subvalue structure. * @param[in] options The store options. * @param[in] resolve Whether the value needs to be resolved (validated by a callback). @@ -220,7 +259,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type *type, struct lyd_va * @return LY_ERR value. */ static LY_ERR -union_find_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_value_union *subvalue, +union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue, uint32_t options, ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, uint32_t *type_idx, struct lys_glob_unres *unres, struct ly_err_item **err) { @@ -233,20 +272,16 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_v *err = NULL; - if (!types || !LY_ARRAY_COUNT(types)) { - return LY_EINVAL; - } - /* alloc errors */ - errs = calloc(LY_ARRAY_COUNT(types), sizeof *errs); + errs = calloc(LY_ARRAY_COUNT(type_u->types), sizeof *errs); LY_CHECK_RET(!errs, LY_EMEM); /* turn logging temporarily off */ prev_lo = ly_temp_log_options(&temp_lo); /* use the first usable subtype to store the value */ - for (u = 0; u < LY_ARRAY_COUNT(types); ++u) { - ret = union_store_type(ctx, types[u], subvalue, options, resolve, ctx_node, tree, unres, &e); + for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) { + ret = union_store_type(ctx, type_u, u, subvalue, options, resolve, ctx_node, tree, unres, &e); if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) { break; } @@ -254,22 +289,26 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_v errs[u] = e; } - if (u == LY_ARRAY_COUNT(types)) { + if (u == LY_ARRAY_COUNT(type_u->types)) { /* create the full error */ - msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n", - (int)subvalue->orig_len, (char *)subvalue->original); + if (subvalue->format == LY_VALUE_LYB) { + msg_len = asprintf(&msg, "Invalid LYB union value - no matching subtype found:\n"); + } else { + msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n", + (int)subvalue->orig_len, (char *)subvalue->original); + } if (msg_len == -1) { LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup); } - for (u = 0; u < LY_ARRAY_COUNT(types); ++u) { + for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) { if (!errs[u]) { /* no error for some reason */ continue; } - msg = ly_realloc(msg, msg_len + 4 + strlen(types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2); + msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2); LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup); - msg_len += sprintf(msg + msg_len, " %s: %s\n", types[u]->plugin->id, errs[u]->msg); + msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg); } ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "%s", msg); @@ -278,7 +317,7 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_v } cleanup: - for (u = 0; u < LY_ARRAY_COUNT(types); ++u) { + for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) { ly_err_free(errs[u]); } free(errs); @@ -334,7 +373,7 @@ lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, cons } /* use the specific type to store the value */ - ret = union_store_type(ctx, type_u->types[type_idx], subvalue, *options, 0, NULL, NULL, unres, err); + ret = union_store_type(ctx, type_u, type_idx, subvalue, *options, 0, NULL, NULL, unres, err); return ret; } @@ -362,7 +401,7 @@ lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, c ret = lyb_fill_subvalue(ctx, type_u, value, value_len, prefix_data, subvalue, &options, unres, err); LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup); } else { - /* Store @p value to subvalue. */ + /* store value to subvalue */ ret = union_subvalue_assignment(value, value_len, &subvalue->original, &subvalue->orig_len, &options); LY_CHECK_GOTO(ret, cleanup); @@ -372,7 +411,7 @@ lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, c LY_CHECK_GOTO(ret, cleanup); /* use the first usable subtype to store the value */ - ret = union_find_type(ctx, type_u->types, subvalue, options, 0, NULL, NULL, NULL, unres, err); + ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, unres, err); LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup); } @@ -399,22 +438,31 @@ lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type struct lysc_type_union *type_u = (struct lysc_type_union *)type; struct lyd_value_union *subvalue = storage->subvalue; uint32_t type_idx; + ly_bool validated = 0; *err = NULL; /* because of types that do not store their own type as realtype (leafref), we are not able to call their - * validate callback (there is no way to get the type TODO could be added to struct lyd_value_union), so - * we have to perform union value storing again from scratch */ + * validate callback (there is no way to get the type) but even if possible, the value may be invalid + * for the type, so we may have to perform union value storing again from scratch */ subvalue->value.realtype->plugin->free(ctx, &subvalue->value); if (subvalue->format == LY_VALUE_LYB) { - /* use the specific type to store the value */ + /* use the specific type to store and validate the value */ lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL); - ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 0, 1, ctx_node, tree, NULL, err); - LY_CHECK_RET(ret); - } else { + ret = union_store_type(ctx, type_u, type_idx, subvalue, 0, 1, ctx_node, tree, NULL, err); + if (ret) { + /* validation failed, we need to try storing the value again */ + ly_err_free(*err); + *err = NULL; + } else { + validated = 1; + } + } + + if (!validated) { /* use the first usable subtype to store the value */ - ret = union_find_type(ctx, type_u->types, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err); + ret = union_find_type(ctx, type_u, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err); LY_CHECK_RET(ret); } @@ -495,7 +543,7 @@ lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct ctx = subvalue->ctx_node->module->ctx; } subvalue->value.realtype->plugin->free(ctx, &subvalue->value); - r = union_find_type(ctx, type_u->types, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err); + r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err); ly_err_free(err); LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL); diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 50593dc32..c2541aaaf 100644 --- a/tests/utests/types/union.c +++ b/tests/utests/types/union.c @@ -192,6 +192,7 @@ test_validation(void **state) const char *schema, *data; struct lyd_node *tree; char *out; + uint32_t uint_val; schema = MODULE_CREATE_YANG("val", "leaf l1 {\n" @@ -230,6 +231,73 @@ test_validation(void **state) free(out); lyd_free_all(tree); + + schema = MODULE_CREATE_YANG("lref", + "container test {\n" + " list a {\n" + " key \"name\";\n" + " leaf name {\n" + " type enumeration {\n" + " enum zero;\n" + " enum one;\n" + " enum two;\n" + " }\n" + " }\n" + " }\n" + "\n" + " list b {\n" + " key \"name\";\n" + " leaf name {\n" + " type uint32;\n" + " }\n" + " }\n" + "\n" + " list community {\n" + " key \"name\";\n" + " leaf name {\n" + " type string;\n" + " }\n" + " leaf view {\n" + " type union {\n" + " type leafref {\n" + " path \"../../a/name\";\n" + " }\n" + " type leafref {\n" + " path \"../../b/name\";\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}\n"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + /* parse from LYB #1 */ + data = "2test2"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS)); + lyd_free_all(tree); + CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + free(out); + lyd_free_all(tree); + + /* parse from LYB #2 */ + data = "onetestone"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS)); + lyd_free_all(tree); + CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + free(out); + + /* remove the target and create another, which is represented the same way in LYB */ + lyd_free_tree(lyd_child(tree)); + uint_val = 1; + assert_int_equal(LY_SUCCESS, lyd_new_list(tree, NULL, "b", LYD_NEW_VAL_BIN, NULL, &uint_val, sizeof uint_val)); + assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL)); + CHECK_LOG_CTX("Invalid LYB union value - no matching subtype found:\n" + " libyang 2 - leafref, version 1: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" + " libyang 2 - leafref, version 1: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0); + + lyd_free_all(tree); } int From e8885ba572c8765146e6617f49b414ab9a4b9bc4 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 10 Apr 2024 12:20:49 +0200 Subject: [PATCH 10/17] SOVERSION bump to version 3.0.10 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ab114431..6046b24be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_ # set version of the library set(LIBYANG_MAJOR_SOVERSION 3) set(LIBYANG_MINOR_SOVERSION 0) -set(LIBYANG_MICRO_SOVERSION 9) +set(LIBYANG_MICRO_SOVERSION 10) set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION}) set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION}) From a1406a52af351c77db13f494e3f7e745d3fa6f8f Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 10 Apr 2024 12:20:57 +0200 Subject: [PATCH 11/17] VERSION bump to version 2.2.10 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6046b24be..c80695197 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # set version of the project set(LIBYANG_MAJOR_VERSION 2) set(LIBYANG_MINOR_VERSION 2) -set(LIBYANG_MICRO_VERSION 9) +set(LIBYANG_MICRO_VERSION 10) set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION}) # set version of the library set(LIBYANG_MAJOR_SOVERSION 3) From 74cc1264f3e824257f104be45004cedc5e3b0ba0 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 12 Apr 2024 11:10:53 +0200 Subject: [PATCH 12/17] log UPDATE logging messages without memory --- src/log.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/log.c b/src/log.c index f936abfee..9bb4b1902 100644 --- a/src/log.c +++ b/src/log.c @@ -592,7 +592,8 @@ static void log_vprintf(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE vecode, char *data_path, char *schema_path, uint64_t line, const char *apptag, const char *format, va_list args) { - char *msg = NULL; + char *dyn_msg = NULL; + const char *msg; ly_bool free_strs = 1, lolog, lostore; /* learn effective logger options */ @@ -610,33 +611,26 @@ log_vprintf(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE } if (err == LY_EMEM) { - /* just print it, anything else would most likely fail anyway */ - if (lolog) { - if (log_clb) { - log_clb(level, LY_EMEM_MSG, data_path, schema_path, line); - } else { - fprintf(stderr, "libyang[%d]: ", level); - vfprintf(stderr, format, args); - log_stderr_path_line(data_path, schema_path, line); - } + /* no not use more dynamic memory */ + vsnprintf(last_msg, LY_LAST_MSG_SIZE, format, args); + msg = last_msg; + } else { + /* print into a single message */ + if (vasprintf(&dyn_msg, format, args) == -1) { + LOGMEM(ctx); + goto cleanup; } - goto cleanup; - } + msg = dyn_msg; - /* print into a single message */ - if (vasprintf(&msg, format, args) == -1) { - LOGMEM(ctx); - goto cleanup; + /* store as the last message */ + strncpy(last_msg, msg, LY_LAST_MSG_SIZE - 1); } - /* store as the last message */ - strncpy(last_msg, msg, LY_LAST_MSG_SIZE - 1); - /* store the error/warning in the context (if we need to store errors internally, it does not matter what are - * the user log options) */ - if ((level < LY_LLVRB) && ctx && lostore) { + * the user log options), if the message is not dynamic, it would most likely fail to store (no memory) */ + if ((level < LY_LLVRB) && ctx && lostore && dyn_msg) { free_strs = 0; - if (log_store(ctx, level, err, vecode, msg, data_path, schema_path, line, apptag ? strdup(apptag) : NULL)) { + if (log_store(ctx, level, err, vecode, dyn_msg, data_path, schema_path, line, apptag ? strdup(apptag) : NULL)) { goto cleanup; } } @@ -656,7 +650,7 @@ log_vprintf(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE if (free_strs) { free(data_path); free(schema_path); - free(msg); + free(dyn_msg); } } From c16626665f2398f9938efcb4f8be4598468c129a Mon Sep 17 00:00:00 2001 From: Vincent JARDIN Date: Wed, 20 Mar 2024 13:14:37 +0100 Subject: [PATCH 13/17] FRRouting + libyang build It can build using a set of well known verions of libyang, for some well known tags. The purpose is to ensure that libyang and FRRouting keeps working together smoothly. Currently, it is just about a compilation and link test. In order to work with pre-set tags/versions, the fork should include the git tags. If they are missing, you can catch up those tags using: $ git remote -v origin git@github.com:vjardin/libyang.git (fetch) origin git@github.com:vjardin/libyang.git (push) upstream git@github.com:CESNET/libyang.git (fetch) upstream git@github.com:CESNET/libyang.git (push) $ git fetch --tags upstream $ git tag -l $ git push --tags origin --- .github/workflows/frr-checks.yml | 117 +++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .github/workflows/frr-checks.yml diff --git a/.github/workflows/frr-checks.yml b/.github/workflows/frr-checks.yml new file mode 100644 index 000000000..3f461553d --- /dev/null +++ b/.github/workflows/frr-checks.yml @@ -0,0 +1,117 @@ +name: libyang+FRR HEAD CI +run-name: libyang CI FRR ${{ github.actor }} ⚗️ +on: + schedule: + # every night at 1.10 + - cron: '10 1 * * *' +# the following in pending for fixes per the comments of pr !2203 +# push: +# branches: +# - '**' +# pull_request: +# branches: +# - '**' +jobs: + build-frr: + name: Build FRR + runs-on: ubuntu-latest + strategy: + matrix: + compiler: [ gcc ] + frr-versions: + - master + libyang-versions: + - v2.1.128 + steps: + - name: add missing packages per building-frr-for-ubuntu2204 + uses: ConorMacBride/install-package@v1 + with: + apt: + git + autoconf + libtool + make + libreadline-dev + texinfo + pkg-config + libelf-dev + libpam0g-dev + libjson-c-dev + bison + flex + libc-ares-dev + python3-dev + python3-sphinx + install-info + build-essential + libsnmp-dev + perl + libcap-dev + libelf-dev + libunwind-dev + protobuf-c-compiler + libprotobuf-c-dev + libgrpc++-dev + protobuf-compiler-grpc + libsqlite3-dev + libzmq5 + libzmq3-dev + - name: libyang ${{ matrix.libyang-versions }} ${{ matrix.compiler }} + uses: actions/checkout@v4 + with: + ref: ${{ matrix.libyang-versions }} + submodules: false + fetch-depth: 0 + filter: tree:0 + fetch-tags: true + - name: make libyang from upstream + run: >- + git branch && + mkdir build && + cd build && + export CC=${{ matrix.compiler }} && + cmake -DCMAKE_BUILD_TYPE:String="Release" .. && + make -j $(nproc) && + sudo make install + - name: Add FRR user and groups + run: >- + sudo groupadd -r -g 92 frr && + sudo groupadd -r -g 85 frrvty && + sudo adduser --system --ingroup frr --home /var/run/frr/ --gecos "FRR suite" --shell /sbin/nologin frr && + sudo usermod -a -G frrvty frr + - name: FRR github checkout + uses: actions/checkout@v4 + with: + repository: 'FRRouting/frr.git' + ref: ${{ matrix.frr-versions }} + submodules: false + fetch-depth: 0 + filter: tree:0 + fetch-tags: true + - name: compile FRR with ${{ matrix.libyang-versions }} ${{ matrix.compiler }} + if: ${{ always() }} + run: >- + ls -la && + export CC=${{ matrix.compiler }} && + ./bootstrap.sh && + ./configure \ + --prefix=/usr \ + --includedir=\${prefix}/include \ + --bindir=\${prefix}/bin \ + --sbindir=\${prefix}/lib/frr \ + --libdir=\${prefix}/lib/frr \ + --libexecdir=\${prefix}/lib/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --with-moduledir=\${prefix}/lib/frr/modules \ + --enable-configfile-mask=0640 \ + --enable-logfile-mask=0640 \ + --enable-snmp=agentx \ + --enable-multipath=64 \ + --enable-user=frr \ + --enable-group=frr \ + --enable-vty-group=frrvty \ + --with-pkg-git-version \ + --with-pkg-extra-version=-MyOwnFRRVersion && + make -j $(nproc) && + sudo make install From 77a9ed076f2c1a7892b4bd482988b1c09fb396a8 Mon Sep 17 00:00:00 2001 From: Vincent JARDIN Date: Wed, 20 Mar 2024 14:03:32 +0100 Subject: [PATCH 14/17] Do not run with FRR master, but only releases --- .github/workflows/frr-checks.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/frr-checks.yml b/.github/workflows/frr-checks.yml index 3f461553d..2e7e9145d 100644 --- a/.github/workflows/frr-checks.yml +++ b/.github/workflows/frr-checks.yml @@ -19,7 +19,9 @@ jobs: matrix: compiler: [ gcc ] frr-versions: - - master + - frr-9.1 + - frr-9.0.2 + - frr-8.5.4 libyang-versions: - v2.1.128 steps: From 1fed62054a4a08b944969f1995f8e7828fee289e Mon Sep 17 00:00:00 2001 From: Vincent JARDIN Date: Fri, 22 Mar 2024 10:02:56 +0100 Subject: [PATCH 15/17] workflow: currently, manual/ondemand run While libyang is bringing many evolutions, let's avoid running it. The versions can be master/devel or the tag'd ones. --- .github/workflows/frr-checks.yml | 47 +++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/frr-checks.yml b/.github/workflows/frr-checks.yml index 2e7e9145d..cd52d799f 100644 --- a/.github/workflows/frr-checks.yml +++ b/.github/workflows/frr-checks.yml @@ -1,9 +1,30 @@ name: libyang+FRR HEAD CI run-name: libyang CI FRR ${{ github.actor }} ⚗️ on: - schedule: - # every night at 1.10 - - cron: '10 1 * * *' + workflow_dispatch: + inputs: + frr-versions: + description: 'FRRouting version' + required: true + default: 'master' + type: choice + options: + - master + - frr-9.1 + - frr-9.0.2 + - frr-8.5.4 + libyang-versions: + description: 'libyang version' + required: true + default: 'devel' + type: choice + options: + - devel + - v2.1.148 + - v2.1.128 +# schedule: +# # every night at 1.10 +# - cron: '10 1 * * *' # the following in pending for fixes per the comments of pr !2203 # push: # branches: @@ -18,12 +39,12 @@ jobs: strategy: matrix: compiler: [ gcc ] - frr-versions: - - frr-9.1 - - frr-9.0.2 - - frr-8.5.4 - libyang-versions: - - v2.1.128 +# frr-versions: +# - frr-9.1 +# - frr-9.0.2 +# - frr-8.5.4 +# libyang-versions: +# - v2.1.128 steps: - name: add missing packages per building-frr-for-ubuntu2204 uses: ConorMacBride/install-package@v1 @@ -58,10 +79,10 @@ jobs: libsqlite3-dev libzmq5 libzmq3-dev - - name: libyang ${{ matrix.libyang-versions }} ${{ matrix.compiler }} + - name: libyang ${{ inputs.libyang-versions }} ${{ matrix.compiler }} uses: actions/checkout@v4 with: - ref: ${{ matrix.libyang-versions }} + ref: ${{ inputs.libyang-versions }} submodules: false fetch-depth: 0 filter: tree:0 @@ -85,12 +106,12 @@ jobs: uses: actions/checkout@v4 with: repository: 'FRRouting/frr.git' - ref: ${{ matrix.frr-versions }} + ref: ${{ inputs.frr-versions }} submodules: false fetch-depth: 0 filter: tree:0 fetch-tags: true - - name: compile FRR with ${{ matrix.libyang-versions }} ${{ matrix.compiler }} + - name: compile FRR with ${{ inputs.libyang-versions }} ${{ matrix.compiler }} if: ${{ always() }} run: >- ls -la && From ded95c7c88bb2f32d2bbf3669de8d16372a9990f Mon Sep 17 00:00:00 2001 From: Vincent JARDIN Date: Sat, 23 Mar 2024 09:33:25 +0100 Subject: [PATCH 16/17] Add WIP FRR libyang3 support --- .github/workflows/frr-checks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/frr-checks.yml b/.github/workflows/frr-checks.yml index cd52d799f..81a2b434c 100644 --- a/.github/workflows/frr-checks.yml +++ b/.github/workflows/frr-checks.yml @@ -10,6 +10,7 @@ on: type: choice options: - master + - pull/15608/head - frr-9.1 - frr-9.0.2 - frr-8.5.4 From 2c571e7cc44bc14fca8af8e4122ebb152925a2b7 Mon Sep 17 00:00:00 2001 From: Vincent JARDIN Date: Sat, 13 Apr 2024 15:55:27 +0200 Subject: [PATCH 17/17] frr: topotests Add 1 basic test for libyang checks Apply the guidelines from https://docs.frrouting.org/projects/dev-guide/en/latest/topotests.html --- .github/workflows/frr-checks.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/frr-checks.yml b/.github/workflows/frr-checks.yml index 81a2b434c..63ebad8c7 100644 --- a/.github/workflows/frr-checks.yml +++ b/.github/workflows/frr-checks.yml @@ -11,6 +11,7 @@ on: options: - master - pull/15608/head + - frr-10.0 - frr-9.1 - frr-9.0.2 - frr-8.5.4 @@ -80,6 +81,7 @@ jobs: libsqlite3-dev libzmq5 libzmq3-dev + python3-pytest - name: libyang ${{ inputs.libyang-versions }} ${{ matrix.compiler }} uses: actions/checkout@v4 with: @@ -130,6 +132,10 @@ jobs: --with-moduledir=\${prefix}/lib/frr/modules \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ + --enable-vtysh \ + --enable-pimd \ + --enable-pim6d \ + --enable-sharpd \ --enable-snmp=agentx \ --enable-multipath=64 \ --enable-user=frr \ @@ -138,4 +144,6 @@ jobs: --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion && make -j $(nproc) && - sudo make install + sudo make install && + cd tests/topotests && + cd all_protocol_startup && pytest-3 -s -v