From 3bb513c399c2e7c8dd597b7399dd7c0f064842d0 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Tue, 4 May 2021 10:41:58 -0400 Subject: [PATCH] lib: adapt to version 2 of libyang Compile with v2.0.0 tag of `libyang2` branch of: https://github.com/CESNET/libyang staticd init load time of 10k routes now 6s vs ly1 time of 150s Signed-off-by: Christian Hopps --- .clang-format | 3 + .travis.yml | 16 +- bfdd/bfd.c | 8 +- bgpd/bgp_nb.c | 3 - bgpd/bgp_nb.h | 6 - bgpd/bgp_nb_config.c | 62 +-- bgpd/bgp_vty.c | 48 +-- bgpd/subdir.am | 4 +- configure.ac | 4 +- debian/control | 4 +- doc/developer/building-libyang.rst | 22 +- docker/ubuntu18-ci/Dockerfile | 14 +- docker/ubuntu20-ci/Dockerfile | 14 +- eigrpd/eigrp_cli.c | 2 +- isisd/isis_circuit.c | 2 +- isisd/isis_cli.c | 26 +- isisd/isis_nb_config.c | 32 +- lib/grammar_sandbox_main.c | 1 - lib/if.c | 6 +- lib/libfrr.c | 6 +- lib/northbound.c | 377 +++++++++++------ lib/northbound.h | 15 +- lib/northbound_cli.c | 93 +++-- lib/northbound_confd.c | 16 +- lib/northbound_grpc.cpp | 2 +- lib/northbound_sysrepo.c | 22 +- lib/vrf.c | 3 +- lib/yang.c | 400 +++++++++--------- lib/yang.h | 143 +++++-- lib/yang_translator.c | 129 +++--- lib/yang_wrappers.c | 546 ++++++++----------------- pathd/path_pcep_debug.c | 2 +- pimd/pim_cmd.c | 76 ++-- pimd/pim_nb_config.c | 9 +- redhat/frr.spec.in | 2 +- ripd/rip_cli.c | 12 +- ripd/rip_interface.c | 2 +- ripd/ripd.c | 10 +- ripngd/ripng_interface.c | 2 +- ripngd/ripngd.c | 10 +- staticd/static_nb.c | 2 - staticd/static_nb.h | 4 - staticd/static_nb_config.c | 37 +- tests/bgpd/test_peer_attr.c | 3 +- tests/helpers/c/main.c | 1 - tests/isisd/test_isis_spf.c | 2 +- tests/lib/cli/common_cli.c | 1 - tests/lib/cli/test_commands.c | 1 - tests/lib/northbound/test_oper_data.c | 1 - tests/subdir.am | 2 +- tools/gen_northbound_callbacks.c | 29 +- tools/gen_yang_deviations.c | 7 +- vrrpd/vrrp_vty.c | 2 +- vtysh/extract.pl.in | 2 +- vtysh/vtysh.c | 33 ++ watchfrr/subdir.am | 2 +- yang/embedmodel.py | 2 +- yang/frr-bgp-bmp.yang | 2 - yang/frr-bgp-common-multiprotocol.yang | 30 +- yang/frr-bgp-common-structure.yang | 3 - yang/frr-bgp-common.yang | 7 +- yang/frr-bgp-neighbor.yang | 3 - yang/frr-bgp-peer-group.yang | 3 - yang/frr-bgp-route-map.yang | 88 ++-- yang/frr-bgp.yang | 4 +- yang/frr-isisd.yang | 18 +- yang/frr-ospfd.yang | 6 +- yang/frr-pim.yang | 4 +- yang/frr-ripd.yang | 12 +- yang/frr-zebra-route-map.yang | 26 +- yang/frr-zebra.yang | 2 +- 71 files changed, 1226 insertions(+), 1267 deletions(-) diff --git a/.clang-format b/.clang-format index 47d681e0e202..e1897bfa99ab 100644 --- a/.clang-format +++ b/.clang-format @@ -50,8 +50,11 @@ ForEachMacros: - FOR_ALL_INTERFACES_ADDRESSES - JSON_FOREACH # libyang + - LY_FOR_KEYS + - LY_LIST_FOR - LY_TREE_FOR - LY_TREE_DFS_BEGIN + - LYD_TREE_DFS_BEGIN # zebra - RE_DEST_FOREACH_ROUTE - RE_DEST_FOREACH_ROUTE_SAFE diff --git a/.travis.yml b/.travis.yml index d8e450a646d7..84dd2d7ec283 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,14 +5,14 @@ services: - docker jobs: include: - - script: - - docker/centos-7/build.sh - - docker images - name: centos7 - - script: - - docker/centos-8/build.sh - - docker images - name: centos8 + # - script: + # - docker/centos-7/build.sh + # - docker images + # name: centos7 + # - script: + # - docker/centos-8/build.sh + # - docker images + # name: centos8 - script: - sudo apt install -y linux-modules-extra-$(uname -r) - docker build -t frr-ubuntu18:latest -f docker/ubuntu18-ci/Dockerfile . diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 18f331e20108..c66fccb853ad 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -2195,13 +2195,13 @@ void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf) snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']/vrf", bs->key.vrfname); - bfd_dnode = yang_dnode_get(running_config->dnode, xpath, - bs->key.vrfname); + bfd_dnode = yang_dnode_getf(running_config->dnode, xpath, + bs->key.vrfname); if (bfd_dnode) { - yang_dnode_get_path(bfd_dnode->parent, oldpath, + yang_dnode_get_path(lyd_parent(bfd_dnode), oldpath, sizeof(oldpath)); yang_dnode_change_leaf(bfd_dnode, vrf->name); - yang_dnode_get_path(bfd_dnode->parent, newpath, + yang_dnode_get_path(lyd_parent(bfd_dnode), newpath, sizeof(newpath)); nb_running_move_tree(oldpath, newpath); running_config->version++; diff --git a/bgpd/bgp_nb.c b/bgpd/bgp_nb.c index 21810b634d4d..71824cd6d3e5 100644 --- a/bgpd/bgp_nb.c +++ b/bgpd/bgp_nb.c @@ -632,7 +632,6 @@ const struct frr_yang_module_info frr_bgp_info = { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/neighbor/local-as/no-prepend", .cbs = { .modify = bgp_neighbors_neighbor_local_as_no_prepend_modify, - .destroy = bgp_neighbors_neighbor_local_as_no_prepend_destroy, } }, { @@ -923,7 +922,6 @@ const struct frr_yang_module_info frr_bgp_info = { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/unnumbered-neighbor/local-as/no-prepend", .cbs = { .modify = bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_modify, - .destroy = bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_destroy, } }, { @@ -1215,7 +1213,6 @@ const struct frr_yang_module_info frr_bgp_info = { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/peer-groups/peer-group/local-as/no-prepend", .cbs = { .modify = bgp_peer_groups_peer_group_local_as_no_prepend_modify, - .destroy = bgp_peer_groups_peer_group_local_as_no_prepend_destroy, } }, { diff --git a/bgpd/bgp_nb.h b/bgpd/bgp_nb.h index 57f379b6ccd5..f8bb31aad6ec 100644 --- a/bgpd/bgp_nb.h +++ b/bgpd/bgp_nb.h @@ -233,8 +233,6 @@ int bgp_neighbors_neighbor_local_as_local_as_destroy( struct nb_cb_destroy_args *args); int bgp_neighbors_neighbor_local_as_no_prepend_modify( struct nb_cb_modify_args *args); -int bgp_neighbors_neighbor_local_as_no_prepend_destroy( - struct nb_cb_destroy_args *args); int bgp_neighbors_neighbor_local_as_no_replace_as_modify( struct nb_cb_modify_args *args); int bgp_neighbors_neighbor_bfd_options_enable_modify( @@ -367,8 +365,6 @@ int bgp_neighbors_unnumbered_neighbor_local_as_local_as_destroy( struct nb_cb_destroy_args *args); int bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_modify( struct nb_cb_modify_args *args); -int bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_destroy( - struct nb_cb_destroy_args *args); int bgp_neighbors_unnumbered_neighbor_local_as_no_replace_as_modify( struct nb_cb_modify_args *args); int bgp_neighbors_unnumbered_neighbor_bfd_options_enable_modify( @@ -501,8 +497,6 @@ int bgp_peer_groups_peer_group_local_as_local_as_destroy( struct nb_cb_destroy_args *args); int bgp_peer_groups_peer_group_local_as_no_prepend_modify( struct nb_cb_modify_args *args); -int bgp_peer_groups_peer_group_local_as_no_prepend_destroy( - struct nb_cb_destroy_args *args); int bgp_peer_groups_peer_group_local_as_no_replace_as_modify( struct nb_cb_modify_args *args); int bgp_peer_groups_peer_group_bfd_options_enable_modify( diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index 8ca7836a99ba..a430124b51a2 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -239,8 +239,8 @@ int bgp_global_local_as_modify(struct nb_cb_modify_args *args) * If the instance already exists - return the validation * error. */ - bgp = nb_running_get_entry_non_rec(args->dnode->parent->parent, - NULL, false); + bgp = nb_running_get_entry_non_rec( + lyd_parent(lyd_parent(args->dnode)), NULL, false); if (bgp) { snprintf(args->errmsg, args->errmsg_len, "Changing AS number is not allowed"); @@ -580,16 +580,11 @@ int bgp_global_route_reflector_route_reflector_cluster_id_modify( struct bgp *bgp; struct in_addr cluster_id; - const struct lyd_node_leaf_list *dleaf; bgp = nb_running_get_entry(args->dnode, NULL, true); - dleaf = (const struct lyd_node_leaf_list *)args->dnode; - if (dleaf->value_type == LY_TYPE_STRING) - yang_dnode_get_ipv4(&cluster_id, args->dnode, NULL); - else - (void)inet_aton(dleaf->value_str, &cluster_id); - + /* cluster-id is either dotted-quad or a uint32 */ + (void)inet_aton(lyd_get_value(args->dnode), &cluster_id); bgp_cluster_id_set(bgp, &cluster_id); if (bgp_clear_star_soft_out(bgp->name, args->errmsg, args->errmsg_len)) @@ -1495,8 +1490,8 @@ int bgp_global_instance_type_view_modify(struct nb_cb_modify_args *args) * If the instance already exists - return the validation * error. */ - bgp = nb_running_get_entry_non_rec(args->dnode->parent->parent, - NULL, false); + bgp = nb_running_get_entry_non_rec( + lyd_parent(lyd_parent(args->dnode)), NULL, false); if (bgp) { snprintf(args->errmsg, args->errmsg_len, "Changing instance type is not allowed"); @@ -3560,21 +3555,6 @@ int bgp_neighbors_neighbor_local_as_no_prepend_modify( return NB_OK; } -int bgp_neighbors_neighbor_local_as_no_prepend_destroy( - struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - /* * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/neighbor/local-as/no-replace-as @@ -5576,21 +5556,6 @@ int bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_modify( return NB_OK; } -int bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_destroy( - struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - /* * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/unnumbered-neighbor/local-as/no-replace-as @@ -7493,21 +7458,6 @@ int bgp_peer_groups_peer_group_local_as_no_prepend_modify( return NB_OK; } -int bgp_peer_groups_peer_group_local_as_no_prepend_destroy( - struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - /* * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/peer-groups/peer-group/local-as/no-replace-as diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5b5f166e4be6..9be614ad62c0 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -4372,12 +4372,12 @@ DEFUN_YANG(neighbor_remote_as, snprintf(prgrp_xpath, sizeof(prgrp_xpath), FRR_BGP_PEER_GROUP_XPATH, argv[idx_peer]->arg, ""); - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, unnbr_xpath + 1)) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, unnbr_xpath + 1)) { strlcpy(base_xpath, unnbr_xpath, sizeof(base_xpath)); - } else if (yang_dnode_exists(vty->candidate_config->dnode, - "%s%s", VTY_CURR_XPATH, - prgrp_xpath + 1)) { + } else if (yang_dnode_existsf(vty->candidate_config->dnode, + "%s%s", VTY_CURR_XPATH, + prgrp_xpath + 1)) { snprintf(base_xpath, sizeof(base_xpath), FRR_BGP_PEER_GROUP_XPATH, argv[idx_peer]->arg, ""); @@ -4648,8 +4648,8 @@ DEFUN_YANG(no_neighbor, if (str2sockunion(argv[idx_peer]->arg, &su) == 0) { snprintf(num_xpath, sizeof(num_xpath), FRR_BGP_NEIGHBOR_NUM_XPATH, argv[idx_peer]->arg, ""); - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, num_xpath + 1)) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, num_xpath + 1)) { strlcpy(base_xpath, num_xpath, sizeof(base_xpath)); } } else { @@ -4659,12 +4659,12 @@ DEFUN_YANG(no_neighbor, snprintf(prgrp_xpath, sizeof(prgrp_xpath), FRR_BGP_PEER_GROUP_XPATH, argv[idx_peer]->arg, ""); - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, unnbr_xpath + 1)) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, unnbr_xpath + 1)) { strlcpy(base_xpath, unnbr_xpath, sizeof(base_xpath)); - } else if (yang_dnode_exists(vty->candidate_config->dnode, - "%s%s", VTY_CURR_XPATH, - prgrp_xpath + 1)) { + } else if (yang_dnode_existsf(vty->candidate_config->dnode, + "%s%s", VTY_CURR_XPATH, + prgrp_xpath + 1)) { strlcpy(base_xpath, prgrp_xpath, sizeof(base_xpath)); } else { vty_out(vty, @@ -4740,11 +4740,11 @@ DEFUN_YANG(no_neighbor_interface_peer_group_remote_as, snprintf(prgrp_xpath, sizeof(prgrp_xpath), FRR_BGP_PEER_GROUP_XPATH, argv[idx_peer]->arg, ""); - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, unnbr_xpath + 1)) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, unnbr_xpath + 1)) { strlcpy(base_xpath, unnbr_xpath, sizeof(base_xpath)); - } else if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, prgrp_xpath + 1)) { + } else if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, prgrp_xpath + 1)) { strlcpy(base_xpath, prgrp_xpath, sizeof(base_xpath)); } else { vty_out(vty, "%% Create the peer-group or interface first\n"); @@ -7036,8 +7036,8 @@ static int peer_and_group_lookup_nb(struct vty *vty, const char *peer_str, if (str2sockunion(peer_str, &su) == 0) { snprintf(num_xpath, sizeof(num_xpath), "/neighbors/neighbor[remote-address='%s']", peer_str); - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, num_xpath)) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, num_xpath)) { snprintf(base_xpath, xpath_len, FRR_BGP_NEIGHBOR_NUM_XPATH, peer_str, xpath ? xpath : ""); @@ -7056,14 +7056,14 @@ static int peer_and_group_lookup_nb(struct vty *vty, const char *peer_str, "/peer-groups/peer-group[peer-group-name='%s']", peer_str); - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, unnbr_xpath)) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, unnbr_xpath)) { snprintf(base_xpath, xpath_len, FRR_BGP_NEIGHBOR_UNNUM_XPATH, peer_str, xpath ? xpath : ""); - } else if (yang_dnode_exists(vty->candidate_config->dnode, - "%s%s", VTY_CURR_XPATH, - prgrp_xpath)) { + } else if (yang_dnode_existsf(vty->candidate_config->dnode, + "%s%s", VTY_CURR_XPATH, + prgrp_xpath)) { snprintf(base_xpath, xpath_len, FRR_BGP_PEER_GROUP_XPATH, peer_str, xpath ? xpath : ""); @@ -8085,7 +8085,7 @@ DEFPY_YANG( bgp_afi_safi_get_container_str(afi, safi)); if (!no) { - if (!yang_dnode_exists( + if (!yang_dnode_existsf( vty->candidate_config->dnode, "/frr-route-map:lib/route-map[name='%s']", rmap_str)) { diff --git a/bgpd/subdir.am b/bgpd/subdir.am index b54c41cabee9..53225192f2c7 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -214,8 +214,8 @@ bgpd_bgpd_SOURCES = bgpd/bgp_main.c bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c # RFPLDADD is set in bgpd/rfp-example/librfp/subdir.am -bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) $(UST_LIBS) -bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) $(UST_LIBS) +bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBYANG_LIBS) $(LIBCAP) $(LIBM) $(UST_LIBS) +bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBYANG_LIBS) $(LIBCAP) $(LIBM) $(UST_LIBS) bgpd_bgpd_snmp_la_SOURCES = bgpd/bgp_snmp.c bgpd/bgp_mplsvpn_snmp.c bgpd_bgpd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11 diff --git a/configure.ac b/configure.ac index c082a9e5273a..f84a3d3c5e1c 100644 --- a/configure.ac +++ b/configure.ac @@ -1866,8 +1866,8 @@ AC_SUBST([SNMP_CFLAGS]) dnl --------------- dnl libyang dnl --------------- -PKG_CHECK_MODULES([LIBYANG], [libyang >= 1.0.184 libyang < 2.0], , [ - AC_MSG_ERROR([libyang (>= 1.0.184) was not found on your system.]) +PKG_CHECK_MODULES([LIBYANG], [libyang >= 2.0.0], , [ + AC_MSG_ERROR([libyang (>= 2.0.0) was not found on your system.]) ]) ac_cflags_save="$CFLAGS" CFLAGS="$CFLAGS $LIBYANG_CFLAGS" diff --git a/debian/control b/debian/control index 7a08cbbdb020..0bbe99b312e4 100644 --- a/debian/control +++ b/debian/control @@ -16,14 +16,14 @@ Build-Depends: bison, libelf-dev, libjson-c-dev | libjson0-dev, libpam0g-dev | libpam-dev, - libpcre3-dev, + libpcre2-dev, libpython3-dev, libreadline-dev, librtr-dev , libsnmp-dev, libssh-dev , libsystemd-dev , - libyang-dev (>= 1.0.184), + libyang2-dev, lsb-base, pkg-config, python3, diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst index 5f82447d744a..a447f583097c 100644 --- a/doc/developer/building-libyang.rst +++ b/doc/developer/building-libyang.rst @@ -10,11 +10,12 @@ The FRR project builds some binary ``libyang`` packages. RPM packages are at our `RPM repository `_. DEB packages are available as CI artifacts `here -`_. +`_. .. warning:: - ``libyang`` version 1.0.184 or newer is required to build FRR. + ``libyang`` version 2.0.0 or newer is required to build FRR. Currently a tag + (``v2.0.0``) is used from the libyang2 branch. .. note:: @@ -26,31 +27,22 @@ DEB packages are available as CI artifacts `here Depending on your platform, you may also need to install the PCRE development package. Typically this is ``libpcre-dev`` or ``pcre-devel``. -.. note:: - - For Debian-based systems, the official ``libyang`` package requires recent - versions of ``swig`` (3.0.12) and ``debhelper`` (11) which are only - available in Debian buster (10). However, ``libyang`` packages built on - Debian buster can be installed on both Debian jessie (8) and Debian stretch - (9), as well as various Ubuntu systems. The ``python3-yang`` package will - not work, but the other packages (``libyang-dev`` is the one needed for FRR) - will. - **Option 2: Source Install** .. note:: Ensure that the `libyang build requirements - `_ + `_ are met before continuing. Usually this entails installing ``cmake`` and ``libpcre-dev`` or ``pcre-devel``. .. code-block:: console - git clone https://github.com/CESNET/libyang.git + git clone https://github.com/CESNET/libyang.git -b libyang2 cd libyang + git checkout v2.0.0 mkdir build; cd build - cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr \ -D CMAKE_BUILD_TYPE:String="Release" .. make sudo make install diff --git a/docker/ubuntu18-ci/Dockerfile b/docker/ubuntu18-ci/Dockerfile index f6fa9103811e..86fbe4f49ca3 100644 --- a/docker/ubuntu18-ci/Dockerfile +++ b/docker/ubuntu18-ci/Dockerfile @@ -26,19 +26,19 @@ RUN groupadd -r -g 92 frr && \ echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \ mkdir -p /home/frr && chown frr.frr /home/frr -#for libyang 1 -RUN apt-get install -y cmake libpcre3-dev +#for libyang 2 +RUN apt-get install -y cmake libpcre2-dev USER frr:frr # build and install libyang1 RUN cd && pwd && ls -al && \ - git clone https://github.com/CESNET/libyang.git && \ + git clone https://github.com/CESNET/libyang.git -b libyang2 && \ cd libyang && \ - git checkout v1.0.225 && \ + git checkout v2.0.0 && \ mkdir build; cd build && \ - cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \ - -D CMAKE_BUILD_TYPE:String="Release" .. && \ + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DCMAKE_BUILD_TYPE:String="Release" .. && \ make -j $(nproc) && \ sudo make install @@ -47,7 +47,7 @@ COPY --chown=frr:frr . /home/frr/frr/ RUN cd && ls -al && ls -al frr RUN cd ~/frr && \ - ./bootstrap.sh && \ + ./bootstrap.sh && \ ./configure \ --prefix=/usr \ --localstatedir=/var/run/frr \ diff --git a/docker/ubuntu20-ci/Dockerfile b/docker/ubuntu20-ci/Dockerfile index 0b08c2f278f8..ead5c56c5498 100644 --- a/docker/ubuntu20-ci/Dockerfile +++ b/docker/ubuntu20-ci/Dockerfile @@ -29,19 +29,19 @@ RUN groupadd -r -g 92 frr && \ echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \ mkdir -p /home/frr && chown frr.frr /home/frr -#for libyang 1 -RUN apt-get install -y cmake libpcre3-dev +#for libyang 2 +RUN apt-get install -y cmake libpcre2-dev USER frr:frr # build and install libyang1 RUN cd && pwd && ls -al && \ - git clone https://github.com/CESNET/libyang.git && \ + git clone https://github.com/CESNET/libyang.git -b libyang2 && \ cd libyang && \ - git checkout v1.0.225 && \ + git checkout v2.0.0 && \ mkdir build; cd build && \ - cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \ - -D CMAKE_BUILD_TYPE:String="Release" .. && \ + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DCMAKE_BUILD_TYPE:String="Release" .. && \ make -j $(nproc) && \ sudo make install @@ -50,7 +50,7 @@ COPY --chown=frr:frr . /home/frr/frr/ RUN cd && ls -al && ls -al frr RUN cd ~/frr && \ - ./bootstrap.sh && \ + ./bootstrap.sh && \ ./configure \ --prefix=/usr \ --localstatedir=/var/run/frr \ diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c index ae15e97d4ab4..cf3999b4573b 100644 --- a/eigrpd/eigrp_cli.c +++ b/eigrpd/eigrp_cli.c @@ -880,7 +880,7 @@ static int eigrp_write_interface(struct vty *vty) RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) { FOR_ALL_INTERFACES(vrf, ifp) { - dnode = yang_dnode_get( + dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifp->name, vrf->name); diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 2c51f21d77f2..2a197ab2b71b 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1306,7 +1306,7 @@ static int isis_interface_config_write(struct vty *vty) FOR_ALL_INTERFACES (vrf, ifp) { struct lyd_node *dnode; - dnode = yang_dnode_get( + dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifp->name, vrf->name); diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 14fa414c522b..5aea9f25d9b8 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -110,7 +110,7 @@ DEFPY_YANG(no_router_isis, no_router_isis_cmd, if (!vrf_name) vrf_name = VRF_DEFAULT_NAME; - if (!yang_dnode_exists( + if (!yang_dnode_existsf( vty->candidate_config->dnode, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, vrf_name)) { @@ -277,8 +277,8 @@ DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd, { const struct lyd_node *dnode; - dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-isisd:isis", VTY_CURR_XPATH); + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); if (!dnode) return CMD_SUCCESS; @@ -345,8 +345,8 @@ DEFPY_YANG(isis_bfd, { const struct lyd_node *dnode; - dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-isisd:isis", VTY_CURR_XPATH); + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); if (dnode == NULL) { vty_out(vty, "ISIS is not enabled on this circuit\n"); return CMD_SUCCESS; @@ -371,8 +371,8 @@ DEFPY_YANG(isis_bfd_profile, { const struct lyd_node *dnode; - dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-isisd:isis", VTY_CURR_XPATH); + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); if (dnode == NULL) { vty_out(vty, "ISIS is not enabled on this circuit\n"); return CMD_SUCCESS; @@ -3092,8 +3092,8 @@ DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd, { const struct lyd_node *dnode; - dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-isisd:isis", VTY_CURR_XPATH); + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); if (dnode == NULL) { vty_out(vty, "ISIS is not enabled on this circuit\n"); return CMD_SUCCESS; @@ -3123,8 +3123,8 @@ DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd, { const struct lyd_node *dnode; - dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-isisd:isis", VTY_CURR_XPATH); + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); if (dnode == NULL) { vty_out(vty, "ISIS is not enabled on this circuit\n"); return CMD_SUCCESS; @@ -3143,8 +3143,8 @@ DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd, { const struct lyd_node *dnode; - dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-isisd:isis", VTY_CURR_XPATH); + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); if (dnode == NULL) { vty_out(vty, "ISIS is not enabled on this circuit\n"); return CMD_SUCCESS; diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 87cd732e0bf8..68a4581a4652 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -2509,10 +2509,10 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args) if (args->event == NB_EV_VALIDATE) { /* libyang doesn't like relative paths across module boundaries */ - ifname = yang_dnode_get_string(args->dnode->parent->parent, - "./name"); - vrfname = yang_dnode_get_string(args->dnode->parent->parent, - "./vrf"); + ifname = yang_dnode_get_string( + lyd_parent(lyd_parent(args->dnode)), "./name"); + vrfname = yang_dnode_get_string( + lyd_parent(lyd_parent(args->dnode)), "./vrf"); vrf = vrf_lookup_by_name(vrfname); assert(vrf); ifp = if_lookup_by_name(ifname, vrf->vrf_id); @@ -2549,10 +2549,10 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args) case NB_EV_VALIDATE: /* libyang doesn't like relative paths across module boundaries */ - ifname = yang_dnode_get_string(args->dnode->parent->parent, - "./name"); - vrfname = yang_dnode_get_string(args->dnode->parent->parent, - "./vrf"); + ifname = yang_dnode_get_string( + lyd_parent(lyd_parent(args->dnode)), "./name"); + vrfname = yang_dnode_get_string( + lyd_parent(lyd_parent(args->dnode)), "./vrf"); vrf = vrf_lookup_by_name(vrfname); assert(vrf); ifp = if_lookup_by_name(ifname, vrf->vrf_id); @@ -3184,8 +3184,9 @@ int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args) switch (args->event) { case NB_EV_VALIDATE: - ifp = nb_running_get_entry(args->dnode->parent->parent->parent, - NULL, false); + ifp = nb_running_get_entry( + lyd_parent(lyd_parent(lyd_parent(args->dnode))), NULL, + false); if (ifp == NULL) return NB_ERR_VALIDATION; if (if_is_loopback(ifp)) { @@ -3239,8 +3240,10 @@ int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args) switch (args->event) { case NB_EV_VALIDATE: - ifp = nb_running_get_entry(args->dnode->parent->parent->parent, - NULL, false); + + ifp = nb_running_get_entry( + lyd_parent(lyd_parent(lyd_parent(args->dnode))), NULL, + false); if (ifp == NULL) return NB_ERR_VALIDATION; if (if_is_loopback(ifp)) { @@ -3283,8 +3286,9 @@ int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args) switch (args->event) { case NB_EV_VALIDATE: - ifp = nb_running_get_entry(args->dnode->parent->parent->parent, - NULL, false); + ifp = nb_running_get_entry( + lyd_parent(lyd_parent(lyd_parent(args->dnode))), NULL, + false); if (ifp == NULL) return NB_ERR_VALIDATION; if (if_is_loopback(ifp)) { diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index 2066e4c96dd0..6469b49262ba 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -54,7 +54,6 @@ int main(int argc, char **argv) vty_init(master, true); lib_cmd_init(); - yang_init(true); nb_init(master, NULL, 0, false); vty_stdio(vty_do_exit); diff --git a/lib/if.c b/lib/if.c index f8a693d8f305..de2af435f6a6 100644 --- a/lib/if.c +++ b/lib/if.c @@ -266,16 +266,16 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; - if_dnode = yang_dnode_get( + if_dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf", ifp->name, old_vrf->name); if (if_dnode) { - yang_dnode_get_path(if_dnode->parent, oldpath, + yang_dnode_get_path(lyd_parent(if_dnode), oldpath, sizeof(oldpath)); yang_dnode_change_leaf(if_dnode, vrf->name); - yang_dnode_get_path(if_dnode->parent, newpath, + yang_dnode_get_path(lyd_parent(if_dnode), newpath, sizeof(newpath)); nb_running_move_tree(oldpath, newpath); running_config->version++; diff --git a/lib/libfrr.c b/lib/libfrr.c index 970e82c0649c..0817182f7a46 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -765,16 +765,14 @@ struct thread_master *frr_init(void) log_ref_vty_init(); lib_error_init(); - yang_init(true); - - debug_init_cli(); - nb_init(master, di->yang_modules, di->n_yang_modules, true); if (nb_db_init() != NB_OK) flog_warn(EC_LIB_NB_DATABASE, "%s: failed to initialize northbound database", __func__); + debug_init_cli(); + return master; } diff --git a/lib/northbound.c b/lib/northbound.c index 34ad5dbfa962..3634fed04f3a 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -83,14 +83,14 @@ static int nb_transaction_process(enum nb_event event, char *errmsg, size_t errmsg_len); static void nb_transaction_apply_finish(struct nb_transaction *transaction, char *errmsg, size_t errmsg_len); -static int nb_oper_data_iter_node(const struct lys_node *snode, +static int nb_oper_data_iter_node(const struct lysc_node *snode, const char *xpath, const void *list_entry, const struct yang_list_keys *list_keys, struct yang_translator *translator, bool first, uint32_t flags, nb_oper_data_cb cb, void *arg); -static int nb_node_check_config_only(const struct lys_node *snode, void *arg) +static int nb_node_check_config_only(const struct lysc_node *snode, void *arg) { bool *config_only = arg; @@ -102,10 +102,10 @@ static int nb_node_check_config_only(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; } -static int nb_node_new_cb(const struct lys_node *snode, void *arg) +static int nb_node_new_cb(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node; - struct lys_node *sparent, *sparent_list; + struct lysc_node *sparent, *sparent_list; nb_node = XCALLOC(MTYPE_NB_NODE, sizeof(*nb_node)); yang_snode_get_path(snode, YANG_PATH_DATA, nb_node->xpath, @@ -129,10 +129,7 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg) SET_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY); } if (CHECK_FLAG(snode->nodetype, LYS_LIST)) { - struct lys_node_list *slist; - - slist = (struct lys_node_list *)snode; - if (slist->keys_size == 0) + if (yang_snode_num_keys(snode) == 0) SET_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST); } @@ -142,18 +139,18 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg) */ nb_node->snode = snode; assert(snode->priv == NULL); - lys_set_private(snode, nb_node); + ((struct lysc_node *)snode)->priv = nb_node; return YANG_ITER_CONTINUE; } -static int nb_node_del_cb(const struct lys_node *snode, void *arg) +static int nb_node_del_cb(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node; nb_node = snode->priv; if (nb_node) { - lys_set_private(snode, NULL); + ((struct lysc_node *)snode)->priv = NULL; XFREE(MTYPE_NB_NODE, nb_node); } @@ -170,15 +167,15 @@ void nb_nodes_delete(void) yang_snodes_iterate(NULL, nb_node_del_cb, 0, NULL); } -struct nb_node *nb_node_find(const char *xpath) +struct nb_node *nb_node_find(const char *path) { - const struct lys_node *snode; + const struct lysc_node *snode; /* - * Use libyang to find the schema node associated to the xpath and get + * Use libyang to find the schema node associated to the path and get * the northbound node from there (snode private pointer). */ - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, path, 0); if (!snode) return NULL; @@ -288,7 +285,7 @@ static unsigned int nb_node_validate_priority(const struct nb_node *nb_node) return 0; } -static int nb_node_validate(const struct lys_node *snode, void *arg) +static int nb_node_validate(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; unsigned int *errors = arg; @@ -339,7 +336,7 @@ int nb_config_merge(struct nb_config *config_dst, struct nb_config *config_src, { int ret; - ret = lyd_merge(config_dst->dnode, config_src->dnode, LYD_OPT_EXPLICIT); + ret = lyd_merge_tree(&config_dst->dnode, config_src->dnode, 0); if (ret != 0) flog_warn(EC_LIB_LIBYANG, "%s: lyd_merge() failed", __func__); @@ -451,7 +448,7 @@ static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq, switch (dnode->schema->nodetype) { case LYS_LEAF: case LYS_LEAFLIST: - if (lyd_wd_default((struct lyd_node_leaf_list *)dnode)) + if (lyd_is_default(dnode)) break; if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema)) @@ -470,7 +467,7 @@ static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq, dnode); /* Process child nodes recursively. */ - LY_TREE_FOR (dnode->child, child) { + LY_LIST_FOR (lyd_child(dnode), child) { nb_config_diff_created(child, seq, changes); } break; @@ -497,52 +494,142 @@ static void nb_config_diff_deleted(const struct lyd_node *dnode, uint32_t *seq, * do is to call the "destroy" callbacks of their child nodes * when applicable (i.e. optional nodes). */ - LY_TREE_FOR (dnode->child, child) { + LY_LIST_FOR (lyd_child(dnode), child) { nb_config_diff_deleted(child, seq, changes); } } } +static int nb_lyd_diff_get_op(const struct lyd_node *dnode) +{ + const struct lyd_meta *meta; + LY_LIST_FOR (dnode->meta, meta) { + if (strcmp(meta->name, "operation") + || strcmp(meta->annotation->module->name, "yang")) + continue; + return lyd_get_meta_value(meta)[0]; + } + return 'n'; +} + +static inline void nb_config_diff_dnode_log_path(const char *context, + const char *path, + const struct lyd_node *dnode) +{ + if (dnode->schema->nodetype & LYD_NODE_TERM) + zlog_debug("nb_config_diff: %s: %s: %s", context, path, + lyd_get_value(dnode)); + else + zlog_debug("nb_config_diff: %s: %s", context, path); +} + +static inline void nb_config_diff_dnode_log(const char *context, + const struct lyd_node *dnode) +{ + if (!dnode) { + zlog_debug("nb_config_diff: %s: NULL", context); + return; + } + + char *path = lyd_path(dnode, LYD_PATH_STD, NULL, 0); + nb_config_diff_dnode_log_path(context, path, dnode); + free(path); +} + /* Calculate the delta between two different configurations. */ static void nb_config_diff(const struct nb_config *config1, const struct nb_config *config2, struct nb_config_cbs *changes) { - struct lyd_difflist *diff; - uint32_t seq = 0; + struct lyd_node *diff = NULL; + const struct lyd_node *root, *dnode; + struct lyd_node *target; + int op; + LY_ERR err; + char *path; + +#if 0 /* Useful (but noisy) when debugging diff code, and for improving later \ + */ + if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) { + LY_LIST_FOR(config1->dnode, root) { + LYD_TREE_DFS_BEGIN(root, dnode) { + nb_config_diff_dnode_log("from", dnode); + LYD_TREE_DFS_END(root, dnode); + } + } + LY_LIST_FOR(config2->dnode, root) { + LYD_TREE_DFS_BEGIN(root, dnode) { + nb_config_diff_dnode_log("to", dnode); + LYD_TREE_DFS_END(root, dnode); + } + } + } +#endif - diff = lyd_diff(config1->dnode, config2->dnode, - LYD_DIFFOPT_WITHDEFAULTS); - assert(diff); + err = lyd_diff_siblings(config1->dnode, config2->dnode, + LYD_DIFF_DEFAULTS, &diff); + assert(!err); - for (int i = 0; diff->type[i] != LYD_DIFF_END; i++) { - LYD_DIFFTYPE type; - struct lyd_node *dnode; + if (diff && DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) + nb_config_diff_dnode_log("iterating diff", diff); - type = diff->type[i]; + uint32_t seq = 0; + LY_LIST_FOR (diff, root) { + LYD_TREE_DFS_BEGIN (root, dnode) { + op = nb_lyd_diff_get_op(dnode); + + path = lyd_path(dnode, LYD_PATH_STD, NULL, 0); + +#if 0 /* Useful (but noisy) when debugging diff code, and for improving later \ + */ + if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) { + char context[80]; + snprintf(context, sizeof(context), + "iterating diff: oper: %c seq: %u", op, seq); + nb_config_diff_dnode_log_path(context, path, dnode); + } +#endif + switch (op) { + case 'c': /* create */ + /* + * This is rather inefficient, but when we use + * dnode from the diff instead of the + * candidate config node we get failures when + * looking up default values, etc, based on + * the diff tree. + */ + target = yang_dnode_get(config2->dnode, path); + nb_config_diff_created(target, &seq, changes); + + /* Skip rest of sub-tree, move to next sibling + */ + LYD_TREE_DFS_continue = 1; + break; + case 'd': /* delete */ + target = yang_dnode_get(config1->dnode, path); + nb_config_diff_deleted(target, &seq, changes); - switch (type) { - case LYD_DIFF_CREATED: - dnode = diff->second[i]; - nb_config_diff_created(dnode, &seq, changes); - break; - case LYD_DIFF_DELETED: - dnode = diff->first[i]; - nb_config_diff_deleted(dnode, &seq, changes); - break; - case LYD_DIFF_CHANGED: - dnode = diff->second[i]; - nb_config_diff_add_change(changes, NB_OP_MODIFY, &seq, - dnode); - break; - case LYD_DIFF_MOVEDAFTER1: - case LYD_DIFF_MOVEDAFTER2: - default: - continue; + /* Skip rest of sub-tree, move to next sibling + */ + LYD_TREE_DFS_continue = 1; + break; + case 'r': /* replace */ + /* either moving an entry or changing a value */ + target = yang_dnode_get(config2->dnode, path); + assert(target); + nb_config_diff_add_change(changes, NB_OP_MODIFY, + &seq, target); + break; + case 'n': /* none */ + default: + break; + } + free(path); + LYD_TREE_DFS_END(root, dnode); } } - lyd_free_diff(diff); + lyd_free_tree(diff); } int nb_candidate_edit(struct nb_config *candidate, @@ -554,6 +641,7 @@ int nb_candidate_edit(struct nb_config *candidate, struct lyd_node *dnode, *dep_dnode; char xpath_edit[XPATH_MAXLEN]; char dep_xpath[XPATH_MAXLEN]; + LY_ERR err; /* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */ if (nb_node->snode->nodetype == LYS_LEAFLIST) @@ -565,11 +653,15 @@ int nb_candidate_edit(struct nb_config *candidate, switch (operation) { case NB_OP_CREATE: case NB_OP_MODIFY: - ly_errno = 0; - dnode = lyd_new_path(candidate->dnode, ly_native_ctx, - xpath_edit, (void *)data->value, 0, - LYD_PATH_OPT_UPDATE); - if (dnode) { + err = lyd_new_path(candidate->dnode, ly_native_ctx, xpath_edit, + (void *)data->value, LYD_NEW_PATH_UPDATE, + &dnode); + if (err) { + flog_warn(EC_LIB_LIBYANG, + "%s: lyd_new_path(%s) failed: %d", __func__, + xpath_edit, err); + return NB_ERR; + } else if (dnode) { /* * create dependency * @@ -581,22 +673,18 @@ int nb_candidate_edit(struct nb_config *candidate, nb_node->dep_cbs.get_dependency_xpath( dnode, dep_xpath); - ly_errno = 0; - dep_dnode = lyd_new_path(candidate->dnode, - ly_native_ctx, - dep_xpath, NULL, 0, - LYD_PATH_OPT_UPDATE); - if (!dep_dnode && ly_errno) { - flog_warn(EC_LIB_LIBYANG, - "%s: lyd_new_path(%s) failed", - __func__, dep_xpath); + err = lyd_new_path(candidate->dnode, + ly_native_ctx, dep_xpath, + NULL, LYD_NEW_PATH_UPDATE, + &dep_dnode); + if (err) { + flog_warn( + EC_LIB_LIBYANG, + "%s: lyd_new_path(%s) failed: %d", + __func__, dep_xpath, err); return NB_ERR; } } - } else if (ly_errno) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed", - __func__, xpath_edit); - return NB_ERR; } break; case NB_OP_DESTROY: @@ -613,9 +701,9 @@ int nb_candidate_edit(struct nb_config *candidate, dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath); if (dep_dnode) - lyd_free(dep_dnode); + lyd_free_tree(dep_dnode); } - lyd_free(dnode); + lyd_free_tree(dnode); break; case NB_OP_MOVE: /* TODO: update configuration. */ @@ -660,9 +748,8 @@ int nb_candidate_update(struct nb_config *candidate) static int nb_candidate_validate_yang(struct nb_config *candidate, char *errmsg, size_t errmsg_len) { - if (lyd_validate(&candidate->dnode, - LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_OPT_WHENAUTODEL, - ly_native_ctx) + if (lyd_validate_all(&candidate->dnode, ly_native_ctx, + LYD_VALIDATE_NO_STATE, NULL) != 0) { yang_print_errors(ly_native_ctx, errmsg, errmsg_len); return NB_ERR_VALIDATION; @@ -678,12 +765,12 @@ static int nb_candidate_validate_code(struct nb_context *context, char *errmsg, size_t errmsg_len) { struct nb_config_cb *cb; - struct lyd_node *root, *next, *child; + struct lyd_node *root, *child; int ret; /* First validate the candidate as a whole. */ - LY_TREE_FOR (candidate->dnode, root) { - LY_TREE_DFS_BEGIN (root, next, child) { + LY_LIST_FOR (candidate->dnode, root) { + LYD_TREE_DFS_BEGIN (root, child) { struct nb_node *nb_node; nb_node = child->schema->priv; @@ -696,7 +783,7 @@ static int nb_candidate_validate_code(struct nb_context *context, return NB_ERR_VALIDATION; next: - LY_TREE_DFS_END(root, next, child); + LYD_TREE_DFS_END(root, child); } } @@ -1439,7 +1526,7 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, if (change->cb.operation == NB_OP_DESTROY) { char xpath[XPATH_MAXLEN]; - dnode = dnode->parent; + dnode = lyd_parent(dnode); if (!dnode) break; @@ -1470,7 +1557,7 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, nb_apply_finish_cb_new(&cbs, nb_node, dnode); next: - dnode = dnode->parent; + dnode = lyd_parent(dnode); } } @@ -1487,16 +1574,16 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, } } -static int nb_oper_data_iter_children(const struct lys_node *snode, +static int nb_oper_data_iter_children(const struct lysc_node *snode, const char *xpath, const void *list_entry, const struct yang_list_keys *list_keys, struct yang_translator *translator, bool first, uint32_t flags, nb_oper_data_cb cb, void *arg) { - struct lys_node *child; + const struct lysc_node *child; - LY_TREE_FOR (snode->child, child) { + LY_LIST_FOR (lysc_node_child(snode), child) { int ret; ret = nb_oper_data_iter_node(child, xpath, list_entry, @@ -1521,7 +1608,7 @@ static int nb_oper_data_iter_leaf(const struct nb_node *nb_node, return NB_OK; /* Ignore list keys. */ - if (lys_is_key((struct lys_node_leaf *)nb_node->snode, NULL)) + if (lysc_is_key(nb_node->snode)) return NB_OK; data = nb_callback_get_elem(nb_node, xpath, list_entry); @@ -1605,7 +1692,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, struct yang_translator *translator, uint32_t flags, nb_oper_data_cb cb, void *arg) { - struct lys_node_list *slist = (struct lys_node_list *)nb_node->snode; + const struct lysc_node *snode = nb_node->snode; const void *list_entry = NULL; uint32_t position = 1; @@ -1614,6 +1701,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, /* Iterate over all list entries. */ do { + const struct lysc_node_leaf *skey; struct yang_list_keys list_keys; char xpath[XPATH_MAXLEN * 2]; int ret; @@ -1638,12 +1726,16 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, /* Build XPath of the list entry. */ strlcpy(xpath, xpath_list, sizeof(xpath)); - for (unsigned int i = 0; i < list_keys.num; i++) { + unsigned int i = 0; + LY_FOR_KEYS (snode, skey) { + assert(i < list_keys.num); snprintf(xpath + strlen(xpath), sizeof(xpath) - strlen(xpath), - "[%s='%s']", slist->keys[i]->name, + "[%s='%s']", skey->name, list_keys.key[i]); + i++; } + assert(i == list_keys.num); } else { /* * Keyless list - build XPath using a positional index. @@ -1664,7 +1756,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, return NB_OK; } -static int nb_oper_data_iter_node(const struct lys_node *snode, +static int nb_oper_data_iter_node(const struct lysc_node *snode, const char *xpath_parent, const void *list_entry, const struct yang_list_keys *list_keys, @@ -1683,18 +1775,16 @@ static int nb_oper_data_iter_node(const struct lys_node *snode, /* Update XPath. */ strlcpy(xpath, xpath_parent, sizeof(xpath)); if (!first && snode->nodetype != LYS_USES) { - struct lys_node *parent; + struct lysc_node *parent; /* Get the real parent. */ parent = snode->parent; - while (parent && parent->nodetype == LYS_USES) - parent = parent->parent; /* * When necessary, include the namespace of the augmenting * module. */ - if (parent && parent->nodetype == LYS_AUGMENT) + if (parent && parent->module != snode->module) snprintf(xpath + strlen(xpath), sizeof(xpath) - strlen(xpath), "/%s:%s", snode->module->name, snode->name); @@ -1769,12 +1859,14 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, * Create a data tree from the XPath so that we can parse the keys of * all YANG lists (if any). */ - ly_errno = 0; - dnode = lyd_new_path(NULL, ly_native_ctx, xpath, NULL, 0, - LYD_PATH_OPT_UPDATE | LYD_PATH_OPT_NOPARENTRET); - if (!dnode) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", - __func__); + + LY_ERR err = lyd_new_path(NULL, ly_native_ctx, xpath, NULL, + LYD_NEW_PATH_UPDATE, &dnode); + if (err || !dnode) { + const char *errmsg = + err ? ly_errmsg(ly_native_ctx) : "node not found"; + flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed %s", + __func__, errmsg); return NB_ERR; } @@ -1782,8 +1874,8 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, * Create a linked list to sort the data nodes starting from the root. */ list_dnodes = list_new(); - for (dn = dnode; dn; dn = dn->parent) { - if (dn->schema->nodetype != LYS_LIST || !dn->child) + for (dn = dnode; dn; dn = lyd_parent(dn)) { + if (dn->schema->nodetype != LYS_LIST || !lyd_child(dn)) continue; listnode_add_head(list_dnodes, dn); } @@ -1798,18 +1890,16 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, /* Obtain the list entry keys. */ memset(&list_keys, 0, sizeof(list_keys)); - LY_TREE_FOR (dn->child, child) { - if (!lys_is_key((struct lys_node_leaf *)child->schema, - NULL)) - continue; + LY_LIST_FOR (lyd_child(dn), child) { + if (!lysc_is_key(child->schema)) + break; strlcpy(list_keys.key[n], yang_dnode_get_string(child, NULL), sizeof(list_keys.key[n])); n++; } list_keys.num = n; - if (list_keys.num - != ((struct lys_node_list *)dn->schema)->keys_size) { + if (list_keys.num != yang_snode_num_keys(dn->schema)) { list_delete(&list_dnodes); yang_dnode_free(dnode); return NB_ERR_NOT_FOUND; @@ -1837,7 +1927,7 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, } /* If a list entry was given, iterate over that list entry only. */ - if (dnode->schema->nodetype == LYS_LIST && dnode->child) + if (dnode->schema->nodetype == LYS_LIST && lyd_child(dnode)) ret = nb_oper_data_iter_children( nb_node->snode, xpath, list_entry, &list_keys, translator, true, flags, cb, arg); @@ -1853,11 +1943,11 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, } bool nb_operation_is_valid(enum nb_operation operation, - const struct lys_node *snode) + const struct lysc_node *snode) { struct nb_node *nb_node = snode->priv; - struct lys_node_container *scontainer; - struct lys_node_leaf *sleaf; + struct lysc_node_container *scontainer; + struct lysc_node_leaf *sleaf; switch (operation) { case NB_OP_CREATE: @@ -1866,13 +1956,13 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base != LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype != LY_TYPE_EMPTY) return false; break; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return false; break; case LYS_LIST: @@ -1888,12 +1978,12 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base == LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype == LY_TYPE_EMPTY) return false; /* List keys can't be modified. */ - if (lys_is_key(sleaf, NULL)) + if (lysc_is_key(sleaf)) return false; break; default: @@ -1906,10 +1996,10 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; + sleaf = (struct lysc_node_leaf *)snode; /* List keys can't be deleted. */ - if (lys_is_key(sleaf, NULL)) + if (lysc_is_key(sleaf)) return false; /* @@ -1925,8 +2015,8 @@ bool nb_operation_is_valid(enum nb_operation operation, return false; break; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return false; break; case LYS_LIST: @@ -1943,7 +2033,7 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LIST: case LYS_LEAFLIST: - if (!CHECK_FLAG(snode->flags, LYS_USERORDERED)) + if (!CHECK_FLAG(snode->flags, LYS_ORDBY_USER)) return false; break; default: @@ -1964,8 +2054,8 @@ bool nb_operation_is_valid(enum nb_operation operation, case LYS_LEAFLIST: break; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return false; break; default: @@ -2114,7 +2204,7 @@ static void *nb_running_unset_entry_helper(const struct lyd_node *dnode) /* Unset user pointers from the child nodes. */ if (CHECK_FLAG(dnode->schema->nodetype, LYS_LIST | LYS_CONTAINER)) { - LY_TREE_FOR (dnode->child, child) { + LY_LIST_FOR (lyd_child(dnode), child) { (void)nb_running_unset_entry_helper(child); } } @@ -2156,7 +2246,7 @@ static void *nb_running_get_entry_worker(const struct lyd_node *dnode, rec_flag = rec_search; - dnode = dnode->parent; + dnode = lyd_parent(dnode); } if (!abort_if_not_found) @@ -2312,27 +2402,42 @@ void nb_validate_callbacks(void) } } -void nb_load_module(const struct frr_yang_module_info *module_info) -{ - struct yang_module *module; - - DEBUGD(&nb_dbg_events, "northbound: loading %s.yang", - module_info->name); - - module = yang_module_load(module_info->name); - yang_snodes_iterate(module->info, nb_node_new_cb, 0, NULL); - nb_load_callbacks(module_info); -} void nb_init(struct thread_master *tm, const struct frr_yang_module_info *const modules[], size_t nmodules, bool db_enabled) { + struct yang_module *loaded[nmodules], **loadedp = loaded; + bool explicit_compile; + + /* + * Currently using this explicit compile feature in libyang2 leads to + * incorrect behavior in FRR. The functionality suppresses the compiling + * of modules until they have all been loaded into the context. This + * avoids multiple recompiles of the same modules as they are + * imported/augmented etc. + */ + explicit_compile = false; + nb_db_enabled = db_enabled; + yang_init(true, explicit_compile); + /* Load YANG modules and their corresponding northbound callbacks. */ - for (size_t i = 0; i < nmodules; i++) - nb_load_module(modules[i]); + for (size_t i = 0; i < nmodules; i++) { + DEBUGD(&nb_dbg_events, "northbound: loading %s.yang", + modules[i]->name); + *loadedp++ = yang_module_load(modules[i]->name); + } + + if (explicit_compile) + yang_init_loading_complete(); + + /* Initialize the compiled nodes with northbound data */ + for (size_t i = 0; i < nmodules; i++) { + yang_snodes_iterate(loaded[i]->info, nb_node_new_cb, 0, NULL); + nb_load_callbacks(modules[i]); + } /* Validate northbound callbacks. */ nb_validate_callbacks(); diff --git a/lib/northbound.h b/lib/northbound.h index 417ecc81ea06..7ccab5cad5e5 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -537,7 +537,7 @@ struct nb_dependency_callbacks { */ struct nb_node { /* Back pointer to the libyang schema node. */ - const struct lys_node *snode; + const struct lysc_node *snode; /* Data path of this YANG node. */ char xpath[XPATH_MAXLEN]; @@ -685,7 +685,7 @@ struct nb_transaction { }; /* Callback function used by nb_oper_data_iterate(). */ -typedef int (*nb_oper_data_cb)(const struct lys_node *snode, +typedef int (*nb_oper_data_cb)(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg); @@ -1114,7 +1114,7 @@ extern int nb_oper_data_iterate(const char *xpath, * true if the operation is valid, false otherwise. */ extern bool nb_operation_is_valid(enum nb_operation operation, - const struct lys_node *snode); + const struct lysc_node *snode); /* * Send a YANG notification. This is a no-op unless the 'nb_notification_send' @@ -1284,15 +1284,6 @@ extern const char *nb_client_name(enum nb_client client); */ void nb_validate_callbacks(void); -/* - * Load a YANG module with its corresponding northbound callbacks. - * - * module_info - * Pointer to structure containing the module name and its northbound - * callbacks. - */ -void nb_load_module(const struct frr_yang_module_info *module_info); - /* * Initialize the northbound layer. Should be called only once during the * daemon initialization process. diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 81e30bce4941..d291a1f24d85 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -448,6 +448,7 @@ static int nb_cli_candidate_load_file(struct vty *vty, struct ly_ctx *ly_ctx; int ly_format; char buf[BUFSIZ]; + LY_ERR err; switch (format) { case NB_CFG_FMT_CMDS: @@ -465,8 +466,10 @@ static int nb_cli_candidate_load_file(struct vty *vty, ly_format = (format == NB_CFG_FMT_JSON) ? LYD_JSON : LYD_XML; ly_ctx = translator ? translator->ly_ctx : ly_native_ctx; - dnode = lyd_parse_path(ly_ctx, path, ly_format, LYD_OPT_EDIT); - if (!dnode) { + err = lyd_parse_data_path(ly_ctx, path, ly_format, + LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, + 0, &dnode); + if (err || !dnode) { flog_warn(EC_LIB_LIBYANG, "%s: lyd_parse_path() failed", __func__); vty_out(vty, "%% Failed to load configuration:\n\n"); @@ -536,8 +539,6 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults) if (config->dnode == NULL) return; - lyd_schema_sort(config->dnode, 1); - /* * Call lyd_validate() only to create default child nodes, ignoring * any possible validation error. This doesn't need to be done when @@ -545,9 +546,8 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults) * validated. */ if (config != running_config) - (void)lyd_validate(&config->dnode, - LYD_OPT_CONFIG | LYD_OPT_WHENAUTODEL, - ly_native_ctx); + (void)lyd_validate_all(&config->dnode, ly_native_ctx, + LYD_VALIDATE_NO_STATE, NULL); } static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root, @@ -559,7 +559,7 @@ static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root, struct list *sort_list; void *data; - LY_TREE_FOR (root->child, child) { + LY_LIST_FOR (lyd_child(root), child) { nb_node = child->schema->priv; /* @@ -634,8 +634,9 @@ static void nb_cli_show_config_cmds(struct vty *vty, struct nb_config *config, vty_out(vty, "frr version %s\n", FRR_VER_SHORT); vty_out(vty, "frr defaults %s\n", frr_defaults_profile()); - LY_TREE_FOR (config->dnode, root) + LY_LIST_FOR (config->dnode, root) { nb_cli_show_dnode_cmds(vty, root, with_defaults); + } vty_out(vty, "!\n"); vty_out(vty, "end\n"); @@ -660,11 +661,11 @@ static int nb_cli_show_config_libyang(struct vty *vty, LYD_FORMAT format, return CMD_WARNING; } - SET_FLAG(options, LYP_FORMAT | LYP_WITHSIBLINGS); + SET_FLAG(options, LYD_PRINT_WITHSIBLINGS); if (with_defaults) - SET_FLAG(options, LYP_WD_ALL); + SET_FLAG(options, LYD_PRINT_WD_ALL); else - SET_FLAG(options, LYP_WD_TRIM); + SET_FLAG(options, LYD_PRINT_WD_TRIM); if (lyd_print_mem(&strp, dnode, format, options) == 0 && strp) { vty_out(vty, "%s", strp); @@ -1401,7 +1402,7 @@ DEFPY (show_config_transaction, #endif /* HAVE_CONFIG_ROLLBACKS */ } -static int nb_cli_oper_data_cb(const struct lys_node *snode, +static int nb_cli_oper_data_cb(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg) { @@ -1427,12 +1428,12 @@ static int nb_cli_oper_data_cb(const struct lys_node *snode, } else ly_ctx = ly_native_ctx; - ly_errno = 0; - dnode = lyd_new_path(dnode, ly_ctx, data->xpath, (void *)data->value, 0, - LYD_PATH_OPT_UPDATE); - if (!dnode && ly_errno) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", - __func__); + LY_ERR err = + lyd_new_path(dnode, ly_ctx, data->xpath, (void *)data->value, + LYD_NEW_PATH_UPDATE, &dnode); + if (err) { + flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed: %s", + __func__, data->xpath, ly_errmsg(ly_native_ctx)); goto error; } @@ -1494,11 +1495,11 @@ DEFPY (show_yang_operational_data, yang_dnode_free(dnode); return CMD_WARNING; } - lyd_validate(&dnode, LYD_OPT_GET, ly_ctx); + (void)lyd_validate_all(&dnode, ly_ctx, 0, NULL); /* Display the data. */ if (lyd_print_mem(&strp, dnode, format, - LYP_FORMAT | LYP_WITHSIBLINGS | LYP_WD_ALL) + LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL) != 0 || !strp) { vty_out(vty, "%% Failed to display operational data.\n"); @@ -1551,13 +1552,12 @@ DEFPY (show_yang_module, snprintf(flags, sizeof(flags), "%c%c", module->implemented ? 'I' : ' ', - (module->deviated == 1) ? 'D' : ' '); + LY_ARRAY_COUNT(module->deviated_by) ? 'D' : ' '); ttable_add_row(tt, "%s|%s|%s|%s|%s", module->name, - (module->version == 2) ? "1.1" : "1.0", - (module->rev_size > 0) ? module->rev[0].date - : "-", - flags, module->ns); + (module->parsed->version == 2) ? "1.1" : "1.0", + module->revision ? module->revision : "-", flags, + module->ns); } /* Dump the generated table. */ @@ -1577,21 +1577,21 @@ DEFPY (show_yang_module, return CMD_SUCCESS; } -DEFPY (show_yang_module_detail, - show_yang_module_detail_cmd, - "show yang module\ +DEFPY(show_yang_module_detail, show_yang_module_detail_cmd, + "show yang module\ [module-translator WORD$translator_family]\ - WORD$module_name ", - SHOW_STR - "YANG information\n" - "Show loaded modules\n" - "YANG module translator\n" - "YANG module translator\n" - "Module name\n" - "Display summary information about the module\n" - "Display module in the tree (RFC 8340) format\n" - "Display module in the YANG format\n" - "Display module in the YIN format\n") + WORD$module_name ", + SHOW_STR + "YANG information\n" + "Show loaded modules\n" + "YANG module translator\n" + "YANG module translator\n" + "Module name\n" + "Display compiled module in YANG format\n" + "Display summary information about the module\n" + "Display module in the tree (RFC 8340) format\n" + "Display module in the YANG format\n" + "Display module in the YIN format\n") { struct ly_ctx *ly_ctx; struct yang_translator *translator = NULL; @@ -1610,7 +1610,7 @@ DEFPY (show_yang_module_detail, } else ly_ctx = ly_native_ctx; - module = ly_ctx_get_module(ly_ctx, module_name, NULL, 0); + module = ly_ctx_get_module_latest(ly_ctx, module_name); if (!module) { vty_out(vty, "%% Module \"%s\" not found\n", module_name); return CMD_WARNING; @@ -1620,12 +1620,17 @@ DEFPY (show_yang_module_detail, format = LYS_OUT_YANG; else if (yin) format = LYS_OUT_YIN; + else if (compiled) + format = LYS_OUT_YANG_COMPILED; else if (tree) format = LYS_OUT_TREE; - else - format = LYS_OUT_INFO; + else { + vty_out(vty, + "%% libyang v2 does not currently support summary\n"); + return CMD_WARNING; + } - if (lys_print_mem(&strp, module, format, NULL, 0, 0) == 0) { + if (lys_print_mem(&strp, module, format, 0) == 0) { vty_out(vty, "%s\n", strp); free(strp); } else { diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 403537e0432d..76af494e30b3 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -515,7 +515,7 @@ static int frr_confd_init_cdb(void) /* Subscribe to all loaded YANG data modules. */ confd_spoints = list_new(); RB_FOREACH (module, yang_modules, &yang_modules) { - struct lys_node *snode; + struct lysc_node *snode; module->confd_hash = confd_str2hash(module->info->ns); if (module->confd_hash == 0) { @@ -531,7 +531,7 @@ static int frr_confd_init_cdb(void) * entire YANG module. So we have to find the top level * nodes ourselves and subscribe to their paths. */ - LY_TREE_FOR (module->info->data, snode) { + LY_LIST_FOR (module->info->data, snode) { struct nb_node *nb_node; int *spoint; int ret; @@ -762,7 +762,7 @@ static int frr_confd_data_get_object(struct confd_trans_ctx *tctx, confd_hkeypath_t *kp) { struct nb_node *nb_node; - const struct lys_node *child; + const struct lysc_node *child; char xpath[XPATH_MAXLEN]; char xpath_child[XPATH_MAXLEN * 2]; struct list *elements; @@ -789,7 +789,7 @@ static int frr_confd_data_get_object(struct confd_trans_ctx *tctx, elements = yang_data_list_new(); /* Loop through list child nodes. */ - LY_TREE_FOR (nb_node->snode->child, child) { + LY_LIST_FOR (lysc_node_child(nb_node->snode), child) { struct nb_node *nb_node_child = child->priv; confd_value_t *v; @@ -869,7 +869,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx, memset(objects, 0, sizeof(objects)); for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) { struct confd_next_object *object; - struct lys_node *child; + struct lysc_node *child; struct yang_data *data; size_t nvalues = 0; @@ -919,7 +919,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx, } /* Loop through list child nodes. */ - LY_TREE_FOR (nb_node->snode->child, child) { + LY_LIST_FOR (lysc_node_child(nb_node->snode), child) { struct nb_node *nb_node_child = child->priv; char xpath_child[XPATH_MAXLEN * 2]; confd_value_t *v; @@ -1187,7 +1187,7 @@ static int frr_confd_dp_read(struct thread *thread) return 0; } -static int frr_confd_subscribe_state(const struct lys_node *snode, void *arg) +static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; struct confd_data_cbs *data_cbs = arg; @@ -1391,7 +1391,7 @@ static void frr_confd_cli_init(void) /* ------------ Main ------------ */ -static int frr_confd_calculate_snode_hash(const struct lys_node *snode, +static int frr_confd_calculate_snode_hash(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 58f4e4251643..dc2d29c11df7 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -1109,7 +1109,7 @@ class NorthboundImpl } } - static int get_oper_data_cb(const struct lys_node *snode, + static int get_oper_data_cb(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg) { diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 63fd40f8d3a6..7c463dd61f0e 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -48,10 +48,10 @@ static int frr_sr_finish(void); static int yang_data_frr2sr(struct yang_data *frr_data, sr_val_t *sr_data) { struct nb_node *nb_node; - const struct lys_node *snode; - struct lys_node_container *scontainer; - struct lys_node_leaf *sleaf; - struct lys_node_leaflist *sleaflist; + const struct lysc_node *snode; + struct lysc_node_container *scontainer; + struct lysc_node_leaf *sleaf; + struct lysc_node_leaflist *sleaflist; LY_DATA_TYPE type; sr_val_set_xpath(sr_data, frr_data->xpath); @@ -67,8 +67,8 @@ static int yang_data_frr2sr(struct yang_data *frr_data, sr_val_t *sr_data) snode = nb_node->snode; switch (snode->nodetype) { case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return -1; sr_data->type = SR_CONTAINER_PRESENCE_T; return 0; @@ -76,11 +76,11 @@ static int yang_data_frr2sr(struct yang_data *frr_data, sr_val_t *sr_data) sr_data->type = SR_LIST_T; return 0; case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; + sleaf = (struct lysc_node_leaf *)snode; type = sleaf->type.base; break; case LYS_LEAFLIST: - sleaflist = (struct lys_node_leaflist *)snode; + sleaflist = (struct lysc_node_leaflist *)snode; type = sleaflist->type.base; break; default: @@ -359,7 +359,7 @@ static int frr_sr_config_change_cb(sr_session_ctx_t *session, } } -static int frr_sr_state_data_iter_cb(const struct lys_node *snode, +static int frr_sr_state_data_iter_cb(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg) { @@ -562,7 +562,7 @@ static void frr_sr_subscribe_config(struct yang_module *module) sr_strerror(ret)); } -static int frr_sr_subscribe_state(const struct lys_node *snode, void *arg) +static int frr_sr_subscribe_state(const struct lysc_node *snode, void *arg) { struct yang_module *module = arg; struct nb_node *nb_node; @@ -591,7 +591,7 @@ static int frr_sr_subscribe_state(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; } -static int frr_sr_subscribe_rpc(const struct lys_node *snode, void *arg) +static int frr_sr_subscribe_rpc(const struct lysc_node *snode, void *arg) { struct yang_module *module = arg; struct nb_node *nb_node; diff --git a/lib/vrf.c b/lib/vrf.c index 7888d435f5b0..b6a53839cf29 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -1214,7 +1214,8 @@ const struct frr_yang_module_info frr_vrf_info = { .get_next = lib_vrf_get_next, .get_keys = lib_vrf_get_keys, .lookup_entry = lib_vrf_lookup_entry, - } + }, + .priority = NB_DFLT_PRIORITY - 2, }, { .xpath = "/frr-vrf:lib/vrf/state/id", diff --git a/lib/yang.c b/lib/yang.c index df3b07fb090c..1e241f049ed1 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -25,8 +25,6 @@ #include "yang_translator.h" #include "northbound.h" -#include - DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module"); DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure"); @@ -42,14 +40,12 @@ void yang_module_embed(struct yang_module_embed *embed) embedupd = &embed->next; } -static const char *yang_module_imp_clb(const char *mod_name, - const char *mod_rev, - const char *submod_name, - const char *submod_rev, - void *user_data, - LYS_INFORMAT *format, - void (**free_module_data) - (void *, void*)) +static LY_ERR yang_module_imp_clb(const char *mod_name, const char *mod_rev, + const char *submod_name, + const char *submod_rev, void *user_data, + LYS_INFORMAT *format, + const char **module_data, + void (**free_module_data)(void *, void *)) { struct yang_module_embed *e; @@ -69,15 +65,17 @@ static const char *yang_module_imp_clb(const char *mod_name, } *format = e->format; - return e->data; + *module_data = e->data; + return LY_SUCCESS; } - flog_warn( - EC_LIB_YANG_MODULE_LOAD, + /* We get here for indirect modules like ietf-inet-types */ + zlog_debug( "YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file", mod_name, mod_rev ? mod_rev : "*", submod_name ? submod_name : "*", submod_rev ? submod_rev : "*"); - return NULL; + + return LY_ENOTFOUND; } /* clang-format off */ @@ -111,7 +109,8 @@ struct yang_module *yang_module_load(const char *module_name) struct yang_module *module; const struct lys_module *module_info; - module_info = ly_ctx_load_module(ly_native_ctx, module_name, NULL); + module_info = + ly_ctx_load_module(ly_native_ctx, module_name, NULL, NULL); if (!module_info) { flog_err(EC_LIB_YANG_MODULE_LOAD, "%s: failed to load data model: %s", __func__, @@ -147,62 +146,39 @@ struct yang_module *yang_module_find(const char *module_name) return RB_FIND(yang_modules, &yang_modules, &s); } -int yang_snodes_iterate_subtree(const struct lys_node *snode, +int yang_snodes_iterate_subtree(const struct lysc_node *snode, const struct lys_module *module, yang_iterate_cb cb, uint16_t flags, void *arg) { - struct lys_node *child; + const struct lysc_node *child; int ret = YANG_ITER_CONTINUE; if (module && snode->module != module) goto next; - if (CHECK_FLAG(flags, YANG_ITER_FILTER_IMPLICIT)) { - switch (snode->nodetype) { - case LYS_CASE: - case LYS_INPUT: - case LYS_OUTPUT: - if (CHECK_FLAG(snode->flags, LYS_IMPLICIT)) - goto next; - break; - default: - break; - } - } - switch (snode->nodetype) { case LYS_CONTAINER: if (CHECK_FLAG(flags, YANG_ITER_FILTER_NPCONTAINERS)) { - struct lys_node_container *scontainer; - - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + if (!CHECK_FLAG(snode->flags, LYS_PRESENCE)) goto next; } break; case LYS_LEAF: if (CHECK_FLAG(flags, YANG_ITER_FILTER_LIST_KEYS)) { - struct lys_node_leaf *sleaf; - /* Ignore list keys. */ - sleaf = (struct lys_node_leaf *)snode; - if (lys_is_key(sleaf, NULL)) + if (lysc_is_key(snode)) goto next; } break; - case LYS_GROUPING: - /* Return since we're not interested in the grouping subtree. */ - return YANG_ITER_CONTINUE; - case LYS_USES: - case LYS_AUGMENT: - /* Always ignore nodes of these types. */ - goto next; case LYS_INPUT: case LYS_OUTPUT: if (CHECK_FLAG(flags, YANG_ITER_FILTER_INPUT_OUTPUT)) goto next; break; default: + assert(snode->nodetype != LYS_AUGMENT + && snode->nodetype != LYS_GROUPING + && snode->nodetype != LYS_USES); break; } @@ -212,19 +188,17 @@ int yang_snodes_iterate_subtree(const struct lys_node *snode, next: /* - * YANG leafs and leaf-lists can't have child nodes, and trying to - * access snode->child is undefined behavior. + * YANG leafs and leaf-lists can't have child nodes. */ if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST)) return YANG_ITER_CONTINUE; - LY_TREE_FOR (snode->child, child) { + LY_LIST_FOR (lysc_node_child(snode), child) { ret = yang_snodes_iterate_subtree(child, module, cb, flags, arg); if (ret == YANG_ITER_STOP) return ret; } - return ret; } @@ -237,12 +211,24 @@ int yang_snodes_iterate(const struct lys_module *module, yang_iterate_cb cb, idx = ly_ctx_internal_modules_count(ly_native_ctx); while ((module_iter = ly_ctx_get_module_iter(ly_native_ctx, &idx))) { - struct lys_node *snode; + struct lysc_node *snode; if (!module_iter->implemented) continue; - LY_TREE_FOR (module_iter->data, snode) { + LY_LIST_FOR (module_iter->compiled->data, snode) { + ret = yang_snodes_iterate_subtree(snode, module, cb, + flags, arg); + if (ret == YANG_ITER_STOP) + return ret; + } + LY_LIST_FOR (&module_iter->compiled->rpcs->node, snode) { + ret = yang_snodes_iterate_subtree(snode, module, cb, + flags, arg); + if (ret == YANG_ITER_STOP) + return ret; + } + LY_LIST_FOR (&module_iter->compiled->notifs->node, snode) { ret = yang_snodes_iterate_subtree(snode, module, cb, flags, arg); if (ret == YANG_ITER_STOP) @@ -253,38 +239,32 @@ int yang_snodes_iterate(const struct lys_module *module, yang_iterate_cb cb, return ret; } -void yang_snode_get_path(const struct lys_node *snode, enum yang_path_type type, - char *xpath, size_t xpath_len) +void yang_snode_get_path(const struct lysc_node *snode, + enum yang_path_type type, char *xpath, + size_t xpath_len) { - char *xpath_ptr; - switch (type) { case YANG_PATH_SCHEMA: - xpath_ptr = lys_path(snode, 0); + (void)lysc_path(snode, LYSC_PATH_LOG, xpath, xpath_len); break; case YANG_PATH_DATA: - xpath_ptr = lys_data_path(snode); + (void)lysc_path(snode, LYSC_PATH_DATA, xpath, xpath_len); break; default: flog_err(EC_LIB_DEVELOPMENT, "%s: unknown yang path type: %u", __func__, type); exit(1); } - strlcpy(xpath, xpath_ptr, xpath_len); - free(xpath_ptr); } -struct lys_node *yang_snode_real_parent(const struct lys_node *snode) +struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode) { - struct lys_node *parent = snode->parent; + struct lysc_node *parent = snode->parent; while (parent) { - struct lys_node_container *scontainer; - switch (parent->nodetype) { case LYS_CONTAINER: - scontainer = (struct lys_node_container *)parent; - if (scontainer->presence) + if (CHECK_FLAG(parent->flags, LYS_PRESENCE)) return parent; break; case LYS_LIST: @@ -298,9 +278,9 @@ struct lys_node *yang_snode_real_parent(const struct lys_node *snode) return NULL; } -struct lys_node *yang_snode_parent_list(const struct lys_node *snode) +struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode) { - struct lys_node *parent = snode->parent; + struct lysc_node *parent = snode->parent; while (parent) { switch (parent->nodetype) { @@ -315,14 +295,14 @@ struct lys_node *yang_snode_parent_list(const struct lys_node *snode) return NULL; } -bool yang_snode_is_typeless_data(const struct lys_node *snode) +bool yang_snode_is_typeless_data(const struct lysc_node *snode) { - struct lys_node_leaf *sleaf; + const struct lysc_node_leaf *sleaf; switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base == LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype == LY_TYPE_EMPTY) return true; return false; case LYS_LEAFLIST: @@ -332,16 +312,16 @@ bool yang_snode_is_typeless_data(const struct lys_node *snode) } } -const char *yang_snode_get_default(const struct lys_node *snode) +const char *yang_snode_get_default(const struct lysc_node *snode) { - struct lys_node_leaf *sleaf; + const struct lysc_node_leaf *sleaf; switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - - /* NOTE: this might be null. */ - return sleaf->dflt; + sleaf = (const struct lysc_node_leaf *)snode; + return sleaf->dflt ? lyd_value_get_canonical(sleaf->module->ctx, + sleaf->dflt) + : NULL; case LYS_LEAFLIST: /* TODO: check leaf-list default values */ return NULL; @@ -350,29 +330,40 @@ const char *yang_snode_get_default(const struct lys_node *snode) } } -const struct lys_type *yang_snode_get_type(const struct lys_node *snode) +const struct lysc_type *yang_snode_get_type(const struct lysc_node *snode) { - struct lys_node_leaf *sleaf = (struct lys_node_leaf *)snode; - struct lys_type *type; + struct lysc_node_leaf *sleaf = (struct lysc_node_leaf *)snode; + struct lysc_type *type; if (!CHECK_FLAG(sleaf->nodetype, LYS_LEAF | LYS_LEAFLIST)) return NULL; - type = &sleaf->type; - while (type->base == LY_TYPE_LEAFREF) - type = &type->info.lref.target->type; + type = sleaf->type; + while (type->basetype == LY_TYPE_LEAFREF) + type = ((struct lysc_type_leafref *)type)->realtype; return type; } +unsigned int yang_snode_num_keys(const struct lysc_node *snode) +{ + const struct lysc_node_leaf *skey; + uint count = 0; + + if (!CHECK_FLAG(snode->nodetype, LYS_LIST)) + return 0; + + /* Walk list of children */ + LY_FOR_KEYS (snode, skey) { + count++; + } + return count; +} + void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath, size_t xpath_len) { - char *xpath_ptr; - - xpath_ptr = lyd_path(dnode); - strlcpy(xpath, xpath_ptr, xpath_len); - free(xpath_ptr); + lyd_path(dnode, LYD_PATH_STD, xpath, xpath_len); } const char *yang_dnode_get_schema_name(const struct lyd_node *dnode, @@ -398,55 +389,78 @@ const char *yang_dnode_get_schema_name(const struct lyd_node *dnode, return dnode->schema->name; } -struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, - const char *xpath_fmt, ...) +struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, const char *xpath) { - va_list ap; - char xpath[XPATH_MAXLEN]; - struct ly_set *set; + struct ly_set *set = NULL; struct lyd_node *dnode_ret = NULL; - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); + /* + * XXX a lot of the code uses this for style I guess. It shouldn't, as + * it adds to the xpath parsing complexity in libyang. + */ + if (xpath[0] == '.' && xpath[1] == '/') + xpath += 2; - set = lyd_find_path(dnode, xpath); - assert(set); - if (set->number == 0) + if (lyd_find_xpath(dnode, xpath, &set)) { + assert(0); /* XXX replicates old libyang1 base code */ + goto exit; + } + if (set->count == 0) goto exit; - if (set->number > 1) { + if (set->count > 1) { flog_warn(EC_LIB_YANG_DNODE_NOT_FOUND, "%s: found %u elements (expected 0 or 1) [xpath %s]", - __func__, set->number, xpath); + __func__, set->count, xpath); goto exit; } - dnode_ret = set->set.d[0]; + dnode_ret = set->dnodes[0]; exit: - ly_set_free(set); + ly_set_free(set, NULL); return dnode_ret; } -bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath_fmt, ...) +struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode, + const char *xpath_fmt, ...) { va_list ap; char xpath[XPATH_MAXLEN]; - struct ly_set *set; - bool found; va_start(ap, xpath_fmt); vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); va_end(ap); - set = lyd_find_path(dnode, xpath); - assert(set); - found = (set->number > 0); - ly_set_free(set); + return yang_dnode_get(dnode, xpath); +} + +bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath) +{ + struct ly_set *set = NULL; + bool exists = false; - return found; + if (xpath[0] == '.' && xpath[1] == '/') + xpath += 2; + if (lyd_find_xpath(dnode, xpath, &set)) + return false; + exists = set->count > 0; + ly_set_free(set, NULL); + return exists; +} + +bool yang_dnode_existsf(const struct lyd_node *dnode, const char *xpath_fmt, + ...) +{ + va_list ap; + char xpath[XPATH_MAXLEN]; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + return yang_dnode_exists(dnode, xpath); } void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, @@ -461,52 +475,42 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); va_end(ap); - set = lyd_find_path(dnode, xpath); - assert(set); - for (unsigned int i = 0; i < set->number; i++) { + if (lyd_find_xpath(dnode, xpath, &set)) { + assert(0); /* XXX libyang2: ly1 code asserted success */ + return; + } + for (unsigned int i = 0; i < set->count; i++) { int ret; - dnode = set->set.d[i]; - ret = (*cb)(dnode, arg); + ret = (*cb)(set->dnodes[i], arg); if (ret == YANG_ITER_STOP) break; } - ly_set_free(set); + ly_set_free(set, NULL); } -bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath_fmt, - ...) +bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath) { - struct lys_node *snode; - struct lys_node_leaf *sleaf; - struct lys_node_container *scontainer; - - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); + const struct lysc_node *snode; + struct lysc_node_leaf *sleaf; + if (xpath) dnode = yang_dnode_get(dnode, xpath); - } assert(dnode); snode = dnode->schema; switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base == LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype == LY_TYPE_EMPTY) return false; - return lyd_wd_default((struct lyd_node_leaf_list *)dnode); + return lyd_is_default(dnode); case LYS_LEAFLIST: /* TODO: check leaf-list default values */ return false; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (scontainer->presence) + if (CHECK_FLAG(snode->flags, LYS_PRESENCE)) return false; return true; default: @@ -514,24 +518,39 @@ bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath_fmt, } } -bool yang_dnode_is_default_recursive(const struct lyd_node *dnode) +bool yang_dnode_is_defaultf(const struct lyd_node *dnode, const char *xpath_fmt, + ...) { - struct lys_node *snode; - struct lyd_node *root, *next, *dnode_iter; - - snode = dnode->schema; - if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST)) + if (!xpath_fmt) return yang_dnode_is_default(dnode, NULL); + else { + va_list ap; + char xpath[XPATH_MAXLEN]; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + return yang_dnode_is_default(dnode, xpath); + } +} + +bool yang_dnode_is_default_recursive(const struct lyd_node *dnode) +{ + struct lyd_node *root, *dnode_iter; if (!yang_dnode_is_default(dnode, NULL)) return false; - LY_TREE_FOR (dnode->child, root) { - LY_TREE_DFS_BEGIN (root, next, dnode_iter) { + if (CHECK_FLAG(dnode->schema->nodetype, LYS_LEAF | LYS_LEAFLIST)) + return true; + + LY_LIST_FOR (lyd_child(dnode), root) { + LYD_TREE_DFS_BEGIN (root, dnode_iter) { if (!yang_dnode_is_default(dnode_iter, NULL)) return false; - LY_TREE_DFS_END(root, next, dnode_iter); + LYD_TREE_DFS_END(root, dnode_iter); } } @@ -541,21 +560,15 @@ bool yang_dnode_is_default_recursive(const struct lyd_node *dnode) void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value) { assert(dnode->schema->nodetype == LYS_LEAF); - lyd_change_leaf((struct lyd_node_leaf_list *)dnode, value); + lyd_change_term(dnode, value); } struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool config_only) { - struct lyd_node *dnode; - int options; - - if (config_only) - options = LYD_OPT_CONFIG; - else - options = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB; + struct lyd_node *dnode = NULL; + int options = config_only ? LYD_VALIDATE_NO_STATE : 0; - dnode = NULL; - if (lyd_validate(&dnode, options, ly_ctx) != 0) { + if (lyd_validate_all(&dnode, ly_ctx, options, NULL) != 0) { /* Should never happen. */ flog_err(EC_LIB_LIBYANG, "%s: lyd_validate() failed", __func__); exit(1); @@ -566,14 +579,18 @@ struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool config_only) struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode) { - return lyd_dup_withsiblings(dnode, 1); + struct lyd_node *dup = NULL; + LY_ERR err; + err = lyd_dup_siblings(dnode, NULL, LYD_DUP_RECURSIVE, &dup); + assert(!err); + return dup; } void yang_dnode_free(struct lyd_node *dnode) { while (dnode->parent) - dnode = dnode->parent; - lyd_free_withsiblings(dnode); + dnode = lyd_parent(dnode); + lyd_free_all(dnode); } struct yang_data *yang_data_new(const char *xpath, const char *value) @@ -679,18 +696,19 @@ const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len) void yang_debugging_set(bool enable) { if (enable) { - ly_verb(LY_LLDBG); - ly_verb_dbg(0xFF); + ly_log_level(LY_LLDBG); + ly_log_dbg_groups(0xFF); } else { - ly_verb(LY_LLERR); - ly_verb_dbg(0); + ly_log_level(LY_LLERR); + ly_log_dbg_groups(0); } } -struct ly_ctx *yang_ctx_new_setup(bool embedded_modules) +struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) { - struct ly_ctx *ctx; + struct ly_ctx *ctx = NULL; const char *yang_models_path = YANG_MODELS_PATH; + LY_ERR err; if (access(yang_models_path, R_OK | X_OK)) { yang_models_path = NULL; @@ -703,8 +721,11 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules) YANG_MODELS_PATH); } - ctx = ly_ctx_new(yang_models_path, LY_CTX_DISABLE_SEARCHDIR_CWD); - if (!ctx) + uint options = LY_CTX_NO_YANGLIBRARY | LY_CTX_DISABLE_SEARCHDIR_CWD; + if (explicit_compile) + options |= LY_CTX_EXPLICIT_COMPILE; + err = ly_ctx_new(yang_models_path, options, &ctx); + if (err) return NULL; if (embedded_modules) @@ -713,14 +734,14 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules) return ctx; } -void yang_init(bool embedded_modules) +void yang_init(bool embedded_modules, bool defer_compile) { /* Initialize libyang global parameters that affect all containers. */ ly_set_log_clb(ly_log_cb, 1); ly_log_options(LY_LOLOG | LY_LOSTORE); /* Initialize libyang container for native models. */ - ly_native_ctx = yang_ctx_new_setup(embedded_modules); + ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile); if (!ly_native_ctx) { flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); exit(1); @@ -729,6 +750,17 @@ void yang_init(bool embedded_modules) yang_translator_init(); } +void yang_init_loading_complete(void) +{ + /* Compile everything */ + if (ly_ctx_compile(ly_native_ctx) != LY_SUCCESS) { + flog_err(EC_LIB_YANG_MODULE_LOAD, + "%s: failed to compile loaded modules: %s", __func__, + ly_errmsg(ly_native_ctx)); + exit(1); + } +} + void yang_terminate(void) { struct yang_module *module; @@ -748,7 +780,7 @@ void yang_terminate(void) XFREE(MTYPE_YANG_MODULE, module); } - ly_ctx_destroy(ly_native_ctx, NULL); + ly_ctx_destroy(ly_native_ctx); } const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, @@ -767,7 +799,7 @@ const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, break; } - orig_dnode = orig_dnode->parent; + orig_dnode = lyd_parent(orig_dnode); } return NULL; @@ -788,17 +820,17 @@ bool yang_is_last_list_dnode(const struct lyd_node *dnode) bool yang_is_last_level_dnode(const struct lyd_node *dnode) { const struct lyd_node *parent; - const struct lys_node_list *snode; const struct lyd_node *key_leaf; uint8_t keys_size; switch (dnode->schema->nodetype) { case LYS_LIST: assert(dnode->parent); - parent = dnode->parent; - snode = (struct lys_node_list *)parent->schema; + parent = lyd_parent(dnode); + uint snode_num_keys = yang_snode_num_keys(parent->schema); + /* XXX libyang2: q: really don't understand this code. */ key_leaf = dnode->prev; - for (keys_size = 1; keys_size < snode->keys_size; keys_size++) + for (keys_size = 1; keys_size < snode_num_keys; keys_size++) key_leaf = key_leaf->prev; if (key_leaf->prev == dnode) return true; @@ -812,13 +844,11 @@ bool yang_is_last_level_dnode(const struct lyd_node *dnode) return false; } - const struct lyd_node * yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) { bool parent = true; const struct lyd_node *node; - const struct lys_node_container *snode; node = dnode; if (node->schema->nodetype != LYS_LIST) @@ -827,13 +857,11 @@ yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) while (parent) { switch (node->schema->nodetype) { case LYS_CONTAINER: - snode = (struct lys_node_container *)node->schema; - if ((!snode->presence) - && yang_is_last_level_dnode(node)) { + if (!CHECK_FLAG(node->schema->flags, LYS_PRESENCE)) { if (node->parent && (node->parent->schema->module == dnode->schema->module)) - node = node->parent; + node = lyd_parent(node); else parent = false; } else @@ -845,7 +873,7 @@ yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) if (node->parent && (node->parent->schema->module == dnode->schema->module)) - node = node->parent; + node = lyd_parent(node); else parent = false; } else @@ -867,7 +895,7 @@ uint32_t yang_get_list_pos(const struct lyd_node *node) uint32_t yang_get_list_elements_count(const struct lyd_node *node) { unsigned int count; - struct lys_node *schema; + const struct lysc_node *schema; if (!node || ((node->schema->nodetype != LYS_LIST) @@ -884,11 +912,3 @@ uint32_t yang_get_list_elements_count(const struct lyd_node *node) } while (node); return count; } - - -const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode) -{ - if (dnode) - return dnode->child; - return NULL; -} diff --git a/lib/yang.h b/lib/yang.h index b8bf07ee7e16..d4517f969aea 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -99,13 +99,10 @@ enum yang_iter_flags { /* Filter RPC input/output nodes. */ YANG_ITER_FILTER_INPUT_OUTPUT = (1<<2), - - /* Filter implicitely created nodes. */ - YANG_ITER_FILTER_IMPLICIT = (1<<3), }; /* Callback used by the yang_snodes_iterate_*() family of functions. */ -typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg); +typedef int (*yang_iterate_cb)(const struct lysc_node *snode, void *arg); /* Callback used by the yang_dnode_iterate() function. */ typedef int (*yang_dnode_iter_cb)(const struct lyd_node *dnode, void *arg); @@ -180,7 +177,7 @@ extern void yang_module_embed(struct yang_module_embed *embed); * Returns: * The return value of the last called callback. */ -extern int yang_snodes_iterate_subtree(const struct lys_node *snode, +extern int yang_snodes_iterate_subtree(const struct lysc_node *snode, const struct lys_module *module, yang_iterate_cb cb, uint16_t flags, void *arg); @@ -222,7 +219,7 @@ extern int yang_snodes_iterate(const struct lys_module *module, * xpath_len * Size of the xpath buffer. */ -extern void yang_snode_get_path(const struct lys_node *snode, +extern void yang_snode_get_path(const struct lysc_node *snode, enum yang_path_type type, char *xpath, size_t xpath_len); @@ -236,7 +233,7 @@ extern void yang_snode_get_path(const struct lys_node *snode, * Returns: * The parent libyang schema node if found, or NULL if not found. */ -extern struct lys_node *yang_snode_real_parent(const struct lys_node *snode); +extern struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode); /* * Find first parent schema node which is a list. @@ -247,7 +244,7 @@ extern struct lys_node *yang_snode_real_parent(const struct lys_node *snode); * Returns: * The parent libyang schema node (list) if found, or NULL if not found. */ -extern struct lys_node *yang_snode_parent_list(const struct lys_node *snode); +extern struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode); /* * Check if the libyang schema node represents typeless data (e.g. containers, @@ -259,7 +256,7 @@ extern struct lys_node *yang_snode_parent_list(const struct lys_node *snode); * Returns: * true if the schema node represents typeless data, false otherwise. */ -extern bool yang_snode_is_typeless_data(const struct lys_node *snode); +extern bool yang_snode_is_typeless_data(const struct lysc_node *snode); /* * Get the default value associated to a YANG leaf or leaf-list. @@ -270,7 +267,7 @@ extern bool yang_snode_is_typeless_data(const struct lys_node *snode); * Returns: * The default value if it exists, NULL otherwise. */ -extern const char *yang_snode_get_default(const struct lys_node *snode); +extern const char *yang_snode_get_default(const struct lysc_node *snode); /* * Get the type structure of a leaf of leaf-list. If the type is a leafref, the @@ -283,7 +280,27 @@ extern const char *yang_snode_get_default(const struct lys_node *snode); * The found type if the schema node represents a leaf or a leaf-list, NULL * otherwise. */ -extern const struct lys_type *yang_snode_get_type(const struct lys_node *snode); +extern const struct lysc_type * +yang_snode_get_type(const struct lysc_node *snode); + +/* + * Get the number of key nodes for the given list. + * + * snode + * libyang (LYS_LIST) schema node to operate on. + * + * Returns: + * The number of key LYS_LEAFs as children of this list node. + */ +extern unsigned int yang_snode_num_keys(const struct lysc_node *snode); + +#define LY_FOR_KEYS(snode, skey) \ + for ((skey) = (const struct lysc_node_leaf *)lysc_node_child((snode)); \ + (skey); (skey) = (const struct lysc_node_leaf *)((skey)->next)) \ + if (!lysc_is_key(skey)) { \ + break; \ + } else + /* * Build data path of the data node. @@ -322,14 +339,49 @@ extern const char *yang_dnode_get_schema_name(const struct lyd_node *dnode, * dnode * Base libyang data node to operate on. * - * xpath_fmt - * XPath expression (absolute or relative). + * xpath + * Limited XPath (absolute or relative) string. See Path in libyang + * documentation for restrictions. * * Returns: * The libyang data node if found, or NULL if not found. */ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, - const char *xpath_fmt, ...); + const char *xpath); + +/* + * Find a libyang data node by its YANG data path. + * + * dnode + * Base libyang data node to operate on. + * + * xpath_fmt + * Limited XPath (absolute or relative) format string. See Path in libyang + * documentation for restrictions. + * + * ... + * any parameters for xpath_fmt. + * + * Returns: + * The libyang data node if found, or NULL if not found. + */ +extern struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode, + const char *path_fmt, ...); + +/* + * Check if a libyang data node exists. + * + * dnode + * Base libyang data node to operate on. + * + * xpath + * Limited XPath (absolute or relative) string. See Path in libyang + * documentation for restrictions. + * + * Returns: + * true if a libyang data node was found, false otherwise. + */ +extern bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath); /* * Check if a libyang data node exists. @@ -338,13 +390,17 @@ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, * Base libyang data node to operate on. * * xpath_fmt - * XPath expression (absolute or relative). + * Limited XPath (absolute or relative) format string. See Path in + * libyang documentation for restrictions. + * + * ... + * any parameters for xpath_fmt. * * Returns: - * true if the libyang data node was found, false otherwise. + * true if a libyang data node was found, false otherwise. */ -extern bool yang_dnode_exists(const struct lyd_node *dnode, - const char *xpath_fmt, ...); +extern bool yang_dnode_existsf(const struct lyd_node *dnode, + const char *xpath_fmt, ...); /* * Iterate over all libyang data nodes that satisfy an XPath query. @@ -360,6 +416,9 @@ extern bool yang_dnode_exists(const struct lyd_node *dnode, * * xpath_fmt * XPath expression (absolute or relative). + * + * ... + * any parameters for xpath_fmt. */ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, const struct lyd_node *dnode, const char *xpath_fmt, @@ -372,7 +431,7 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, * dnode * Base libyang data node to operate on. * - * xpath_fmt + * xpath * Optional XPath expression (absolute or relative) to specify a different * data node to operate on in the same data tree. * @@ -380,7 +439,27 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, * true if the data node contains the default value, false otherwise. */ extern bool yang_dnode_is_default(const struct lyd_node *dnode, - const char *xpath_fmt, ...); + const char *xpath); + +/* + * Check if the libyang data node contains a default value. Non-presence + * containers are assumed to always contain a default value. + * + * dnode + * Base libyang data node to operate on. + * + * xpath + * Optional limited XPath (absolute or relative) format string. See Path in + * libyang documentation for restrictions. + * + * ... + * any parameters for xpath_fmt. + * + * Returns: + * true if the data node contains the default value, false otherwise. + */ +extern bool yang_dnode_is_defaultf(const struct lyd_node *dnode, + const char *xpath_fmt, ...); /* * Check if the libyang data node and all of its children contain default @@ -437,7 +516,8 @@ extern struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode); * Delete a libyang data node. * * dnode - * Pointer to the libyang data node that is going to be deleted. + * Pointer to the libyang data node that is going to be deleted along with + * the entire tree it belongs to. */ extern void yang_dnode_free(struct lyd_node *dnode); @@ -493,8 +573,13 @@ extern struct yang_data *yang_data_list_find(const struct list *list, * * embedded_modules * Specify whether libyang should attempt to look for embedded YANG modules. + * + * explicit_compile + * True if the caller will later call ly_ctx_compile to compile all loaded + * modules at once. */ -extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules); +extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, + bool explicit_compile); /* * Enable or disable libyang verbose debugging. @@ -528,8 +613,16 @@ extern const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, * * embedded_modules * Specify whether libyang should attempt to look for embedded YANG modules. + * defer_compile + * Hold off on compiling modules until yang_init_loading_complete is called. */ -extern void yang_init(bool embedded_modules); +extern void yang_init(bool embedded_modules, bool defer_compile); + +/* + * Should be called after yang_init and all yang_module_load()s have been done, + * compiles all modules loaded into the yang context. + */ +extern void yang_init_loading_complete(void); /* * Finish the YANG subsystem gracefully. Should be called only when the daemon @@ -583,10 +676,6 @@ extern uint32_t yang_get_list_pos(const struct lyd_node *node); */ extern uint32_t yang_get_list_elements_count(const struct lyd_node *node); - -/* To get the immediate child of a dnode */ -const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode); - /* API to check if the given node is last node in the list */ bool yang_is_last_list_dnode(const struct lyd_node *dnode); diff --git a/lib/yang_translator.c b/lib/yang_translator.c index 5b1d96f24c64..d562e4d29ea5 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -93,7 +93,7 @@ yang_mapping_lookup(const struct yang_translator *translator, int dir, } static void yang_mapping_add(struct yang_translator *translator, int dir, - const struct lys_node *snode, + const struct lysc_node *snode, const char *xpath_from_fmt, const char *xpath_to_fmt) { @@ -135,13 +135,15 @@ struct yang_translator *yang_translator_load(const char *path) struct lyd_node *dnode; struct ly_set *set; struct listnode *ln; + LY_ERR err; /* Load module translator (JSON file). */ - dnode = lyd_parse_path(ly_translator_ctx, path, LYD_JSON, - LYD_OPT_CONFIG); - if (!dnode) { + err = lyd_parse_data_path(ly_translator_ctx, path, LYD_JSON, + LYD_PARSE_NO_STATE, LYD_VALIDATE_NO_STATE, + &dnode); + if (err) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, - "%s: lyd_parse_path() failed", __func__); + "%s: lyd_parse_path() failed: %d", __func__, err); return NULL; } dnode = yang_dnode_get(dnode, @@ -171,89 +173,94 @@ struct yang_translator *yang_translator_load(const char *path) RB_INSERT(yang_translators, &yang_translators, translator); /* Initialize the translator libyang context. */ - translator->ly_ctx = yang_ctx_new_setup(false); + translator->ly_ctx = yang_ctx_new_setup(false, false); if (!translator->ly_ctx) { flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); goto error; } - /* Load modules and deviations. */ - set = lyd_find_path(dnode, "./module"); - assert(set); - for (size_t i = 0; i < set->number; i++) { + /* Load modules */ + if (lyd_find_xpath(dnode, "./module", &set) != LY_SUCCESS) + assert(0); /* XXX libyang2: old ly1 code asserted success */ + + for (size_t i = 0; i < set->count; i++) { const char *module_name; tmodule = XCALLOC(MTYPE_YANG_TRANSLATOR_MODULE, sizeof(*tmodule)); - module_name = yang_dnode_get_string(set->set.d[i], "./name"); + module_name = yang_dnode_get_string(set->dnodes[i], "./name"); tmodule->module = ly_ctx_load_module(translator->ly_ctx, - module_name, NULL); + module_name, NULL, NULL); if (!tmodule->module) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: failed to load module: %s", __func__, module_name); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } + } - module_name = - yang_dnode_get_string(set->set.d[i], "./deviations"); - tmodule->deviations = ly_ctx_load_module(translator->ly_ctx, - module_name, NULL); + /* Count nodes in modules. */ + for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { + tmodule->nodes_before_deviations = + yang_module_nodes_count(tmodule->module); + } + + /* Load the deviations and count nodes again */ + for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { + const char *module_name = tmodule->module->name; + tmodule->deviations = ly_ctx_load_module( + translator->ly_ctx, module_name, NULL, NULL); if (!tmodule->deviations) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: failed to load module: %s", __func__, module_name); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } - lys_set_disabled(tmodule->deviations); - listnode_add(translator->modules, tmodule); + tmodule->nodes_after_deviations = + yang_module_nodes_count(tmodule->module); } - ly_set_free(set); + ly_set_free(set, NULL); /* Calculate the coverage. */ for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { - tmodule->nodes_before_deviations = - yang_module_nodes_count(tmodule->module); - - lys_set_enabled(tmodule->deviations); - - tmodule->nodes_after_deviations = - yang_module_nodes_count(tmodule->module); tmodule->coverage = ((double)tmodule->nodes_after_deviations / (double)tmodule->nodes_before_deviations) * 100; } /* Load mappings. */ - set = lyd_find_path(dnode, "./module/mappings"); - assert(set); - for (size_t i = 0; i < set->number; i++) { + if (lyd_find_xpath(dnode, "./module/mappings", &set) != LY_SUCCESS) + assert(0); /* XXX libyang2: old ly1 code asserted success */ + for (size_t i = 0; i < set->count; i++) { const char *xpath_custom, *xpath_native; - const struct lys_node *snode_custom, *snode_native; + const struct lysc_node *snode_custom, *snode_native; + + xpath_custom = + yang_dnode_get_string(set->dnodes[i], "./custom"); - xpath_custom = yang_dnode_get_string(set->set.d[i], "./custom"); - snode_custom = ly_ctx_get_node(translator->ly_ctx, NULL, - xpath_custom, 0); + snode_custom = lys_find_path(translator->ly_ctx, NULL, + xpath_custom, 0); if (!snode_custom) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: unknown data path: %s", __func__, xpath_custom); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } - xpath_native = yang_dnode_get_string(set->set.d[i], "./native"); + xpath_native = + yang_dnode_get_string(set->dnodes[i], "./native"); snode_native = - ly_ctx_get_node(ly_native_ctx, NULL, xpath_native, 0); + lys_find_path(ly_native_ctx, NULL, xpath_native, 0); if (!snode_native) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: unknown data path: %s", __func__, xpath_native); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } @@ -262,7 +269,7 @@ struct yang_translator *yang_translator_load(const char *path) yang_mapping_add(translator, YANG_TRANSLATE_FROM_NATIVE, snode_native, xpath_native, xpath_custom); } - ly_set_free(set); + ly_set_free(set, NULL); /* Validate mappings. */ if (yang_translator_validate(translator) != 0) @@ -290,7 +297,7 @@ void yang_translator_unload(struct yang_translator *translator) hash_clean(translator->mappings[i], yang_mapping_hash_free); translator->modules->del = (void (*)(void *))yang_tmodule_delete; list_delete(&translator->modules); - ly_ctx_destroy(translator->ly_ctx, NULL); + ly_ctx_destroy(translator->ly_ctx); RB_REMOVE(yang_translators, &yang_translators, translator); XFREE(MTYPE_YANG_TRANSLATOR, translator); } @@ -308,7 +315,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir, char *xpath, size_t xpath_len) { struct ly_ctx *ly_ctx; - const struct lys_node *snode; + const struct lysc_node *snode; struct yang_mapping_node *mapping; char xpath_canonical[XPATH_MAXLEN]; char keys[4][LIST_MAXKEYLEN]; @@ -319,7 +326,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir, else ly_ctx = ly_native_ctx; - snode = ly_ctx_get_node(ly_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_ctx, NULL, xpath, 0); if (!snode) { flog_warn(EC_LIB_YANG_TRANSLATION_ERROR, "%s: unknown data path: %s", __func__, xpath); @@ -352,7 +359,7 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir, { struct ly_ctx *ly_ctx; struct lyd_node *new; - struct lyd_node *root, *next, *dnode_iter; + struct lyd_node *root, *dnode_iter; /* Create new libyang data node to hold the translated data. */ if (dir == YANG_TRANSLATE_TO_NATIVE) @@ -362,8 +369,8 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir, new = yang_dnode_new(ly_ctx, false); /* Iterate over all nodes from the data tree. */ - LY_TREE_FOR (*dnode, root) { - LY_TREE_DFS_BEGIN (root, next, dnode_iter) { + LY_LIST_FOR (*dnode, root) { + LYD_TREE_DFS_BEGIN (root, dnode_iter) { char xpath[XPATH_MAXLEN]; enum yang_translate_result ret; @@ -380,19 +387,17 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir, } /* Create new node in the tree of translated data. */ - ly_errno = 0; - if (!lyd_new_path(new, ly_ctx, xpath, - (void *)yang_dnode_get_string( - dnode_iter, NULL), - 0, LYD_PATH_OPT_UPDATE) - && ly_errno) { + if (lyd_new_path(new, ly_ctx, xpath, + (void *)yang_dnode_get_string( + dnode_iter, NULL), + LYD_NEW_PATH_UPDATE, NULL)) { flog_err(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", __func__); goto error; } next: - LY_TREE_DFS_END(root, next, dnode_iter); + LYD_TREE_DFS_END(root, dnode_iter); } } @@ -413,13 +418,13 @@ struct translator_validate_args { unsigned int errors; }; -static int yang_translator_validate_cb(const struct lys_node *snode_custom, +static int yang_translator_validate_cb(const struct lysc_node *snode_custom, void *arg) { struct translator_validate_args *args = arg; struct yang_mapping_node *mapping; - const struct lys_node *snode_native; - const struct lys_type *stype_custom, *stype_native; + const struct lysc_node *snode_native; + const struct lysc_type *stype_custom, *stype_native; char xpath[XPATH_MAXLEN]; yang_snode_get_path(snode_custom, YANG_PATH_DATA, xpath, sizeof(xpath)); @@ -433,14 +438,14 @@ static int yang_translator_validate_cb(const struct lys_node *snode_custom, } snode_native = - ly_ctx_get_node(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0); + lys_find_path(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0); assert(snode_native); /* Check if the YANG types are compatible. */ stype_custom = yang_snode_get_type(snode_custom); stype_native = yang_snode_get_type(snode_native); if (stype_custom && stype_native) { - if (stype_custom->base != stype_native->base) { + if (stype_custom->basetype != stype_native->basetype) { flog_warn( EC_LIB_YANG_TRANSLATOR_LOAD, "%s: YANG types are incompatible (xpath: \"%s\")", @@ -486,7 +491,7 @@ static unsigned int yang_translator_validate(struct yang_translator *translator) return args.errors; } -static int yang_module_nodes_count_cb(const struct lys_node *snode, void *arg) +static int yang_module_nodes_count_cb(const struct lysc_node *snode, void *arg) { unsigned int *total = arg; @@ -511,14 +516,14 @@ static unsigned int yang_module_nodes_count(const struct lys_module *module) void yang_translator_init(void) { - ly_translator_ctx = yang_ctx_new_setup(true); + ly_translator_ctx = yang_ctx_new_setup(true, false); if (!ly_translator_ctx) { flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); exit(1); } if (!ly_ctx_load_module(ly_translator_ctx, "frr-module-translator", - NULL)) { + NULL, NULL)) { flog_err( EC_LIB_YANG_MODULE_LOAD, "%s: failed to load the \"frr-module-translator\" module", @@ -536,5 +541,5 @@ void yang_translator_terminate(void) yang_translator_unload(translator); } - ly_ctx_destroy(ly_translator_ctx, NULL); + ly_ctx_destroy(ly_translator_ctx); } diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index 98f8fea0fec3..85aa003db725 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -26,12 +26,80 @@ #include "nexthop.h" #include "printfrr.h" + +#define YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt) \ + ({ \ + va_list __ap; \ + va_start(__ap, (xpath_fmt)); \ + const struct lyd_value *__dvalue = \ + yang_dnode_xpath_get_value(dnode, xpath_fmt, __ap); \ + va_end(__ap); \ + __dvalue; \ + }) + +#define YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt) \ + ({ \ + va_list __ap; \ + va_start(__ap, (xpath_fmt)); \ + const char *__canon = \ + yang_dnode_xpath_get_canon(dnode, xpath_fmt, __ap); \ + va_end(__ap); \ + __canon; \ + }) + +#define YANG_DNODE_GET_ASSERT(dnode, xpath) \ + do { \ + if ((dnode) == NULL) { \ + flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, \ + "%s: couldn't find %s", __func__, (xpath)); \ + zlog_backtrace(LOG_ERR); \ + abort(); \ + } \ + } while (0) + +static inline const char * +yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt, + va_list ap) +{ + const struct lyd_node_term *__dleaf = + (const struct lyd_node_term *)dnode; + assert(__dleaf); + if (xpath_fmt) { + char __xpath[XPATH_MAXLEN]; + vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); + __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, + __xpath); + YANG_DNODE_GET_ASSERT(__dleaf, __xpath); + } + return lyd_get_value(&__dleaf->node); +} + +static inline const struct lyd_value * +yang_dnode_xpath_get_value(const struct lyd_node *dnode, const char *xpath_fmt, + va_list ap) +{ + const struct lyd_node_term *__dleaf = + (const struct lyd_node_term *)dnode; + assert(__dleaf); + if (xpath_fmt) { + char __xpath[XPATH_MAXLEN]; + vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); + __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, + __xpath); + YANG_DNODE_GET_ASSERT(__dleaf, __xpath); + } + const struct lyd_value *__dvalue = &__dleaf->value; + if (__dvalue->realtype->basetype == LY_TYPE_UNION) + __dvalue = &__dvalue->subvalue->value; + return __dvalue; +} + static const char *yang_get_default_value(const char *xpath) { - const struct lys_node *snode; + const struct lysc_node *snode; const char *value; - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -45,16 +113,6 @@ static const char *yang_get_default_value(const char *xpath) return value; } -#define YANG_DNODE_GET_ASSERT(dnode, xpath) \ - do { \ - if ((dnode) == NULL) { \ - flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, \ - "%s: couldn't find %s", __func__, (xpath)); \ - zlog_backtrace(LOG_ERR); \ - abort(); \ - } \ - } while (0) - /* * Primitive type: bool. */ @@ -71,23 +129,10 @@ struct yang_data *yang_data_new_bool(const char *xpath, bool value) bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_BOOL); - return dleaf->value.bln; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_BOOL); + return dvalue->boolean; } bool yang_get_default_bool(const char *xpath_fmt, ...) @@ -133,24 +178,18 @@ struct yang_data *yang_data_new_dec64(const char *xpath, double value) double yang_dnode_get_dec64(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } + const double denom[19] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, + 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, + 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, + 1e-15, 1e-16, 1e-17, 1e-18}; + const struct lysc_type_dec *dectype; + const struct lyd_value *dvalue; - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_DEC64); - - return lyd_dec64_to_double(dnode); + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + dectype = (const struct lysc_type_dec *)dvalue->realtype; + assert(dectype->basetype == LY_TYPE_DEC64); + assert(dectype->fraction_digits < sizeof(denom) / sizeof(*denom)); + return (double)dvalue->dec64 * denom[dectype->fraction_digits]; } double yang_get_default_dec64(const char *xpath_fmt, ...) @@ -172,12 +211,12 @@ double yang_get_default_dec64(const char *xpath_fmt, ...) */ int yang_str2enum(const char *xpath, const char *value) { - const struct lys_node *snode; - const struct lys_node_leaf *sleaf; - const struct lys_type *type; - const struct lys_type_info_enums *enums; + const struct lysc_node *snode; + const struct lysc_node_leaf *sleaf; + const struct lysc_type_enum *type; + const struct lysc_type_bitenum_item *enums; - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -185,18 +224,17 @@ int yang_str2enum(const char *xpath, const char *value) abort(); } - sleaf = (const struct lys_node_leaf *)snode; - type = &sleaf->type; - enums = &type->info.enums; - while (enums->count == 0 && type->der) { - type = &type->der->type; - enums = &type->info.enums; - } - for (unsigned int i = 0; i < enums->count; i++) { - const struct lys_type_enum *enm = &enums->enm[i]; - - if (strmatch(value, enm->name)) - return enm->value; + assert(snode->nodetype == LYS_LEAF); + sleaf = (const struct lysc_node_leaf *)snode; + type = (const struct lysc_type_enum *)sleaf->type; + assert(type->basetype == LY_TYPE_ENUM); + enums = type->enums; + unsigned int count = LY_ARRAY_COUNT(enums); + for (unsigned int i = 0; i < count; i++) { + if (strmatch(value, enums[i].name)) { + assert(CHECK_FLAG(enums[i].flags, LYS_SET_VALUE)); + return enums[i].value; + } } flog_err(EC_LIB_YANG_DATA_CONVERT, @@ -208,12 +246,12 @@ int yang_str2enum(const char *xpath, const char *value) struct yang_data *yang_data_new_enum(const char *xpath, int value) { - const struct lys_node *snode; - const struct lys_node_leaf *sleaf; - const struct lys_type *type; - const struct lys_type_info_enums *enums; + const struct lysc_node *snode; + const struct lysc_node_leaf *sleaf; + const struct lysc_type_enum *type; + const struct lysc_type_bitenum_item *enums; - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -221,18 +259,16 @@ struct yang_data *yang_data_new_enum(const char *xpath, int value) abort(); } - sleaf = (const struct lys_node_leaf *)snode; - type = &sleaf->type; - enums = &type->info.enums; - while (enums->count == 0 && type->der) { - type = &type->der->type; - enums = &type->info.enums; - } - for (unsigned int i = 0; i < enums->count; i++) { - const struct lys_type_enum *enm = &enums->enm[i]; - - if (value == enm->value) - return yang_data_new(xpath, enm->name); + assert(snode->nodetype == LYS_LEAF); + sleaf = (const struct lysc_node_leaf *)snode; + type = (const struct lysc_type_enum *)sleaf->type; + assert(type->basetype == LY_TYPE_ENUM); + enums = type->enums; + unsigned int count = LY_ARRAY_COUNT(enums); + for (unsigned int i = 0; i < count; i++) { + if (CHECK_FLAG(enums[i].flags, LYS_SET_VALUE) + && value == enums[i].value) + return yang_data_new(xpath, enums[i].name); } flog_err(EC_LIB_YANG_DATA_CONVERT, @@ -245,23 +281,12 @@ struct yang_data *yang_data_new_enum(const char *xpath, int value) int yang_dnode_get_enum(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; + const struct lyd_value *dvalue; - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_ENUM); - return dleaf->value.enm->value; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_ENUM); + assert(dvalue->enum_item->flags & LYS_SET_VALUE); + return dvalue->enum_item->value; } int yang_get_default_enum(const char *xpath_fmt, ...) @@ -297,23 +322,10 @@ struct yang_data *yang_data_new_int8(const char *xpath, int8_t value) int8_t yang_dnode_get_int8(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT8); - return dleaf->value.int8; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT8); + return dvalue->int8; } int8_t yang_get_default_int8(const char *xpath_fmt, ...) @@ -349,23 +361,10 @@ struct yang_data *yang_data_new_int16(const char *xpath, int16_t value) int16_t yang_dnode_get_int16(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT16); - return dleaf->value.int16; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT16); + return dvalue->int16; } int16_t yang_get_default_int16(const char *xpath_fmt, ...) @@ -401,23 +400,10 @@ struct yang_data *yang_data_new_int32(const char *xpath, int32_t value) int32_t yang_dnode_get_int32(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT32); - return dleaf->value.int32; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT32); + return dvalue->int32; } int32_t yang_get_default_int32(const char *xpath_fmt, ...) @@ -453,23 +439,10 @@ struct yang_data *yang_data_new_int64(const char *xpath, int64_t value) int64_t yang_dnode_get_int64(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT64); - return dleaf->value.int64; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT64); + return dvalue->int64; } int64_t yang_get_default_int64(const char *xpath_fmt, ...) @@ -505,23 +478,10 @@ struct yang_data *yang_data_new_uint8(const char *xpath, uint8_t value) uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT8); - return dleaf->value.uint8; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT8); + return dvalue->uint8; } uint8_t yang_get_default_uint8(const char *xpath_fmt, ...) @@ -557,23 +517,10 @@ struct yang_data *yang_data_new_uint16(const char *xpath, uint16_t value) uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT16); - return dleaf->value.uint16; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT16); + return dvalue->uint16; } uint16_t yang_get_default_uint16(const char *xpath_fmt, ...) @@ -609,23 +556,10 @@ struct yang_data *yang_data_new_uint32(const char *xpath, uint32_t value) uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT32); - return dleaf->value.uint32; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT32); + return dvalue->uint32; } uint32_t yang_get_default_uint32(const char *xpath_fmt, ...) @@ -661,23 +595,10 @@ struct yang_data *yang_data_new_uint64(const char *xpath, uint64_t value) uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT64); - return dleaf->value.uint64; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT64); + return dvalue->uint64; } uint64_t yang_get_default_uint64(const char *xpath_fmt, ...) @@ -707,44 +628,15 @@ struct yang_data *yang_data_new_string(const char *xpath, const char *value) const char *yang_dnode_get_string(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - return dleaf->value_str; + return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); } void yang_dnode_get_string_buf(char *buf, size_t size, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - if (strlcpy(buf, dleaf->value_str, size) >= size) { + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + if (strlcpy(buf, canon, size) >= size) { char xpath[XPATH_MAXLEN]; yang_dnode_get_path(dnode, xpath, sizeof(xpath)); @@ -797,7 +689,7 @@ bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt, { va_list ap; char xpath[XPATH_MAXLEN]; - const struct lyd_node_leaf_list *dleaf; + const struct lyd_node_term *dleaf; assert(dnode); @@ -807,8 +699,8 @@ bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt, dnode = yang_dnode_get(dnode, xpath); if (dnode) { - dleaf = (const struct lyd_node_leaf_list *)dnode; - if (dleaf->value_type == LY_TYPE_EMPTY) + dleaf = (const struct lyd_node_term *)dnode; + if (dleaf->value.realtype->basetype == LY_TYPE_EMPTY) return true; } @@ -836,29 +728,16 @@ struct yang_data *yang_data_new_prefix(const char *xpath, void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - + const char *canon; /* * Initialize prefix to avoid static analyzer complaints about * uninitialized memory. */ memset(prefix, 0, sizeof(*prefix)); - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2prefix(dleaf->value_str, prefix); + /* XXX ip_prefix is a native type now in ly2, leverage? */ + canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2prefix(canon, prefix); } void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt, ...) @@ -895,23 +774,9 @@ struct yang_data *yang_data_new_ipv4(const char *xpath, void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)inet_pton(AF_INET, dleaf->value_str, addr); + /* XXX libyang2 IPv4 address is a native type now in ly2 */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)inet_pton(AF_INET, canon, addr); } void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt, ...) @@ -951,24 +816,10 @@ struct yang_data *yang_data_new_ipv4p(const char *xpath, void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; struct prefix_ipv4 *prefix4 = prefix.p4; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2prefix_ipv4(dleaf->value_str, prefix4); + /* XXX libyang2: ipv4/6 address is a native type now in ly2 */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2prefix_ipv4(canon, prefix4); } void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt, ...) @@ -1005,23 +856,9 @@ struct yang_data *yang_data_new_ipv6(const char *xpath, void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)inet_pton(AF_INET6, dleaf->value_str, addr); + /* XXX libyang2: IPv6 address is a native type now, leverage. */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)inet_pton(AF_INET6, canon, addr); } void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt, ...) @@ -1061,24 +898,11 @@ struct yang_data *yang_data_new_ipv6p(const char *xpath, void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; struct prefix_ipv6 *prefix6 = prefix.p6; - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2prefix_ipv6(dleaf->value_str, prefix6); + /* XXX IPv6 address is a native type now in ly2 -- can we leverage? */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2prefix_ipv6(canon, prefix6); } void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...) @@ -1115,23 +939,9 @@ struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr) void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - if (xpath_fmt) { - va_list ap; - char xpath[XPATH_MAXLEN]; - - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); - dnode = yang_dnode_get(dnode, xpath); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2ipaddr(dleaf->value_str, addr); + /* XXX IPv4 address could be a plugin type now in ly2, leverage? */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2ipaddr(canon, addr); } void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...) diff --git a/pathd/path_pcep_debug.c b/pathd/path_pcep_debug.c index 370484dc1b3f..55148d9d0517 100644 --- a/pathd/path_pcep_debug.c +++ b/pathd/path_pcep_debug.c @@ -980,7 +980,7 @@ const char *format_yang_dnode(struct lyd_node *dnode) char *buff; int len; - lyd_print_mem(&buff, dnode, LYD_JSON, LYP_FORMAT); + lyd_print_mem(&buff, dnode, LYD_JSON, LYD_PRINT_WD_ALL); len = strlen(buff); memcpy(_debug_buff, buff, len); free(buff); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 90aa15beee2d..548c866e4d81 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -7986,8 +7986,8 @@ DEFUN (interface_no_ip_igmp, snprintf(pim_if_xpath, sizeof(pim_if_xpath), "%s/frr-pim:pim", VTY_CURR_XPATH); - pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/pim-enable", pim_if_xpath); + pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/pim-enable", pim_if_xpath); if (!pim_enable_dnode) { nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY, NULL); nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); @@ -8081,9 +8081,9 @@ DEFUN (interface_ip_igmp_query_interval, { const struct lyd_node *pim_enable_dnode; - pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-pim:pim/pim-enable", - VTY_CURR_XPATH); + pim_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH); if (!pim_enable_dnode) { nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true"); @@ -8157,9 +8157,9 @@ DEFUN (interface_ip_igmp_query_max_response_time, { const struct lyd_node *pim_enable_dnode; - pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-pim:pim/pim-enable", - VTY_CURR_XPATH); + pim_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH); if (!pim_enable_dnode) { nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, @@ -8206,9 +8206,9 @@ DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec, { const struct lyd_node *pim_enable_dnode; - pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-pim:pim/pim-enable", - VTY_CURR_XPATH); + pim_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH); if (!pim_enable_dnode) { nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true"); @@ -8254,9 +8254,9 @@ DEFUN (interface_ip_igmp_last_member_query_count, { const struct lyd_node *pim_enable_dnode; - pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-pim:pim/pim-enable", - VTY_CURR_XPATH); + pim_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH); if (!pim_enable_dnode) { nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true"); @@ -8301,9 +8301,9 @@ DEFUN (interface_ip_igmp_last_member_query_interval, { const struct lyd_node *pim_enable_dnode; - pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-pim:pim/pim-enable", - VTY_CURR_XPATH); + pim_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH); if (!pim_enable_dnode) { nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true"); @@ -8531,8 +8531,8 @@ DEFUN_HIDDEN (interface_no_ip_pim_ssm, snprintf(igmp_if_xpath, sizeof(igmp_if_xpath), "%s/frr-igmp:igmp", VTY_CURR_XPATH); - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/igmp-enable", igmp_if_xpath); + igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/igmp-enable", igmp_if_xpath); if (!igmp_enable_dnode) { nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL); @@ -8563,8 +8563,8 @@ DEFUN_HIDDEN (interface_no_ip_pim_sm, snprintf(igmp_if_xpath, sizeof(igmp_if_xpath), "%s/frr-igmp:igmp", VTY_CURR_XPATH); - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/igmp-enable", igmp_if_xpath); + igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/igmp-enable", igmp_if_xpath); if (!igmp_enable_dnode) { nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL); @@ -8594,8 +8594,8 @@ DEFUN (interface_no_ip_pim, snprintf(igmp_if_xpath, sizeof(igmp_if_xpath), "%s/frr-igmp:igmp", VTY_CURR_XPATH); - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/igmp-enable", igmp_if_xpath); + igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/igmp-enable", igmp_if_xpath); if (!igmp_enable_dnode) { nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL); @@ -8716,9 +8716,9 @@ DEFUN (interface_ip_pim_hello, int idx_hold = 4; const struct lyd_node *igmp_enable_dnode; - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-igmp:igmp/igmp-enable", - VTY_CURR_XPATH); + igmp_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH); if (!igmp_enable_dnode) { nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true"); @@ -9436,9 +9436,9 @@ DEFPY (ip_pim_bfd, { const struct lyd_node *igmp_enable_dnode; - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-igmp:igmp/igmp-enable", - VTY_CURR_XPATH); + igmp_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH); if (!igmp_enable_dnode) nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true"); @@ -9491,9 +9491,9 @@ DEFUN (ip_pim_bsm, { const struct lyd_node *igmp_enable_dnode; - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-igmp:igmp/igmp-enable", - VTY_CURR_XPATH); + igmp_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH); if (!igmp_enable_dnode) nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true"); @@ -9530,9 +9530,9 @@ DEFUN (ip_pim_ucast_bsm, { const struct lyd_node *igmp_enable_dnode; - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-igmp:igmp/igmp-enable", - VTY_CURR_XPATH); + igmp_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH); if (!igmp_enable_dnode) nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true"); @@ -9589,9 +9589,9 @@ DEFUN_HIDDEN( int idx_number_3 = 5; const struct lyd_node *igmp_enable_dnode; - igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode, - "%s/frr-igmp:igmp/igmp-enable", - VTY_CURR_XPATH); + igmp_enable_dnode = + yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH); if (!igmp_enable_dnode) nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true"); diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 4598297f93b3..003a9947e458 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -524,11 +524,10 @@ static bool is_pim_interface(const struct lyd_node *dnode) const struct lyd_node *igmp_enable_dnode; yang_dnode_get_path(dnode, if_xpath, sizeof(if_xpath)); - pim_enable_dnode = yang_dnode_get(dnode, "%s/frr-pim:pim/pim-enable", - if_xpath); - igmp_enable_dnode = yang_dnode_get(dnode, - "%s/frr-igmp:igmp/igmp-enable", - if_xpath); + pim_enable_dnode = + yang_dnode_getf(dnode, "%s/frr-pim:pim/pim-enable", if_xpath); + igmp_enable_dnode = yang_dnode_getf( + dnode, "%s/frr-igmp:igmp/igmp-enable", if_xpath); if (((pim_enable_dnode) && (yang_dnode_get_bool(pim_enable_dnode, "."))) || diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 47c6ad41afb7..e24a84d1e446 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -176,7 +176,7 @@ BuildRequires: make BuildRequires: ncurses-devel BuildRequires: readline-devel BuildRequires: texinfo -BuildRequires: libyang-devel >= 1.0.184 +BuildRequires: libyang2-devel %if 0%{?rhel} && 0%{?rhel} < 7 #python27-devel is available from ius community repo for RedHat/CentOS 6 BuildRequires: python27-devel diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 43e5b21fa1fb..0c5730b4d566 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -903,9 +903,9 @@ DEFPY_YANG (ip_rip_authentication_string, return CMD_WARNING_CONFIG_FAILED; } - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, - "/frr-ripd:rip/authentication-key-chain")) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, + "/frr-ripd:rip/authentication-key-chain")) { vty_out(vty, "%% key-chain configuration exists\n"); return CMD_WARNING_CONFIG_FAILED; } @@ -952,9 +952,9 @@ DEFPY_YANG (ip_rip_authentication_key_chain, "Authentication key-chain\n" "name of key-chain\n") { - if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s", - VTY_CURR_XPATH, - "/frr-ripd:rip/authentication-password")) { + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, + "/frr-ripd:rip/authentication-password")) { vty_out(vty, "%% authentication string configuration exists\n"); return CMD_WARNING_CONFIG_FAILED; } diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 1ef64ff0def0..0b927c76fa93 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -1113,7 +1113,7 @@ static int rip_interface_config_write(struct vty *vty) FOR_ALL_INTERFACES (vrf, ifp) { struct lyd_node *dnode; - dnode = yang_dnode_get( + dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifp->name, vrf->name); diff --git a/ripd/ripd.c b/ripd/ripd.c index 9832c7c52a4e..c6c82fb65ac1 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3632,16 +3632,16 @@ static int rip_vrf_enable(struct vrf *vrf) char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; - rip_dnode = yang_dnode_get( + rip_dnode = yang_dnode_getf( running_config->dnode, "/frr-ripd:ripd/instance[vrf='%s']/vrf", old_vrf_name); if (rip_dnode) { - yang_dnode_get_path(rip_dnode->parent, oldpath, - sizeof(oldpath)); + yang_dnode_get_path(lyd_parent(rip_dnode), + oldpath, sizeof(oldpath)); yang_dnode_change_leaf(rip_dnode, vrf->name); - yang_dnode_get_path(rip_dnode->parent, newpath, - sizeof(newpath)); + yang_dnode_get_path(lyd_parent(rip_dnode), + newpath, sizeof(newpath)); nb_running_move_tree(oldpath, newpath); running_config->version++; } diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 11a8fdff87e3..c4d494804f02 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -933,7 +933,7 @@ static int interface_config_write(struct vty *vty) FOR_ALL_INTERFACES (vrf, ifp) { struct lyd_node *dnode; - dnode = yang_dnode_get( + dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifp->name, vrf->name); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 5a71928fbdb8..3b8d2076f347 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2634,16 +2634,16 @@ static int ripng_vrf_enable(struct vrf *vrf) char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; - ripng_dnode = yang_dnode_get( + ripng_dnode = yang_dnode_getf( running_config->dnode, "/frr-ripngd:ripngd/instance[vrf='%s']/vrf", old_vrf_name); if (ripng_dnode) { - yang_dnode_get_path(ripng_dnode->parent, oldpath, - sizeof(oldpath)); + yang_dnode_get_path(lyd_parent(ripng_dnode), + oldpath, sizeof(oldpath)); yang_dnode_change_leaf(ripng_dnode, vrf->name); - yang_dnode_get_path(ripng_dnode->parent, newpath, - sizeof(newpath)); + yang_dnode_get_path(lyd_parent(ripng_dnode), + newpath, sizeof(newpath)); nb_running_move_tree(oldpath, newpath); running_config->version++; } diff --git a/staticd/static_nb.c b/staticd/static_nb.c index aa9076aa881f..c1a6253a1dd6 100644 --- a/staticd/static_nb.c +++ b/staticd/static_nb.c @@ -61,7 +61,6 @@ const struct frr_yang_module_info frr_staticd_info = { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type", .cbs = { .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify, - .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy, } }, { @@ -139,7 +138,6 @@ const struct frr_yang_module_info frr_staticd_info = { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/bh-type", .cbs = { .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify, - .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy, } }, { diff --git a/staticd/static_nb.h b/staticd/static_nb.h index e85e1d0e9f50..96dd05c0cf6c 100644 --- a/staticd/static_nb.h +++ b/staticd/static_nb.h @@ -37,8 +37,6 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify( struct nb_cb_modify_args *args); -int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy( - struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify( struct nb_cb_modify_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_color_modify( @@ -77,8 +75,6 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_sr struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify( struct nb_cb_modify_args *args); -int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy( - struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify( struct nb_cb_modify_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_color_modify( diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index e78f5172a312..cd151bface88 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -297,7 +297,7 @@ static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args) uint8_t index; nh = nb_running_get_entry(args->dnode, NULL, true); - pos = yang_get_list_pos(args->dnode->parent); + pos = yang_get_list_pos(lyd_parent(args->dnode)); if (!pos) { flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, "libyang returns invalid label position"); @@ -457,7 +457,7 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa uint32_t count; mls_dnode = yang_dnode_get(args->dnode, "./mpls-label-stack"); - count = yang_get_list_elements_count(yang_dnode_get_child(mls_dnode)); + count = yang_get_list_elements_count(lyd_child(mls_dnode)); if (count > MPLS_MAX_LABELS) { snprintf(args->errmsg, args->errmsg_len, @@ -689,22 +689,6 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa return static_nexthop_bh_type_modify(args); } -int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy( - struct nb_cb_destroy_args *args) -{ - /* blackhole type has a boolean type with default value, - * so no need to do any operations in destroy callback - */ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - break; - } - return NB_OK; -} - /* * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink @@ -1069,23 +1053,6 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_sr return static_nexthop_bh_type_modify(args); } -int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy( - struct nb_cb_destroy_args *args) -{ - /* blackhole type has a boolean type with default value, - * so no need to do any operations in destroy callback - */ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - break; - } - - return NB_OK; -} - /* * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/onlink diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index 123d97bc9700..cd5186f2aeb3 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -783,6 +783,8 @@ static void test_execute(struct test *test, const char *fmt, ...) cmd, ret); } + nb_cli_pending_commit_check(test->vty); + /* Free memory. */ cmd_free_strvec(vline); XFREE(MTYPE_TMP, cmd); @@ -1397,7 +1399,6 @@ static void bgp_startup(void) zprivs_init(&bgpd_privs); master = thread_master_create(NULL); - yang_init(true); nb_init(master, bgpd_yang_modules, array_size(bgpd_yang_modules), false); bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new()); bgp_option_set(BGP_OPT_NO_LISTEN); diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c index 7f15996daad6..64ecab913254 100644 --- a/tests/helpers/c/main.c +++ b/tests/helpers/c/main.c @@ -155,7 +155,6 @@ int main(int argc, char **argv) cmd_init(1); vty_init(master, false); lib_cmd_init(); - yang_init(true); nb_init(master, NULL, 0, false); /* OSPF vty inits. */ diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c index 8fe1ad0b8ae7..915f849aec51 100644 --- a/tests/isisd/test_isis_spf.c +++ b/tests/isisd/test_isis_spf.c @@ -547,7 +547,7 @@ int main(int argc, char **argv) cmd_init(1); cmd_hostname_set("test"); vty_init(master, false); - yang_init(true); + yang_init(true, false); if (debug) zlog_aux_init("NONE: ", LOG_DEBUG); else diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index 44cc6efe8427..49bc0f4fb23a 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -79,7 +79,6 @@ int main(int argc, char **argv) vty_init(master, false); lib_cmd_init(); - yang_init(true); nb_init(master, NULL, 0, false); test_init(argc, argv); diff --git a/tests/lib/cli/test_commands.c b/tests/lib/cli/test_commands.c index cb512211a43e..a00f80073c99 100644 --- a/tests/lib/cli/test_commands.c +++ b/tests/lib/cli/test_commands.c @@ -208,7 +208,6 @@ static void test_init(void) struct cmd_element *cmd; cmd_init(1); - yang_init(true); nb_init(master, NULL, 0, false); install_node(&bgp_node); diff --git a/tests/lib/northbound/test_oper_data.c b/tests/lib/northbound/test_oper_data.c index b5f257fa2ff5..08eb0d527cbe 100644 --- a/tests/lib/northbound/test_oper_data.c +++ b/tests/lib/northbound/test_oper_data.c @@ -399,7 +399,6 @@ int main(int argc, char **argv) cmd_hostname_set("test"); vty_init(master, false); lib_cmd_init(); - yang_init(true); nb_init(master, modules, array_size(modules), false); /* Create artificial data. */ diff --git a/tests/subdir.am b/tests/subdir.am index 43fad29fa24e..39966997745e 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -157,7 +157,7 @@ TESTS_CFLAGS = \ # note no -Werror ALL_TESTS_LDADD = lib/libfrr.la $(LIBCAP) -BGP_TEST_LDADD = bgpd/libbgp.a $(RFPLDADD) $(ALL_TESTS_LDADD) -lm +BGP_TEST_LDADD = bgpd/libbgp.a $(RFPLDADD) $(ALL_TESTS_LDADD) $(LIBYANG_LIBS) -lm ISISD_TEST_LDADD = isisd/libisis.a $(ALL_TESTS_LDADD) OSPFD_TEST_LDADD = ospfd/libfrrospf.a $(ALL_TESTS_LDADD) OSPF6_TEST_LDADD = ospf6d/libospf6.a $(ALL_TESTS_LDADD) diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c index a785f43cdf09..1705a3203fa4 100644 --- a/tools/gen_northbound_callbacks.c +++ b/tools/gen_northbound_callbacks.c @@ -118,7 +118,7 @@ static void replace_hyphens_by_underscores(char *str) *p++ = '_'; } -static void generate_callback_name(struct lys_node *snode, +static void generate_callback_name(const struct lysc_node *snode, enum nb_operation operation, char *buffer, size_t size) { @@ -126,14 +126,14 @@ static void generate_callback_name(struct lys_node *snode, struct listnode *ln; snodes = list_new(); - for (; snode; snode = lys_parent(snode)) { + for (; snode; snode = snode->parent) { /* Skip schema-only snodes. */ if (CHECK_FLAG(snode->nodetype, LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)) continue; - listnode_add_head(snodes, snode); + listnode_add_head(snodes, (void *)snode); } memset(buffer, 0, size); @@ -153,7 +153,7 @@ static void generate_prototype(const struct nb_callback_info *ncinfo, printf("%s%s(%s);\n", ncinfo->return_type, cb_name, ncinfo->arguments); } -static int generate_prototypes(const struct lys_node *snode, void *arg) +static int generate_prototypes(const struct lysc_node *snode, void *arg) { switch (snode->nodetype) { case LYS_CONTAINER: @@ -175,8 +175,8 @@ static int generate_prototypes(const struct lys_node *snode, void *arg) || !nb_operation_is_valid(cb->operation, snode)) continue; - generate_callback_name((struct lys_node *)snode, cb->operation, - cb_name, sizeof(cb_name)); + generate_callback_name(snode, cb->operation, cb_name, + sizeof(cb_name)); generate_prototype(cb, cb_name); } @@ -213,7 +213,7 @@ static void generate_callback(const struct nb_callback_info *ncinfo, printf("\treturn %s;\n}\n\n", ncinfo->return_value); } -static int generate_callbacks(const struct lys_node *snode, void *arg) +static int generate_callbacks(const struct lysc_node *snode, void *arg) { bool first = true; @@ -250,15 +250,15 @@ static int generate_callbacks(const struct lys_node *snode, void *arg) first = false; } - generate_callback_name((struct lys_node *)snode, cb->operation, - cb_name, sizeof(cb_name)); + generate_callback_name(snode, cb->operation, cb_name, + sizeof(cb_name)); generate_callback(cb, cb_name); } return YANG_ITER_CONTINUE; } -static int generate_nb_nodes(const struct lys_node *snode, void *arg) +static int generate_nb_nodes(const struct lysc_node *snode, void *arg) { bool first = true; @@ -295,8 +295,8 @@ static int generate_nb_nodes(const struct lys_node *snode, void *arg) first = false; } - generate_callback_name((struct lys_node *)snode, cb->operation, - cb_name, sizeof(cb_name)); + generate_callback_name(snode, cb->operation, cb_name, + sizeof(cb_name)); printf("\t\t\t\t.%s = %s,\n", nb_operation_name(cb->operation), cb_name); } @@ -350,18 +350,21 @@ int main(int argc, char *argv[]) if (argc != 1) usage(EXIT_FAILURE); - yang_init(false); + yang_init(false, true); if (search_path) ly_ctx_set_searchdir(ly_native_ctx, search_path); /* Load all FRR native models to ensure all augmentations are loaded. */ yang_module_load_all(); + module = yang_module_find(argv[0]); if (!module) /* Non-native FRR module (e.g. modules from unit tests). */ module = yang_module_load(argv[0]); + yang_init_loading_complete(); + /* Create a nb_node for all YANG schema nodes. */ nb_nodes_create(); diff --git a/tools/gen_yang_deviations.c b/tools/gen_yang_deviations.c index 53a53c943c47..8aa5695d3ecd 100644 --- a/tools/gen_yang_deviations.c +++ b/tools/gen_yang_deviations.c @@ -32,7 +32,7 @@ static void __attribute__((noreturn)) usage(int status) exit(status); } -static int generate_yang_deviation(const struct lys_node *snode, void *arg) +static int generate_yang_deviation(const struct lysc_node *snode, void *arg) { char xpath[XPATH_MAXLEN]; @@ -65,14 +65,13 @@ int main(int argc, char *argv[]) if (argc != 1) usage(EXIT_FAILURE); - yang_init(false); + yang_init(false, false); /* Load YANG module. */ module = yang_module_load(argv[0]); /* Generate deviations. */ - yang_snodes_iterate(module->info, generate_yang_deviation, - YANG_ITER_FILTER_IMPLICIT, NULL); + yang_snodes_iterate(module->info, generate_yang_deviation, 0, NULL); /* Cleanup and exit. */ yang_terminate(); diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c index 7d9cea3adc6e..6c3863132d69 100644 --- a/vrrpd/vrrp_vty.c +++ b/vrrpd/vrrp_vty.c @@ -729,7 +729,7 @@ static int vrrp_config_write_interface(struct vty *vty) FOR_ALL_INTERFACES (vrf, ifp) { struct lyd_node *dnode; - dnode = yang_dnode_get( + dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifp->name, vrf->name); diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 37ae0ab189d1..86cf8c9657d1 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -42,7 +42,7 @@ sub scan_file { $cppadd = $fabricd ? "-DFABRICD=1" : ""; - open (FH, "@CPP@ -P -std=gnu11 -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ $cppadd $file |"); + open (FH, "@CPP@ -P -std=gnu11 -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ @LIBYANG_CFLAGS@ $cppadd $file |"); local $/; undef $/; $line = ; if (!close (FH)) { diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 336bd44a49f8..111c2dbc03db 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2890,6 +2890,37 @@ DEFUN (show_yang_operational_data, return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text); } +DEFUN(show_yang_module, show_yang_module_cmd, + "show yang module [module-translator WORD] " DAEMONS_LIST, + SHOW_STR + "YANG information\n" + "Show loaded modules\n" + "YANG module translator\n" + "YANG module translator\n" DAEMONS_STR) +{ + return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text); +} + +DEFUN(show_yang_module_detail, show_yang_module_detail_cmd, + "show yang module\ + [module-translator WORD]\ + WORD " DAEMONS_LIST, + SHOW_STR + "YANG information\n" + "Show loaded modules\n" + "YANG module translator\n" + "YANG module translator\n" + "Module name\n" + "Display compiled module in YANG format\n" + "Display summary information about the module\n" + "Display module in the tree (RFC 8340) format\n" + "Display module in the YANG format\n" + "Display module in the YIN format\n" DAEMONS_STR) +{ + return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text); +} + + DEFUNSH(VTYSH_ALL, debug_nb, debug_nb_cmd, "[no] debug northbound\ @@ -4449,6 +4480,8 @@ void vtysh_init_vty(void) /* northbound */ install_element(ENABLE_NODE, &show_config_running_cmd); install_element(ENABLE_NODE, &show_yang_operational_data_cmd); + install_element(ENABLE_NODE, &show_yang_module_cmd); + install_element(ENABLE_NODE, &show_yang_module_detail_cmd); install_element(ENABLE_NODE, &debug_nb_cmd); install_element(CONFIG_NODE, &debug_nb_cmd); diff --git a/watchfrr/subdir.am b/watchfrr/subdir.am index 677f85efcbb3..e899b895e7c5 100644 --- a/watchfrr/subdir.am +++ b/watchfrr/subdir.am @@ -13,7 +13,7 @@ noinst_HEADERS += \ watchfrr/watchfrr_errors.h \ # end -watchfrr_watchfrr_LDADD = lib/libfrr.la $(LIBCAP) +watchfrr_watchfrr_LDADD = lib/libfrr.la $(LIBYANG_LIBS) $(LIBCAP) watchfrr_watchfrr_SOURCES = \ watchfrr/watchfrr.c \ watchfrr/watchfrr_errors.c \ diff --git a/yang/embedmodel.py b/yang/embedmodel.py index 39bf2bb9226c..a77a81363fa5 100644 --- a/yang/embedmodel.py +++ b/yang/embedmodel.py @@ -94,7 +94,7 @@ def escape(line): sub_name = search_name.group(1) name = re_mainname.search(data).group(1) sub_rev = re_rev.search(data).group(1) - fmt = "LYS_YANG" + fmt = "LYS_IN_YANG" if name is None or rev is None: raise ValueError("cannot determine YANG module name and revision") diff --git a/yang/frr-bgp-bmp.yang b/yang/frr-bgp-bmp.yang index 344448f104f0..2417874ea0a9 100644 --- a/yang/frr-bgp-bmp.yang +++ b/yang/frr-bgp-bmp.yang @@ -13,8 +13,6 @@ submodule frr-bgp-bmp { prefix frr-bt; } - include frr-bgp-common-multiprotocol; - organization "FRRouting"; contact diff --git a/yang/frr-bgp-common-multiprotocol.yang b/yang/frr-bgp-common-multiprotocol.yang index aefdf02ba68d..4b080613d637 100644 --- a/yang/frr-bgp-common-multiprotocol.yang +++ b/yang/frr-bgp-common-multiprotocol.yang @@ -9,8 +9,6 @@ submodule frr-bgp-common-multiprotocol { prefix frr-rt; } - include frr-bgp-common; - organization "FRRouting"; contact @@ -67,7 +65,7 @@ submodule frr-bgp-common-multiprotocol { "A common grouping used for contents of the list that is used for AFI-SAFI entries."; container ipv4-unicast { - when "derived-from-or-self(../afi-safi-name, 'ipv4-unicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv4-unicast')" { description "Include this container for IPv4 Unicast specific configuration."; @@ -77,7 +75,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv6-unicast { - when "derived-from-or-self(../afi-safi-name, 'ipv6-unicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv6-unicast')" { description "Include this container for IPv6 Unicast specific configuration."; @@ -87,7 +85,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv4-labeled-unicast { - when "derived-from-or-self(../afi-safi-name, 'ipv4-labeled-unicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv4-labeled-unicast')" { description "Include this container for IPv4 Labeled Unicast specific configuration."; @@ -97,7 +95,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv6-labeled-unicast { - when "derived-from-or-self(../afi-safi-name, 'ipv6-labeled-unicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv6-labeled-unicast')" { description "Include this container for IPv6 Labeled Unicast specific configuration."; @@ -107,7 +105,7 @@ submodule frr-bgp-common-multiprotocol { } container l3vpn-ipv4-unicast { - when "derived-from-or-self(../afi-safi-name, 'l3vpn-ipv4-unicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:l3vpn-ipv4-unicast')" { description "Include this container for IPv4 Unicast L3VPN specific configuration."; @@ -117,7 +115,7 @@ submodule frr-bgp-common-multiprotocol { } container l3vpn-ipv6-unicast { - when "derived-from-or-self(../afi-safi-name, 'l3vpn-ipv6-unicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:l3vpn-ipv6-unicast')" { description "Include this container for unicast IPv6 L3VPN specific configuration."; @@ -127,7 +125,7 @@ submodule frr-bgp-common-multiprotocol { } container l3vpn-ipv4-multicast { - when "derived-from-or-self(../afi-safi-name, 'l3vpn-ipv4-multicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:l3vpn-ipv4-multicast')" { description "Include this container for multicast IPv4 L3VPN specific configuration."; @@ -137,7 +135,7 @@ submodule frr-bgp-common-multiprotocol { } container l3vpn-ipv6-multicast { - when "derived-from-or-self(../afi-safi-name, 'l3vpn-ipv6-multicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:l3vpn-ipv6-multicast')" { description "Include this container for multicast IPv6 L3VPN specific configuration."; @@ -147,7 +145,7 @@ submodule frr-bgp-common-multiprotocol { } container l2vpn-vpls { - when "derived-from-or-self(../afi-safi-name, 'l2vpn-vpls')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:l2vpn-vpls')" { description "Include this container for BGP-signalled VPLS specific configuration."; @@ -157,7 +155,7 @@ submodule frr-bgp-common-multiprotocol { } container l2vpn-evpn { - when "derived-from-or-self(../afi-safi-name, 'l2vpn-evpn')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:l2vpn-evpn')" { description "Include this container for BGP EVPN specific configuration."; @@ -167,7 +165,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv4-multicast { - when "derived-from-or-self(../afi-safi-name, 'ipv4-multicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv4-multicast')" { description "Include this container for IPv4 multicast specific configuration."; @@ -177,7 +175,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv6-multicast { - when "derived-from-or-self(../afi-safi-name, 'ipv6-multicast')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv6-multicast')" { description "Include this container for IPv6 multicast specific configuration."; @@ -187,7 +185,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv4-flowspec { - when "derived-from-or-self(../afi-safi-name, 'ipv4-flowspec')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv4-flowspec')" { description "Include this container for IPv4 flowspec specific configuration."; @@ -197,7 +195,7 @@ submodule frr-bgp-common-multiprotocol { } container ipv6-flowspec { - when "derived-from-or-self(../afi-safi-name, 'ipv6-flowspec')" { + when "derived-from-or-self(../afi-safi-name, 'frr-rt:ipv6-flowspec')" { description "Include this container for IPv6 flowspec specific configuration."; diff --git a/yang/frr-bgp-common-structure.yang b/yang/frr-bgp-common-structure.yang index 7b987a93cd03..232c78899e4f 100644 --- a/yang/frr-bgp-common-structure.yang +++ b/yang/frr-bgp-common-structure.yang @@ -25,8 +25,6 @@ submodule frr-bgp-common-structure { prefix frr-bt; } - include frr-bgp-common; - organization "FRRouting"; contact @@ -118,7 +116,6 @@ submodule frr-bgp-common-structure { } leaf no-prepend { - when "../local-as != 0"; type boolean; default "false"; description diff --git a/yang/frr-bgp-common.yang b/yang/frr-bgp-common.yang index 1a19d5296562..157e4cd614c7 100644 --- a/yang/frr-bgp-common.yang +++ b/yang/frr-bgp-common.yang @@ -455,11 +455,14 @@ submodule frr-bgp-common { grouping global-network-config { leaf import-check { type boolean; - default "false"; + default "true"; description "When set to 'true' bgp creates entries for network statements if a matching prefix exists in the rib. When set to 'false' bgp - creates entries for networks that the router cannot reach."; + creates entries for networks that the router cannot reach. + + In FRR versions < 7.4 this used to default to 'false' this is an + incompatible backward change"; } } diff --git a/yang/frr-bgp-neighbor.yang b/yang/frr-bgp-neighbor.yang index a4b50b156b14..d6688eed296f 100644 --- a/yang/frr-bgp-neighbor.yang +++ b/yang/frr-bgp-neighbor.yang @@ -5,9 +5,6 @@ submodule frr-bgp-neighbor { prefix "bgp"; } - include frr-bgp-common-structure; - include frr-bgp-common-multiprotocol; - organization "FRRouting"; contact diff --git a/yang/frr-bgp-peer-group.yang b/yang/frr-bgp-peer-group.yang index 452ff1a12f02..746ced30cc7a 100644 --- a/yang/frr-bgp-peer-group.yang +++ b/yang/frr-bgp-peer-group.yang @@ -13,9 +13,6 @@ submodule frr-bgp-peer-group { prefix frr-bt; } - include frr-bgp-common-structure; - include frr-bgp-neighbor; - organization "FRRouting"; contact diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index 96505b08a8b7..ca60c8f7b6a4 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -332,7 +332,7 @@ module frr-bgp-route-map { augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:rmap-match-condition/frr-route-map:match-condition" { case local-preference { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'match-local-preference')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-local-preference')"; leaf local-preference { type uint32 { range "0..4294967295"; @@ -341,14 +341,14 @@ module frr-bgp-route-map { } case script { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'match-script')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-script')"; leaf script { type string; } } case origin { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'match-origin')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-origin')"; leaf origin { type enumeration { enum "egp" { @@ -371,7 +371,7 @@ module frr-bgp-route-map { } case rpki { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'rpki')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:rpki')"; leaf rpki { type enumeration { enum "invalid" { @@ -394,7 +394,7 @@ module frr-bgp-route-map { } case probability { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'probability')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:probability')"; leaf probability { type uint8 { range "0..100"; @@ -403,14 +403,14 @@ module frr-bgp-route-map { } case source-vrf { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'source-vrf')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:source-vrf')"; leaf source-vrf { type string; } } case peer { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'peer')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:peer')"; choice peer { description "Value of the peer"; @@ -449,10 +449,10 @@ module frr-bgp-route-map { } case access-list-name { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'mac-address-list') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'as-path-list') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'ip-route-source') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'ip-route-source-prefix-list')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:mac-address-list') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:as-path-list') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ip-route-source') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ip-route-source-prefix-list')"; description "Access-list name"; leaf list-name { @@ -461,7 +461,7 @@ module frr-bgp-route-map { } case evpn-default-route { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'evpn-default-route')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-default-route')"; description "Match default EVPN type-5 route"; leaf evpn-default-route { @@ -470,7 +470,7 @@ module frr-bgp-route-map { } case evpn-vni { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'evpn-vni')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-vni')"; description "Match eVPN VNI"; leaf evpn-vni { @@ -481,7 +481,7 @@ module frr-bgp-route-map { } case evpn-route-type { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'evpn-route-type')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-route-type')"; description "Match eVPN route-type"; leaf evpn-route-type { @@ -506,7 +506,7 @@ module frr-bgp-route-map { } case evpn-rd { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'evpn-rd')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-rd')"; description "Match eVPN route-distinguisher"; leaf route-distinguisher { @@ -515,9 +515,9 @@ module frr-bgp-route-map { } case comm-list-name { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'match-community') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'match-large-community') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'match-extcommunity')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-community') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-large-community') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-extcommunity')"; container comm-list { leaf comm-list-name { type bgp-filter:bgp-list-name; @@ -532,7 +532,7 @@ module frr-bgp-route-map { } case ipv4-address { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'ipv4-nexthop')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ipv4-nexthop')"; leaf ipv4-address { type inet:ipv4-address; description @@ -541,7 +541,7 @@ module frr-bgp-route-map { } case ipv6-address { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'ipv6-nexthop')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ipv6-nexthop')"; leaf ipv6-address { type inet:ipv6-address; description @@ -552,7 +552,7 @@ module frr-bgp-route-map { augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" { case distance { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'distance')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:distance')"; leaf distance { type uint8 { range "0..255"; @@ -561,7 +561,7 @@ module frr-bgp-route-map { } case extcommunity-rt { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-extcommunity-rt')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-rt')"; description "Value of the ext-community"; leaf extcommunity-rt { @@ -572,7 +572,7 @@ module frr-bgp-route-map { } case extcommunity-soo { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-extcommunity-soo')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-soo')"; description "Value of the ext-community"; leaf extcommunity-soo { @@ -583,7 +583,7 @@ module frr-bgp-route-map { } case extcommunity-lb { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-extcommunity-lb')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-lb')"; container extcommunity-lb { description "Value of the ext-community."; @@ -604,7 +604,7 @@ module frr-bgp-route-map { } case ipv4-address { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'ipv4-vpn-address')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv4-vpn-address')"; description "Set the IPv4 address"; leaf ipv4-address { @@ -613,15 +613,15 @@ module frr-bgp-route-map { } case ipv4-nexthop { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-ipv4-nexthop')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-ipv4-nexthop')"; leaf ipv4-nexthop { type string; } } case ipv6-address { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'ipv6-nexthop-global') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'ipv6-vpn-address')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-nexthop-global') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-vpn-address')"; description "Set the IPv6 address"; leaf ipv6-address { @@ -630,15 +630,15 @@ module frr-bgp-route-map { } case preference { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'ipv6-prefer-global') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'ipv6-peer-address')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-prefer-global') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-peer-address')"; leaf preference { type boolean; } } case label-index { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'label-index')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:label-index')"; leaf label-index { type uint32 { range "0..1048560"; @@ -647,14 +647,14 @@ module frr-bgp-route-map { } case local-pref { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-local-preference')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-local-preference')"; leaf local-pref { type string; } } case weight { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'weight')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:weight')"; leaf weight { type uint32 { range "0..4294967295"; @@ -663,7 +663,7 @@ module frr-bgp-route-map { } case origin { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-origin')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-origin')"; leaf origin { type enumeration { enum "egp" { @@ -686,14 +686,14 @@ module frr-bgp-route-map { } case originator-id { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'originator-id')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:originator-id')"; leaf originator-id { type inet:ipv4-address; } } case table { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'table')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:table')"; leaf table { type uint32 { range "1..4294967295"; @@ -702,14 +702,14 @@ module frr-bgp-route-map { } case atomic-aggregate { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'atomic-aggregate')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:atomic-aggregate')"; leaf atomic-aggregate { type empty; } } case as-path-prepend { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'as-path-prepend')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:as-path-prepend')"; choice as-path-prepend { description "Value of the BGP AS-path attribute"; @@ -734,7 +734,7 @@ module frr-bgp-route-map { } case as-path-exclude { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'as-path-exclude')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:as-path-exclude')"; leaf exclude-as-path { type string; description @@ -743,7 +743,7 @@ module frr-bgp-route-map { } case community { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-community')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-community')"; choice community { description "Value of the BGP community attribute"; @@ -766,7 +766,7 @@ module frr-bgp-route-map { } case large-community { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'set-large-community')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-large-community')"; choice large-community { description "Value of the BGP large-community attribute"; @@ -789,7 +789,7 @@ module frr-bgp-route-map { } case aggregator { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'aggregator')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:aggregator')"; container aggregator { leaf aggregator-asn { type uint32 { @@ -810,8 +810,8 @@ module frr-bgp-route-map { } case comm-list-name { - when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'comm-list-delete') or " - + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'large-comm-list-delete')"; + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:comm-list-delete') or " + + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:large-comm-list-delete')"; leaf comm-list-name { type bgp-filter:bgp-list-name; } diff --git a/yang/frr-bgp.yang b/yang/frr-bgp.yang index ae44447df73d..a779bb20540f 100644 --- a/yang/frr-bgp.yang +++ b/yang/frr-bgp.yang @@ -23,10 +23,10 @@ module frr-bgp { prefix frr-bt; } - include "frr-bgp-common-structure"; - include "frr-bgp-common"; + include "frr-bgp-common-structure"; + include "frr-bgp-common-multiprotocol"; include "frr-bgp-neighbor"; diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 4653e6f009a3..5997e8866aee 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -481,6 +481,10 @@ module frr-isisd { description "TI-LFA configuration."; leaf enable { + must ". = 'false' or ../../lfa/enable = 'false'" { + error-message + "Can't enable both classic LFA and TI-LFA in the same interface."; + } type boolean; default false; description @@ -804,10 +808,6 @@ module frr-isisd { container level-1 { description "Level-1 IP Fast-reroute configuration."; - must "./lfa/enable = 'false' or ./ti-lfa/enable = 'false'" { - error-message - "Can't enable both classic LFA and TI-LFA in the same interface."; - } uses interface-config-lfa; uses interface-config-remote-lfa; uses interface-config-ti-lfa; @@ -815,10 +815,6 @@ module frr-isisd { container level-2 { description "Level-2 IP Fast-reroute configuration."; - must "./lfa/enable = 'false' or ./ti-lfa/enable = 'false'" { - error-message - "Can't enable both classic LFA and TI-LFA in the same interface."; - } uses interface-config-lfa; uses interface-config-remote-lfa; uses interface-config-ti-lfa; @@ -1502,14 +1498,15 @@ module frr-isisd { container srgb { description "Global blocks to be advertised."; - must "./upper-bound > ./lower-bound"; leaf lower-bound { + must "../upper-bound > ."; type uint32; default "16000"; description "Lower value in the label range."; } leaf upper-bound { + must ". > ../lower-bound"; type uint32; default "23999"; description @@ -1519,14 +1516,15 @@ module frr-isisd { container srlb { description "Local blocks to be advertised."; - must "./upper-bound > ./lower-bound"; leaf lower-bound { + must "../upper-bound > ."; type uint32; default "15000"; description "Lower value in the label range."; } leaf upper-bound { + must ". > ../lower-bound"; type uint32; default "15999"; description diff --git a/yang/frr-ospfd.yang b/yang/frr-ospfd.yang index 42a7e8784ce8..b0150cc0612a 100644 --- a/yang/frr-ospfd.yang +++ b/yang/frr-ospfd.yang @@ -682,8 +682,8 @@ module frr-ospfd { container global-block { description "Segment Routing Global Block label range."; - must "./upper-bound > ./lower-bound"; leaf lower-bound { + must "../upper-bound > ."; type uint32 { range "0..1048575"; } @@ -691,6 +691,7 @@ module frr-ospfd { } leaf upper-bound { + must ". > ../lower-bound"; type uint32 { range "0..1048575"; } @@ -701,14 +702,15 @@ module frr-ospfd { container srlb { description "Local blocks to be advertised."; - must "./upper-bound > ./lower-bound"; leaf lower-bound { + must "../upper-bound > ."; type uint32; default "15000"; description "Lower value in the label range."; } leaf upper-bound { + must ". > ../lower-bound"; type uint32; default "15999"; description diff --git a/yang/frr-pim.yang b/yang/frr-pim.yang index 52d86416130f..70adb37b2653 100644 --- a/yang/frr-pim.yang +++ b/yang/frr-pim.yang @@ -341,14 +341,14 @@ module frr-pim { leaf bsm { type boolean; - default "false"; + default "true"; description "Enables BSM support on the interface."; } leaf unicast-bsm { type boolean; - default "false"; + default "true"; description "Accept/Send unicast BSM on the interface."; } diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index 929c916069b3..d77241cb15db 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -291,6 +291,10 @@ module frr-ripd { } container version { leaf receive { + must + '(. = "1" and ../send = "1") or ' + + '(. = "2" and ../send = "2") or ' + + '(. = "1-2" and ../send = "2")'; type enumeration { enum "1" { value 1; @@ -313,6 +317,10 @@ module frr-ripd { "Advertisement reception - Version control."; } leaf send { + must + '(../receive = "1" and . = "1") or ' + + '(../receive = "2" and . = "2") or ' + + '(../receive = "1-2" and . = "2")'; type enumeration { enum "1" { value 1; @@ -329,10 +337,6 @@ module frr-ripd { description "Advertisement transmission - Version control."; } - must - '(./receive = "1" and ./send = "1") or ' + - '(./receive = "2" and ./send = "2") or ' + - '(./receive = "1-2" and ./send = "2")'; } /* diff --git a/yang/frr-zebra-route-map.yang b/yang/frr-zebra-route-map.yang index 91f4c87e3384..de0f64d3893d 100644 --- a/yang/frr-zebra-route-map.yang +++ b/yang/frr-zebra-route-map.yang @@ -64,10 +64,15 @@ module frr-zebra-route-map { "Set IPv4/IPv6 source address for route"; } - augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:rmap-match-condition/frr-route-map:match-condition" { + augment "/frr-route-map:lib" + + "/frr-route-map:route-map" + + "/frr-route-map:entry" + + "/frr-route-map:match-condition" + + "/frr-route-map:rmap-match-condition" + + "/frr-route-map:match-condition" { case ipv4-prefix-length { - when "derived-from-or-self(../condition, 'ipv4-prefix-length') or " - + "derived-from-or-self(../condition, 'ipv4-next-hop-prefix-length')"; + when "derived-from-or-self(../frr-route-map:condition, 'frr-zebra-route-map:ipv4-prefix-length') or " + + "derived-from-or-self(../frr-route-map:condition, 'frr-zebra-route-map:ipv4-next-hop-prefix-length')"; leaf ipv4-prefix-length { type uint8 { range "0..32"; @@ -76,7 +81,7 @@ module frr-zebra-route-map { } case ipv6-prefix-length { - when "derived-from-or-self(../condition, 'ipv6-prefix-length')"; + when "derived-from-or-self(../frr-route-map:condition, 'frr-zebra-route-map:ipv6-prefix-length')"; leaf ipv6-prefix-length { type uint8 { range "0..128"; @@ -85,7 +90,7 @@ module frr-zebra-route-map { } case source-instance { - when "derived-from-or-self(../condition, 'source-instance')"; + when "derived-from-or-self(../frr-route-map:condition, 'frr-zebra-route-map:source-instance')"; leaf source-instance { type uint8 { range "0..255"; @@ -94,16 +99,21 @@ module frr-zebra-route-map { } case source-protocol { - when "derived-from-or-self(../condition, 'source-protocol')"; + when "derived-from-or-self(../frr-route-map:condition, 'frr-zebra-route-map:source-protocol')"; leaf source-protocol { type frr-route-types:frr-route-types; } } } - augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" { + augment "/frr-route-map:lib" + + "/frr-route-map:route-map" + + "/frr-route-map:entry" + + "/frr-route-map:set-action" + + "/frr-route-map:rmap-set-action" + + "/frr-route-map:set-action" { case src-address { - when "derived-from-or-self(../action, 'src-address')"; + when "derived-from-or-self(../frr-route-map:action, 'frr-zebra-route-map:src-address')"; choice src-address { description "Value of the source address"; diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang index 5c2560837f1e..a2c6bb4c2b8f 100644 --- a/yang/frr-zebra.yang +++ b/yang/frr-zebra.yang @@ -1953,7 +1953,7 @@ module frr-zebra { } leaf ip4-peer { - when "derived-from-or-self(../address-family, 'ipv4')"; + when "derived-from-or-self(../address-family, 'frr-rt:ipv4')"; type inet:ipv4-prefix; description "Peer prefix, for peer-to-peer interfaces.";