mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 11:50:21 +00:00
lib: adapt to version 2 of libyang
Compile with v2.0.0 tag of `libyang2` branch of: https://github.com/CESNET/libyang staticd init load time of 10k routes now 6s vs ly1 time of 150s Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
parent
17daea8a18
commit
3bb513c399
@ -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
|
||||
|
16
.travis.yml
16
.travis.yml
@ -5,14 +5,14 @@ services:
|
||||
- docker
|
||||
jobs:
|
||||
include:
|
||||
- script:
|
||||
- docker/centos-7/build.sh
|
||||
- docker images
|
||||
name: centos7
|
||||
- script:
|
||||
- docker/centos-8/build.sh
|
||||
- docker images
|
||||
name: centos8
|
||||
# - script:
|
||||
# - docker/centos-7/build.sh
|
||||
# - docker images
|
||||
# name: centos7
|
||||
# - script:
|
||||
# - docker/centos-8/build.sh
|
||||
# - docker images
|
||||
# name: centos8
|
||||
- script:
|
||||
- sudo apt install -y linux-modules-extra-$(uname -r)
|
||||
- docker build -t frr-ubuntu18:latest -f docker/ubuntu18-ci/Dockerfile .
|
||||
|
@ -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++;
|
||||
|
@ -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,
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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
4
debian/control
vendored
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
6
lib/if.c
6
lib/if.c
@ -266,16 +266,16 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
|
||||
char oldpath[XPATH_MAXLEN];
|
||||
char newpath[XPATH_MAXLEN];
|
||||
|
||||
if_dnode = yang_dnode_get(
|
||||
if_dnode = yang_dnode_getf(
|
||||
running_config->dnode,
|
||||
"/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
|
||||
ifp->name, old_vrf->name);
|
||||
|
||||
if (if_dnode) {
|
||||
yang_dnode_get_path(if_dnode->parent, oldpath,
|
||||
yang_dnode_get_path(lyd_parent(if_dnode), oldpath,
|
||||
sizeof(oldpath));
|
||||
yang_dnode_change_leaf(if_dnode, vrf->name);
|
||||
yang_dnode_get_path(if_dnode->parent, newpath,
|
||||
yang_dnode_get_path(lyd_parent(if_dnode), newpath,
|
||||
sizeof(newpath));
|
||||
nb_running_move_tree(oldpath, newpath);
|
||||
running_config->version++;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
375
lib/northbound.c
375
lib/northbound.c
@ -83,14 +83,14 @@ static int nb_transaction_process(enum nb_event event,
|
||||
char *errmsg, size_t errmsg_len);
|
||||
static void nb_transaction_apply_finish(struct nb_transaction *transaction,
|
||||
char *errmsg, size_t errmsg_len);
|
||||
static int nb_oper_data_iter_node(const struct lys_node *snode,
|
||||
static int nb_oper_data_iter_node(const struct lysc_node *snode,
|
||||
const char *xpath, const void *list_entry,
|
||||
const struct yang_list_keys *list_keys,
|
||||
struct yang_translator *translator,
|
||||
bool first, uint32_t flags,
|
||||
nb_oper_data_cb cb, void *arg);
|
||||
|
||||
static int nb_node_check_config_only(const struct lys_node *snode, void *arg)
|
||||
static int nb_node_check_config_only(const struct lysc_node *snode, void *arg)
|
||||
{
|
||||
bool *config_only = arg;
|
||||
|
||||
@ -102,10 +102,10 @@ static int nb_node_check_config_only(const struct lys_node *snode, void *arg)
|
||||
return YANG_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static int nb_node_new_cb(const struct lys_node *snode, void *arg)
|
||||
static int nb_node_new_cb(const struct lysc_node *snode, void *arg)
|
||||
{
|
||||
struct nb_node *nb_node;
|
||||
struct lys_node *sparent, *sparent_list;
|
||||
struct lysc_node *sparent, *sparent_list;
|
||||
|
||||
nb_node = XCALLOC(MTYPE_NB_NODE, sizeof(*nb_node));
|
||||
yang_snode_get_path(snode, YANG_PATH_DATA, nb_node->xpath,
|
||||
@ -129,10 +129,7 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg)
|
||||
SET_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY);
|
||||
}
|
||||
if (CHECK_FLAG(snode->nodetype, LYS_LIST)) {
|
||||
struct lys_node_list *slist;
|
||||
|
||||
slist = (struct lys_node_list *)snode;
|
||||
if (slist->keys_size == 0)
|
||||
if (yang_snode_num_keys(snode) == 0)
|
||||
SET_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST);
|
||||
}
|
||||
|
||||
@ -142,18 +139,18 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg)
|
||||
*/
|
||||
nb_node->snode = snode;
|
||||
assert(snode->priv == NULL);
|
||||
lys_set_private(snode, nb_node);
|
||||
((struct lysc_node *)snode)->priv = nb_node;
|
||||
|
||||
return YANG_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static int nb_node_del_cb(const struct lys_node *snode, void *arg)
|
||||
static int nb_node_del_cb(const struct lysc_node *snode, void *arg)
|
||||
{
|
||||
struct nb_node *nb_node;
|
||||
|
||||
nb_node = snode->priv;
|
||||
if (nb_node) {
|
||||
lys_set_private(snode, NULL);
|
||||
((struct lysc_node *)snode)->priv = NULL;
|
||||
XFREE(MTYPE_NB_NODE, nb_node);
|
||||
}
|
||||
|
||||
@ -170,15 +167,15 @@ void nb_nodes_delete(void)
|
||||
yang_snodes_iterate(NULL, nb_node_del_cb, 0, NULL);
|
||||
}
|
||||
|
||||
struct nb_node *nb_node_find(const char *xpath)
|
||||
struct nb_node *nb_node_find(const char *path)
|
||||
{
|
||||
const struct lys_node *snode;
|
||||
const struct lysc_node *snode;
|
||||
|
||||
/*
|
||||
* Use libyang to find the schema node associated to the xpath and get
|
||||
* Use libyang to find the schema node associated to the path and get
|
||||
* the northbound node from there (snode private pointer).
|
||||
*/
|
||||
snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0);
|
||||
snode = lys_find_path(ly_native_ctx, NULL, path, 0);
|
||||
if (!snode)
|
||||
return NULL;
|
||||
|
||||
@ -288,7 +285,7 @@ static unsigned int nb_node_validate_priority(const struct nb_node *nb_node)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nb_node_validate(const struct lys_node *snode, void *arg)
|
||||
static int nb_node_validate(const struct lysc_node *snode, void *arg)
|
||||
{
|
||||
struct nb_node *nb_node = snode->priv;
|
||||
unsigned int *errors = arg;
|
||||
@ -339,7 +336,7 @@ int nb_config_merge(struct nb_config *config_dst, struct nb_config *config_src,
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lyd_merge(config_dst->dnode, config_src->dnode, LYD_OPT_EXPLICIT);
|
||||
ret = lyd_merge_tree(&config_dst->dnode, config_src->dnode, 0);
|
||||
if (ret != 0)
|
||||
flog_warn(EC_LIB_LIBYANG, "%s: lyd_merge() failed", __func__);
|
||||
|
||||
@ -451,7 +448,7 @@ static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq,
|
||||
switch (dnode->schema->nodetype) {
|
||||
case LYS_LEAF:
|
||||
case LYS_LEAFLIST:
|
||||
if (lyd_wd_default((struct lyd_node_leaf_list *)dnode))
|
||||
if (lyd_is_default(dnode))
|
||||
break;
|
||||
|
||||
if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
|
||||
@ -470,7 +467,7 @@ static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq,
|
||||
dnode);
|
||||
|
||||
/* Process child nodes recursively. */
|
||||
LY_TREE_FOR (dnode->child, child) {
|
||||
LY_LIST_FOR (lyd_child(dnode), child) {
|
||||
nb_config_diff_created(child, seq, changes);
|
||||
}
|
||||
break;
|
||||
@ -497,52 +494,142 @@ static void nb_config_diff_deleted(const struct lyd_node *dnode, uint32_t *seq,
|
||||
* do is to call the "destroy" callbacks of their child nodes
|
||||
* when applicable (i.e. optional nodes).
|
||||
*/
|
||||
LY_TREE_FOR (dnode->child, child) {
|
||||
LY_LIST_FOR (lyd_child(dnode), child) {
|
||||
nb_config_diff_deleted(child, seq, changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int nb_lyd_diff_get_op(const struct lyd_node *dnode)
|
||||
{
|
||||
const struct lyd_meta *meta;
|
||||
LY_LIST_FOR (dnode->meta, meta) {
|
||||
if (strcmp(meta->name, "operation")
|
||||
|| strcmp(meta->annotation->module->name, "yang"))
|
||||
continue;
|
||||
return lyd_get_meta_value(meta)[0];
|
||||
}
|
||||
return 'n';
|
||||
}
|
||||
|
||||
static inline void nb_config_diff_dnode_log_path(const char *context,
|
||||
const char *path,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
if (dnode->schema->nodetype & LYD_NODE_TERM)
|
||||
zlog_debug("nb_config_diff: %s: %s: %s", context, path,
|
||||
lyd_get_value(dnode));
|
||||
else
|
||||
zlog_debug("nb_config_diff: %s: %s", context, path);
|
||||
}
|
||||
|
||||
static inline void nb_config_diff_dnode_log(const char *context,
|
||||
const struct lyd_node *dnode)
|
||||
{
|
||||
if (!dnode) {
|
||||
zlog_debug("nb_config_diff: %s: NULL", context);
|
||||
return;
|
||||
}
|
||||
|
||||
char *path = lyd_path(dnode, LYD_PATH_STD, NULL, 0);
|
||||
nb_config_diff_dnode_log_path(context, path, dnode);
|
||||
free(path);
|
||||
}
|
||||
|
||||
/* Calculate the delta between two different configurations. */
|
||||
static void nb_config_diff(const struct nb_config *config1,
|
||||
const struct nb_config *config2,
|
||||
struct nb_config_cbs *changes)
|
||||
{
|
||||
struct lyd_difflist *diff;
|
||||
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();
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
400
lib/yang.c
400
lib/yang.c
@ -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;
|
||||
}
|
||||
|
143
lib/yang.h
143
lib/yang.h
@ -99,13 +99,10 @@ enum yang_iter_flags {
|
||||
|
||||
/* Filter RPC input/output nodes. */
|
||||
YANG_ITER_FILTER_INPUT_OUTPUT = (1<<2),
|
||||
|
||||
/* Filter implicitely created nodes. */
|
||||
YANG_ITER_FILTER_IMPLICIT = (1<<3),
|
||||
};
|
||||
|
||||
/* Callback used by the yang_snodes_iterate_*() family of functions. */
|
||||
typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg);
|
||||
typedef int (*yang_iterate_cb)(const struct lysc_node *snode, void *arg);
|
||||
|
||||
/* Callback used by the yang_dnode_iterate() function. */
|
||||
typedef int (*yang_dnode_iter_cb)(const struct lyd_node *dnode, void *arg);
|
||||
@ -180,7 +177,7 @@ extern void yang_module_embed(struct yang_module_embed *embed);
|
||||
* Returns:
|
||||
* The return value of the last called callback.
|
||||
*/
|
||||
extern int yang_snodes_iterate_subtree(const struct lys_node *snode,
|
||||
extern int yang_snodes_iterate_subtree(const struct lysc_node *snode,
|
||||
const struct lys_module *module,
|
||||
yang_iterate_cb cb, uint16_t flags,
|
||||
void *arg);
|
||||
@ -222,7 +219,7 @@ extern int yang_snodes_iterate(const struct lys_module *module,
|
||||
* xpath_len
|
||||
* Size of the xpath buffer.
|
||||
*/
|
||||
extern void yang_snode_get_path(const struct lys_node *snode,
|
||||
extern void yang_snode_get_path(const struct lysc_node *snode,
|
||||
enum yang_path_type type, char *xpath,
|
||||
size_t xpath_len);
|
||||
|
||||
@ -236,7 +233,7 @@ extern void yang_snode_get_path(const struct lys_node *snode,
|
||||
* Returns:
|
||||
* The parent libyang schema node if found, or NULL if not found.
|
||||
*/
|
||||
extern struct lys_node *yang_snode_real_parent(const struct lys_node *snode);
|
||||
extern struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode);
|
||||
|
||||
/*
|
||||
* Find first parent schema node which is a list.
|
||||
@ -247,7 +244,7 @@ extern struct lys_node *yang_snode_real_parent(const struct lys_node *snode);
|
||||
* Returns:
|
||||
* The parent libyang schema node (list) if found, or NULL if not found.
|
||||
*/
|
||||
extern struct lys_node *yang_snode_parent_list(const struct lys_node *snode);
|
||||
extern struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode);
|
||||
|
||||
/*
|
||||
* Check if the libyang schema node represents typeless data (e.g. containers,
|
||||
@ -259,7 +256,7 @@ extern struct lys_node *yang_snode_parent_list(const struct lys_node *snode);
|
||||
* Returns:
|
||||
* true if the schema node represents typeless data, false otherwise.
|
||||
*/
|
||||
extern bool yang_snode_is_typeless_data(const struct lys_node *snode);
|
||||
extern bool yang_snode_is_typeless_data(const struct lysc_node *snode);
|
||||
|
||||
/*
|
||||
* Get the default value associated to a YANG leaf or leaf-list.
|
||||
@ -270,7 +267,7 @@ extern bool yang_snode_is_typeless_data(const struct lys_node *snode);
|
||||
* Returns:
|
||||
* The default value if it exists, NULL otherwise.
|
||||
*/
|
||||
extern const char *yang_snode_get_default(const struct lys_node *snode);
|
||||
extern const char *yang_snode_get_default(const struct lysc_node *snode);
|
||||
|
||||
/*
|
||||
* Get the type structure of a leaf of leaf-list. If the type is a leafref, the
|
||||
@ -283,7 +280,27 @@ extern const char *yang_snode_get_default(const struct lys_node *snode);
|
||||
* The found type if the schema node represents a leaf or a leaf-list, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
extern const struct lys_type *yang_snode_get_type(const struct lys_node *snode);
|
||||
extern const struct lysc_type *
|
||||
yang_snode_get_type(const struct lysc_node *snode);
|
||||
|
||||
/*
|
||||
* Get the number of key nodes for the given list.
|
||||
*
|
||||
* snode
|
||||
* libyang (LYS_LIST) schema node to operate on.
|
||||
*
|
||||
* Returns:
|
||||
* The number of key LYS_LEAFs as children of this list node.
|
||||
*/
|
||||
extern unsigned int yang_snode_num_keys(const struct lysc_node *snode);
|
||||
|
||||
#define LY_FOR_KEYS(snode, skey) \
|
||||
for ((skey) = (const struct lysc_node_leaf *)lysc_node_child((snode)); \
|
||||
(skey); (skey) = (const struct lysc_node_leaf *)((skey)->next)) \
|
||||
if (!lysc_is_key(skey)) { \
|
||||
break; \
|
||||
} else
|
||||
|
||||
|
||||
/*
|
||||
* Build data path of the data node.
|
||||
@ -322,14 +339,49 @@ extern const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
|
||||
* dnode
|
||||
* Base libyang data node to operate on.
|
||||
*
|
||||
* xpath_fmt
|
||||
* XPath expression (absolute or relative).
|
||||
* xpath
|
||||
* Limited XPath (absolute or relative) string. See Path in libyang
|
||||
* documentation for restrictions.
|
||||
*
|
||||
* Returns:
|
||||
* The libyang data node if found, or NULL if not found.
|
||||
*/
|
||||
extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
|
||||
const char *xpath_fmt, ...);
|
||||
const char *xpath);
|
||||
|
||||
/*
|
||||
* Find a libyang data node by its YANG data path.
|
||||
*
|
||||
* dnode
|
||||
* Base libyang data node to operate on.
|
||||
*
|
||||
* xpath_fmt
|
||||
* Limited XPath (absolute or relative) format string. See Path in libyang
|
||||
* documentation for restrictions.
|
||||
*
|
||||
* ...
|
||||
* any parameters for xpath_fmt.
|
||||
*
|
||||
* Returns:
|
||||
* The libyang data node if found, or NULL if not found.
|
||||
*/
|
||||
extern struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode,
|
||||
const char *path_fmt, ...);
|
||||
|
||||
/*
|
||||
* Check if a libyang data node exists.
|
||||
*
|
||||
* dnode
|
||||
* Base libyang data node to operate on.
|
||||
*
|
||||
* xpath
|
||||
* Limited XPath (absolute or relative) string. See Path in libyang
|
||||
* documentation for restrictions.
|
||||
*
|
||||
* Returns:
|
||||
* true if a libyang data node was found, false otherwise.
|
||||
*/
|
||||
extern bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath);
|
||||
|
||||
/*
|
||||
* Check if a libyang data node exists.
|
||||
@ -338,13 +390,17 @@ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
|
||||
* Base libyang data node to operate on.
|
||||
*
|
||||
* xpath_fmt
|
||||
* XPath expression (absolute or relative).
|
||||
* Limited XPath (absolute or relative) format string. See Path in
|
||||
* libyang documentation for restrictions.
|
||||
*
|
||||
* ...
|
||||
* any parameters for xpath_fmt.
|
||||
*
|
||||
* Returns:
|
||||
* true if the libyang data node was found, false otherwise.
|
||||
* true if a libyang data node was found, false otherwise.
|
||||
*/
|
||||
extern bool yang_dnode_exists(const struct lyd_node *dnode,
|
||||
const char *xpath_fmt, ...);
|
||||
extern bool yang_dnode_existsf(const struct lyd_node *dnode,
|
||||
const char *xpath_fmt, ...);
|
||||
|
||||
/*
|
||||
* Iterate over all libyang data nodes that satisfy an XPath query.
|
||||
@ -360,6 +416,9 @@ extern bool yang_dnode_exists(const struct lyd_node *dnode,
|
||||
*
|
||||
* xpath_fmt
|
||||
* XPath expression (absolute or relative).
|
||||
*
|
||||
* ...
|
||||
* any parameters for xpath_fmt.
|
||||
*/
|
||||
void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
|
||||
const struct lyd_node *dnode, const char *xpath_fmt,
|
||||
@ -372,7 +431,7 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
|
||||
* dnode
|
||||
* Base libyang data node to operate on.
|
||||
*
|
||||
* xpath_fmt
|
||||
* xpath
|
||||
* Optional XPath expression (absolute or relative) to specify a different
|
||||
* data node to operate on in the same data tree.
|
||||
*
|
||||
@ -380,7 +439,27 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
|
||||
* true if the data node contains the default value, false otherwise.
|
||||
*/
|
||||
extern bool yang_dnode_is_default(const struct lyd_node *dnode,
|
||||
const char *xpath_fmt, ...);
|
||||
const char *xpath);
|
||||
|
||||
/*
|
||||
* Check if the libyang data node contains a default value. Non-presence
|
||||
* containers are assumed to always contain a default value.
|
||||
*
|
||||
* dnode
|
||||
* Base libyang data node to operate on.
|
||||
*
|
||||
* xpath
|
||||
* Optional limited XPath (absolute or relative) format string. See Path in
|
||||
* libyang documentation for restrictions.
|
||||
*
|
||||
* ...
|
||||
* any parameters for xpath_fmt.
|
||||
*
|
||||
* Returns:
|
||||
* true if the data node contains the default value, false otherwise.
|
||||
*/
|
||||
extern bool yang_dnode_is_defaultf(const struct lyd_node *dnode,
|
||||
const char *xpath_fmt, ...);
|
||||
|
||||
/*
|
||||
* Check if the libyang data node and all of its children contain default
|
||||
@ -437,7 +516,8 @@ extern struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode);
|
||||
* Delete a libyang data node.
|
||||
*
|
||||
* dnode
|
||||
* Pointer to the libyang data node that is going to be deleted.
|
||||
* Pointer to the libyang data node that is going to be deleted along with
|
||||
* the entire tree it belongs to.
|
||||
*/
|
||||
extern void yang_dnode_free(struct lyd_node *dnode);
|
||||
|
||||
@ -493,8 +573,13 @@ extern struct yang_data *yang_data_list_find(const struct list *list,
|
||||
*
|
||||
* embedded_modules
|
||||
* Specify whether libyang should attempt to look for embedded YANG modules.
|
||||
*
|
||||
* explicit_compile
|
||||
* True if the caller will later call ly_ctx_compile to compile all loaded
|
||||
* modules at once.
|
||||
*/
|
||||
extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules);
|
||||
extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules,
|
||||
bool explicit_compile);
|
||||
|
||||
/*
|
||||
* Enable or disable libyang verbose debugging.
|
||||
@ -528,8 +613,16 @@ extern const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf,
|
||||
*
|
||||
* embedded_modules
|
||||
* Specify whether libyang should attempt to look for embedded YANG modules.
|
||||
* defer_compile
|
||||
* Hold off on compiling modules until yang_init_loading_complete is called.
|
||||
*/
|
||||
extern void yang_init(bool embedded_modules);
|
||||
extern void yang_init(bool embedded_modules, bool defer_compile);
|
||||
|
||||
/*
|
||||
* Should be called after yang_init and all yang_module_load()s have been done,
|
||||
* compiles all modules loaded into the yang context.
|
||||
*/
|
||||
extern void yang_init_loading_complete(void);
|
||||
|
||||
/*
|
||||
* Finish the YANG subsystem gracefully. Should be called only when the daemon
|
||||
@ -583,10 +676,6 @@ extern uint32_t yang_get_list_pos(const struct lyd_node *node);
|
||||
*/
|
||||
extern uint32_t yang_get_list_elements_count(const struct lyd_node *node);
|
||||
|
||||
|
||||
/* To get the immediate child of a dnode */
|
||||
const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode);
|
||||
|
||||
/* API to check if the given node is last node in the list */
|
||||
bool yang_is_last_list_dnode(const struct lyd_node *dnode);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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, ...)
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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, "."))) ||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
10
ripd/ripd.c
10
ripd/ripd.c
@ -3632,16 +3632,16 @@ static int rip_vrf_enable(struct vrf *vrf)
|
||||
char oldpath[XPATH_MAXLEN];
|
||||
char newpath[XPATH_MAXLEN];
|
||||
|
||||
rip_dnode = yang_dnode_get(
|
||||
rip_dnode = yang_dnode_getf(
|
||||
running_config->dnode,
|
||||
"/frr-ripd:ripd/instance[vrf='%s']/vrf",
|
||||
old_vrf_name);
|
||||
if (rip_dnode) {
|
||||
yang_dnode_get_path(rip_dnode->parent, oldpath,
|
||||
sizeof(oldpath));
|
||||
yang_dnode_get_path(lyd_parent(rip_dnode),
|
||||
oldpath, sizeof(oldpath));
|
||||
yang_dnode_change_leaf(rip_dnode, vrf->name);
|
||||
yang_dnode_get_path(rip_dnode->parent, newpath,
|
||||
sizeof(newpath));
|
||||
yang_dnode_get_path(lyd_parent(rip_dnode),
|
||||
newpath, sizeof(newpath));
|
||||
nb_running_move_tree(oldpath, newpath);
|
||||
running_config->version++;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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")
|
||||
|
@ -13,8 +13,6 @@ submodule frr-bgp-bmp {
|
||||
prefix frr-bt;
|
||||
}
|
||||
|
||||
include frr-bgp-common-multiprotocol;
|
||||
|
||||
organization
|
||||
"FRRouting";
|
||||
contact
|
||||
|
@ -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.";
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,6 @@ submodule frr-bgp-neighbor {
|
||||
prefix "bgp";
|
||||
}
|
||||
|
||||
include frr-bgp-common-structure;
|
||||
include frr-bgp-common-multiprotocol;
|
||||
|
||||
organization
|
||||
"FRRouting";
|
||||
contact
|
||||
|
@ -13,9 +13,6 @@ submodule frr-bgp-peer-group {
|
||||
prefix frr-bt;
|
||||
}
|
||||
|
||||
include frr-bgp-common-structure;
|
||||
include frr-bgp-neighbor;
|
||||
|
||||
organization
|
||||
"FRRouting";
|
||||
contact
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.";
|
||||
}
|
||||
|
@ -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")';
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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";
|
||||
|
@ -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.";
|
||||
|
Loading…
Reference in New Issue
Block a user