Merge pull request #8144 from LabNConsulting/chopps/ly2

libyang2
This commit is contained in:
Martin Winter 2021-05-14 01:12:06 +02:00 committed by GitHub
commit d8baf3db2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 1227 additions and 1268 deletions

View File

@ -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

View File

@ -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 .

View File

@ -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++;

View File

@ -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,
}
},
{

View File

@ -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(

View File

@ -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

View File

@ -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)) {

View File

@ -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

View File

@ -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"

4
debian/control vendored
View File

@ -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 <!pkg.frr.nortrlib>,
libsnmp-dev,
libssh-dev <!pkg.frr.nortrlib>,
libsystemd-dev <!pkg.frr.nosystemd>,
libyang-dev (>= 1.0.184),
libyang2-dev,
lsb-base,
pkg-config,
python3,

View File

@ -10,11 +10,12 @@ The FRR project builds some binary ``libyang`` packages.
RPM packages are at our `RPM repository <https://rpm.frrouting.org>`_.
DEB packages are available as CI artifacts `here
<https://ci1.netdef.org/browse/LIBYANG-LY1REL-DEB10AMD64-4/artifact>`_.
<https://ci1.netdef.org/browse/LIBYANG-LIBYANG-V2/latestSuccessful/artifact>`_.
.. 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
<https://github.com/CESNET/libyang/blob/master/README.md#build-requirements>`_
<https://github.com/CESNET/libyang/tree/libyang2#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

View File

@ -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 \

View File

@ -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 \

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)) {

View File

@ -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);

View File

@ -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++;

View File

@ -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;
}

View File

@ -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;
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
err = lyd_diff_siblings(config1->dnode, config2->dnode,
LYD_DIFF_DEFAULTS, &diff);
assert(!err);
if (diff && DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL))
nb_config_diff_dnode_log("iterating diff", diff);
uint32_t seq = 0;
LY_LIST_FOR (diff, root) {
LYD_TREE_DFS_BEGIN (root, dnode) {
op = nb_lyd_diff_get_op(dnode);
diff = lyd_diff(config1->dnode, config2->dnode,
LYD_DIFFOPT_WITHDEFAULTS);
assert(diff);
path = lyd_path(dnode, LYD_PATH_STD, NULL, 0);
for (int i = 0; diff->type[i] != LYD_DIFF_END; i++) {
LYD_DIFFTYPE type;
struct lyd_node *dnode;
#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);
type = diff->type[i];
/* 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();

View File

@ -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.

View File

@ -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 <summary|tree$tree|yang$yang|yin$yin>",
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 <compiled$compiled|summary|tree$tree|yang$yang|yin$yin>",
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 {

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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",

View File

@ -25,8 +25,6 @@
#include "yang_translator.h"
#include "northbound.h"
#include <libyang/user_types.h>
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);
}
return found;
bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath)
{
struct ly_set *set = NULL;
bool exists = false;
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_defaultf(const struct lyd_node *dnode, const char *xpath_fmt,
...)
{
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 lys_node *snode;
struct lyd_node *root, *next, *dnode_iter;
snode = dnode->schema;
if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST))
return yang_dnode_is_default(dnode, NULL);
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;
struct lyd_node *dnode = NULL;
int options = config_only ? LYD_VALIDATE_NO_STATE : 0;
if (config_only)
options = LYD_OPT_CONFIG;
else
options = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB;
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;
}

View File

@ -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);

View File

@ -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);
}
ly_set_free(set);
/* 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);
}
ly_set_free(set, NULL);
/* Calculate the coverage. */
for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
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->set.d[i], "./custom");
snode_custom = ly_ctx_get_node(translator->ly_ctx, NULL,
xpath_custom, 0);
xpath_custom =
yang_dnode_get_string(set->dnodes[i], "./custom");
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);
}

View File

@ -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;
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;
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_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, ...)

View File

@ -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);

View File

@ -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");

View File

@ -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, "."))) ||

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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++;
}

View File

@ -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);

View File

@ -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++;
}

View File

@ -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,
}
},
{

View File

@ -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(

View File

@ -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

View File

@ -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);

View File

@ -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. */

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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. */

View File

@ -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)

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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 = <FH>;
if (!close (FH)) {

View File

@ -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 <compiled|summary|tree|yang|yin> " 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);

View File

@ -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 \

View File

@ -94,7 +94,7 @@ else:
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")

View File

@ -13,8 +13,6 @@ submodule frr-bgp-bmp {
prefix frr-bt;
}
include frr-bgp-common-multiprotocol;
organization
"FRRouting";
contact

View File

@ -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.";

View File

@ -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

View File

@ -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";
}
}

View File

@ -5,9 +5,6 @@ submodule frr-bgp-neighbor {
prefix "bgp";
}
include frr-bgp-common-structure;
include frr-bgp-common-multiprotocol;
organization
"FRRouting";
contact

View File

@ -13,9 +13,6 @@ submodule frr-bgp-peer-group {
prefix frr-bt;
}
include frr-bgp-common-structure;
include frr-bgp-neighbor;
organization
"FRRouting";
contact

View File

@ -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;
}

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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.";
}

View File

@ -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")';
}
/*

View File

@ -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";

View File

@ -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.";