summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn_mh.h5
-rw-r--r--bgpd/bgp_mplsvpn.c19
-rw-r--r--bgpd/bgp_packet.c3
-rw-r--r--bgpd/bgp_route.c27
-rw-r--r--bgpd/bgp_vty.c11
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--bgpd/bgp_zebra.h2
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/rfapi/rfapi_vty.c29
-rw-r--r--doc/developer/northbound/plugins-sysrepo.rst213
-rw-r--r--doc/developer/rcu.rst9
-rw-r--r--doc/user/bgp.rst12
-rw-r--r--doc/user/mgmtd.rst12
-rw-r--r--doc/user/routemap.rst8
-rw-r--r--doc/user/zebra.rst4
-rw-r--r--lib/filter_cli.c58
-rw-r--r--lib/if.c25
-rw-r--r--lib/if.h1
-rw-r--r--lib/northbound_sysrepo.c11
-rw-r--r--lib/plist.c40
-rw-r--r--lib/routemap_cli.c12
-rw-r--r--lib/routing_nb.c10
-rw-r--r--lib/routing_nb.h1
-rw-r--r--lib/sockopt.c3
-rw-r--r--lib/vrf.c18
-rw-r--r--lib/vrf.h1
-rw-r--r--lib/vty.h4
-rw-r--r--lib/yang.c3
-rw-r--r--mgmtd/mgmt_fe_adapter.c3
-rw-r--r--mgmtd/mgmt_main.c19
-rw-r--r--mgmtd/mgmt_txn.c28
-rw-r--r--mgmtd/subdir.am2
-rw-r--r--nhrpd/netlink_arp.c5
-rw-r--r--ospf6d/ospf6_area.c4
-rw-r--r--ospf6d/ospf6_interface.c4
-rw-r--r--ospfd/ospf_vty.c4
-rw-r--r--pimd/pim6_cmd.c8
-rw-r--r--pimd/pim_cmd.c14
-rw-r--r--staticd/static_zebra.c6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json2
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf17
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf10
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/setup_vrfs1
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py313
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt2
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt2
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt4
-rw-r--r--vtysh/vtysh.c30
-rw-r--r--vtysh/vtysh_config.c10
-rw-r--r--zebra/rib.h26
-rw-r--r--zebra/zebra_cli.c17
-rw-r--r--zebra/zebra_evpn_mh.h2
-rw-r--r--zebra/zebra_nb_config.c10
53 files changed, 784 insertions, 308 deletions
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index ee1f74989b..cebabb9fd0 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -388,11 +388,6 @@ static inline bool bgp_evpn_attr_is_local_es(struct attr *attr)
return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false;
}
-static inline uint32_t bgp_evpn_attr_get_df_pref(struct attr *attr)
-{
- return (attr) ? attr->df_pref : 0;
-}
-
static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es)
{
return (es->flags & BGP_EVPNES_OPER_UP)
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 32436861f4..cd5cf5be54 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -2209,12 +2209,22 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
/* If the path has accept-own community and the source VRF
* is valid, reset next-hop to self, to allow importing own
* routes between different VRFs on the same node.
- * Set the nh ifindex to VRF's interface, not the real interface.
+ */
+
+ if (src_bgp)
+ subgroup_announce_reset_nhop(nhfamily, &static_attr);
+
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
+
+ /* The nh ifindex may not be defined (when the route is
+ * imported from the network statement => BGP_ROUTE_STATIC)
+ * or to the real interface.
+ * Rewrite the nh ifindex to VRF's interface.
* Let the kernel to decide with double lookup the real next-hop
* interface when installing the route.
*/
- if (src_bgp) {
- subgroup_announce_reset_nhop(nhfamily, &static_attr);
+ if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC ||
+ bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) {
ifp = if_get_vrf_loopback(src_vrf->vrf_id);
if (ifp)
static_attr.nh_ifindex = ifp->ifindex;
@@ -2300,9 +2310,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
*/
if (!CHECK_FLAG(to_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
- /* work back to original route */
- bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
-
/*
* if original route was unicast,
* then it did not arrive over vpn
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index f94b64d0bd..9d484d901a 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1534,7 +1534,8 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
iana_safi2str(pkt_safi));
break;
case CAPABILITY_CODE_FQDN:
- if (hostname) {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN) &&
+ hostname) {
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, action);
stream_putc(s, CAPABILITY_CODE_FQDN);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b8d6c660b7..32d822aad7 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3520,7 +3520,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
*/
if (old_select &&
is_route_parent_evpn(old_select))
- bgp_zebra_withdraw(p, old_select, bgp, safi);
+ bgp_zebra_withdraw(p, old_select, bgp, afi,
+ safi);
bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
} else {
@@ -3530,7 +3531,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
- bgp_zebra_withdraw(p, old_select, bgp, safi);
+ bgp_zebra_withdraw(p, old_select, bgp, afi,
+ safi);
}
}
@@ -4185,7 +4187,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
int aspath_loop_count = 0;
struct bgp_dest *dest;
struct bgp *bgp;
- struct attr new_attr;
+ struct attr new_attr = {};
struct attr *attr_new;
struct bgp_path_info *pi;
struct bgp_path_info *new = NULL;
@@ -4218,10 +4220,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (orig_safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
- memset(&new_attr, 0, sizeof(new_attr));
- new_attr.label_index = BGP_INVALID_LABEL_INDEX;
- new_attr.label = MPLS_INVALID_LABEL;
-
bgp = peer->bgp;
dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
/* TODO: Check to see if we can get rid of "is_valid_label" */
@@ -4431,7 +4429,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
/* remove from RIB previous entry */
- bgp_zebra_withdraw(p, pi, bgp, safi);
+ bgp_zebra_withdraw(p, pi, bgp, afi, safi);
}
if (peer->sort == BGP_PEER_EBGP) {
@@ -6033,7 +6031,7 @@ bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
}
static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
- safi_t safi)
+ afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
struct bgp_path_info *pi;
@@ -6057,7 +6055,8 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
|| pi->sub_type == BGP_ROUTE_IMPORTED)) {
if (bgp_fibupd_safi(safi))
- bgp_zebra_withdraw(p, pi, bgp, safi);
+ bgp_zebra_withdraw(p, pi, bgp, afi,
+ safi);
}
dest = bgp_path_info_reap(dest, pi);
@@ -6075,7 +6074,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
if (afi == AFI_L2VPN)
continue;
- bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
+ bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST], afi,
SAFI_UNICAST);
/*
* VPN and ENCAP and EVPN tables are two-level (RD is top level)
@@ -6087,7 +6086,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, safi);
+ bgp_cleanup_table(bgp, table, afi, safi);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
dest = bgp_dest_unlock_node(dest);
@@ -6100,7 +6099,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, safi);
+ bgp_cleanup_table(bgp, table, afi, safi);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
dest = bgp_dest_unlock_node(dest);
@@ -6114,7 +6113,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, SAFI_EVPN);
+ bgp_cleanup_table(bgp, table, afi, SAFI_EVPN);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
dest = bgp_dest_unlock_node(dest);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 09f9667a9a..33884d0452 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -5746,17 +5746,24 @@ DEFPY (neighbor_capability_fqdn,
"Advertise fqdn capability to the peer\n")
{
struct peer *peer;
+ int ret;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
if (no)
- return peer_flag_unset_vty(vty, neighbor,
+ ret = peer_flag_unset_vty(vty, neighbor,
PEER_FLAG_CAPABILITY_FQDN);
else
- return peer_flag_set_vty(vty, neighbor,
+ ret = peer_flag_set_vty(vty, neighbor,
PEER_FLAG_CAPABILITY_FQDN);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_FQDN,
+ no ? CAPABILITY_ACTION_UNSET
+ : CAPABILITY_ACTION_SET);
+
+ return ret;
}
/* neighbor capability extended next hop encoding */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 0db0ac4873..dcbb87e969 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1724,7 +1724,7 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
}
void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
- struct bgp *bgp, safi_t safi)
+ struct bgp *bgp, afi_t afi, safi_t safi)
{
struct zapi_route api;
struct peer *peer;
@@ -1743,7 +1743,7 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
if (safi == SAFI_FLOWSPEC) {
peer = info->peer;
- bgp_pbr_update_entry(peer->bgp, p, info, AFI_IP, safi, false);
+ bgp_pbr_update_entry(peer->bgp, p, info, afi, safi, false);
return;
}
@@ -1784,7 +1784,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
&& (pi->type == ZEBRA_ROUTE_BGP))
bgp_zebra_withdraw(bgp_dest_get_prefix(dest),
- pi, bgp, safi);
+ pi, bgp, afi, safi);
}
}
}
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 4696e4dc44..396c8335f8 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -34,7 +34,7 @@ extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi);
extern void bgp_zebra_withdraw(const struct prefix *p,
struct bgp_path_info *path, struct bgp *bgp,
- safi_t safi);
+ afi_t afi, safi_t safi);
/* Announce routes of any bgp subtype of a table to zebra */
extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 58514566ef..b8517199af 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4574,7 +4574,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_AIGP, 0, peer_change_none},
{PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
- {PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_reset},
+ {PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 8e88550ddf..5da99dbc4e 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -419,22 +419,21 @@ void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
else
vty_out(vty, " label=%u",
decode_label(&bpi->extra->label[0]));
+ }
- if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
- struct in6_addr *sid_tmp =
- bpi->attr->srv6_l3vpn
- ? (&bpi->attr->srv6_l3vpn->sid)
- : (&bpi->attr->srv6_vpn->sid);
- vty_out(vty, " sid=%pI6", sid_tmp);
-
- if (bpi->attr->srv6_l3vpn &&
- bpi->attr->srv6_l3vpn->loc_block_len != 0) {
- vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
- bpi->attr->srv6_l3vpn->loc_block_len,
- bpi->attr->srv6_l3vpn->loc_node_len,
- bpi->attr->srv6_l3vpn->func_len,
- bpi->attr->srv6_l3vpn->arg_len);
- }
+ if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
+ struct in6_addr *sid_tmp =
+ bpi->attr->srv6_l3vpn ? (&bpi->attr->srv6_l3vpn->sid)
+ : (&bpi->attr->srv6_vpn->sid);
+ vty_out(vty, " sid=%pI6", sid_tmp);
+
+ if (bpi->attr->srv6_l3vpn &&
+ bpi->attr->srv6_l3vpn->loc_block_len != 0) {
+ vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
+ bpi->attr->srv6_l3vpn->loc_block_len,
+ bpi->attr->srv6_l3vpn->loc_node_len,
+ bpi->attr->srv6_l3vpn->func_len,
+ bpi->attr->srv6_l3vpn->arg_len);
}
}
diff --git a/doc/developer/northbound/plugins-sysrepo.rst b/doc/developer/northbound/plugins-sysrepo.rst
index 1797157573..0cfdb825e5 100644
--- a/doc/developer/northbound/plugins-sysrepo.rst
+++ b/doc/developer/northbound/plugins-sysrepo.rst
@@ -1,140 +1,193 @@
-Plugins Sysrepo (old)
-=====================
+Plugins Sysrepo
+===============
Installation
------------
Required dependencies
^^^^^^^^^^^^^^^^^^^^^
+Install FRR build required dependencies, check `Building FRR
+<https://docs.frrouting.org/projects/dev-guide/en/latest/building.html>`_ document for specific platform required packages.
+Below are debian systems required packages:
-::
+.. code-block:: console
- # apt-get install git cmake build-essential bison flex libpcre3-dev libev-dev \
- libavl-dev libprotobuf-c-dev protobuf-c-compiler libcmocka0 \
- libcmocka-dev doxygen libssl-dev libssl-dev libssh-dev
+ sudo apt-get install git autoconf automake libtool make \
+ libprotobuf-c-dev protobuf-c-compiler build-essential \
+ python3-dev python3-pytest python3-sphinx libjson-c-dev \
+ libelf-dev libreadline-dev cmake libcap-dev bison flex \
+ pkg-config texinfo gdb libgrpc-dev python3-grpc-tools libpcre2-dev
libyang
^^^^^^^
-::
+.. note::
- # apt-get install libyang0.16 libyang-dev
+ FRR requires version 2.1.128 or newer, in this document we will
+ be compiling and installing libyang version 2.1.148.
-Sysrepo
-^^^^^^^
+.. code-block:: console
-::
+ git clone https://github.com/CESNET/libyang.git
+ cd libyang
+ git checkout v2.1.148
+ mkdir build; cd build
+ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ -DCMAKE_BUILD_TYPE:String="Release" ..
+ make
+ sudo make install
- $ git clone https://github.com/sysrepo/sysrepo.git
- $ cd sysrepo/
- $ mkdir build; cd build
- $ cmake -DCMAKE_BUILD_TYPE=Release -DGEN_LANGUAGE_BINDINGS=OFF .. && make
- # make install
+Sysrepo
+^^^^^^^
-libnetconf2
-^^^^^^^^^^^
+.. note::
-::
+ The following code block assumes you have installed libyang v2.1.148, if you have
+ libyang v2.1.128 change sysrepo version to 2.2.105.
- $ git clone https://github.com/CESNET/libnetconf2.git
- $ cd libnetconf2/
- $ mkdir build; cd build
- $ cmake .. && make
- # make install
+.. code-block:: console
-netopeer2
-^^^^^^^^^
+ git clone https://github.com/sysrepo/sysrepo.git
+ cd sysrepo/
+ git checkout v2.2.150
+ mkdir build; cd build
+ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ -DCMAKE_BUILD_TYPE:String="Release" ..
+ make
+ sudo make install
-::
+Verify that sysrepo is installed correctly:
- $ git clone https://github.com/CESNET/Netopeer2.git
- $ cd Netopeer2
- $ cd server
- $ mkdir build; cd build
- $ cmake .. && make
- # make install
+.. code-block:: console
-**Note:** If ``make install`` fails as it can’t find
-``libsysrepo.so.0.7``, then run ``ldconfig`` and try again as it might
-not have updated the lib search path
+ sudo sysrepoctl -l
FRR
^^^
-Build and install FRR using the ``--enable-sysrepo`` configure-time
-option.
+Follow the steps of `Building FRR
+<https://docs.frrouting.org/projects/dev-guide/en/latest/building.html>`_
+
+
+Make sure to use ``--enable-sysrepo`` configure-time option while building FRR.
+
+Below is an example of frr configure-time options, your options
+might vary, however in order to allow sysrepo plugin you have
+to keep ``--enable-sysrepo`` option:
+
+.. code-block:: console
+
+ ./bootstrap.sh
+ ./configure \
+ --localstatedir=/var/opt/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-fpm \
+ --enable-sysrepo \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
Initialization
--------------
-Install the FRR YANG modules in the Sysrepo datastore:
-
-::
+Install FRR YANG modules in Sysrepo datastore:
- # sysrepoctl --install /usr/local/share/yang/ietf-interfaces@2018-01-09.yang
- # sysrepoctl --install /usr/local/share/yang/frr-vrf.yang
- # sysrepoctl --install /usr/local/share/yang/frr-interface.yang
- # sysrepoctl --install /usr/local/share/yang/frr-route-types.yang
- # sysrepoctl --install /usr/local/share/yang/frr-filter.yang
- # sysrepoctl --install /usr/local/share/yang/frr-route-map.yang
- # sysrepoctl --install /usr/local/share/yang/frr-isisd.yang
- # sysrepoctl --install /usr/local/share/yang/frr-ripd.yang
- # sysrepoctl --install /usr/local/share/yang/frr-ripngd.yang
- # sysrepoctl -c frr-vrf --owner frr --group frr
- # sysrepoctl -c frr-interface --owner frr --group frr
- # sysrepoctl -c frr-route-types --owner frr --group frr
- # sysrepoctl -c frr-filter --owner frr --group frr
- # sysrepoctl -c frr-route-map --owner frr --group frr
- # sysrepoctl -c frr-isisd --owner frr --group frr
- # sysrepoctl -c frr-ripd --owner frr --group frr
- # sysrepoctl -c frr-ripngd --owner frr --group frr
+.. code-block:: console
-Start netopeer2-server:
+ cd frr/yang/
+ sudo sysrepoctl -i ./ietf/ietf-interfaces.yang -o frr -g frr
+ sudo sysrepoctl -i frr-vrf.yang -o frr -g frr
+ sudo sysrepoctl -i frr-interface.yang -o frr -g frr
+ sudo sysrepoctl -i frr-route-types.yang -o frr -g frr
+ sudo sysrepoctl -i frr-filter.yang -o frr -g frr
+ sudo sysrepoctl -i frr-route-map.yang -o frr -g frr
+ sudo sysrepoctl -i frr-isisd.yang -o frr -g frr
+ sudo sysrepoctl -i frr-bfdd.yang -o frr -g frr
+ sudo sysrepoctl -i ./ietf/ietf-routing-types.yang -o frr -g frr
+ sudo sysrepoctl -i frr-nexthop.yang -o frr -g frr
+ sudo sysrepoctl -i frr-if-rmap.yang -o frr -g frr
+ sudo sysrepoctl -i frr-ripd.yang -o frr -g frr
+ sudo sysrepoctl -i frr-ripngd.yang -o frr -g frr
+ sudo sysrepoctl -i frr-affinity-map.yang -o frr -g frr
+ sudo sysrepoctl -i ./ietf/frr-deviations-ietf-interfaces.yang -o frr -g frr
-::
- # netopeer2-server -d &
+Start FRR daemons with sysrepo plugin:
-Start the FRR daemons with the sysrepo module:
+.. code-block:: console
-::
+ sudo /usr/lib/frr/isisd -M sysrepo --log stdout
- # isisd -M sysrepo --log=stdout
+Any daemon running with ``-M sysrepo`` will subscribe to its frr yang moduels
+on sysrepo and you be able to configure it by editing module configuration on sysrepo.
Managing the configuration
--------------------------
-The following NETCONF scripts can be used to show and edit the FRR
-configuration:
-https://github.com/rzalamena/ietf-hackathon-brazil-201907/tree/master/netconf-scripts
+Testing
+^^^^^^^
-Example:
+To test FRR intergartion with sysrepo, ``sysrepocfg`` tool can be used
+to edit frr configuration on sysrepo
-::
+Example:
- # ./netconf-edit.py 127.0.0.1
- # ./netconf-get-config.py 127.0.0.1
- <?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><isis xmlns="http://frrouting.org/yang/isisd"><instance><area-tag>testnet</area-tag><is-type>level-1</is-type></instance></isis></data>
+Edit sysrepo running datastore configuration for the desiged frr module:
-..
+.. code-block:: console
- NOTE: the ncclient library needs to be installed first:
- ``apt install -y python3-ncclient``
+ sudo sysrepocfg -E nano -d running -m frr-isisd -f json
-The *sysrepocfg* tool can also be used to show/edit the FRR
-configuration. Example:
+Paste the following json configuration:
-::
+.. code-block:: console
- # sysrepocfg --format=json --import=frr-isisd.json --datastore=running frr-isisd
- # sysrepocfg --format=json --export --datastore=running frr-isisd
{
"frr-isisd:isis": {
"instance": [
{
"area-tag": "testnet",
+ "vrf": "default",
"is-type": "level-1"
}
]
}
}
+
+Exit and save config to the same file.
+
+After that, this configuration should get reflected to vtysh:
+
+.. code-block:: console
+
+ show run
+ Building configuration...
+
+ Current configuration:
+ !
+ frr version 9.2-dev-MyOwnFRRVersion
+ frr defaults traditional
+ hostname bullseye
+ !
+ router isis testnet
+ is-type level-1
+ exit
+ !
+ end
+
+NETCONF
+^^^^^^^
+
+To manage sysrepo configuration through netconf
+you can use `netopeer2 <https://github.com/CESNET/netopeer2>`_ as a netfconf server that can
+be easily integrated with sysrepo.
diff --git a/doc/developer/rcu.rst b/doc/developer/rcu.rst
index 4fd56587ae..2335e8faed 100644
--- a/doc/developer/rcu.rst
+++ b/doc/developer/rcu.rst
@@ -232,6 +232,15 @@ Internals
that case, either all of the library's threads must be registered for RCU,
or the code must instead pass a (non-RCU) copy of the data to the library.
+.. c:function:: int frr_pthread_non_controlled_startup(pthread_t thread, const char *name, const char *os_name)
+
+ If a pthread is started outside the control of normal pthreads in frr
+ then frr_pthread_non_controlled_startup should be called. This will
+ properly setup both the pthread with rcu usage as well as some data
+ structures pertaining to the name of the pthread. This is especially
+ important if the pthread created ends up calling back into FRR and
+ one of the various zlog_XXX functions is called.
+
.. c:function:: void rcu_shutdown(void)
Stop the RCU sweeper thread and make sure all cleanup has finished.
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 914e879e31..86d7c402ed 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1626,10 +1626,12 @@ Configuring Peers
.. clicmd:: neighbor PEER update-source <IFNAME|ADDRESS>
- Specify the IPv4 source address to use for the :abbr:`BGP` session to this
- neighbour, may be specified as either an IPv4 address directly or as an
+ Specify the IPv4 or IPv6 source address to use for the :abbr:`BGP` session to this
+ neighbour, may be specified as either an IP address directly or as an
interface name (in which case the *zebra* daemon MUST be running in order
- for *bgpd* to be able to retrieve interface state).
+ for *bgpd* to be able to retrieve interface state). When there are multiple
+ addresses on the choosen IFNAME then BGP will use the address that matches
+ the most number of bits in comparison to the destination peer address.
.. code-block:: frr
@@ -3473,7 +3475,7 @@ The import filtering described in item (2) is constrained just to Type-2
The EVPN MAC-VRF Site-of-Origin can be configured using a single CLI command
under ``address-family l2vpn evpn`` of the EVPN underlay BGP instance.
-.. clicmd:: [no] mac-vrf soo <site-of-origin-string>
+.. clicmd:: mac-vrf soo <site-of-origin-string>
Example configuration:
@@ -3619,7 +3621,7 @@ route maybe fragmented.
The number of EVIs per-EAD route can be configured via the following
BGP command -
-.. clicmd:: [no] ead-es-frag evi-limit (1-1000)
+.. clicmd:: ead-es-frag evi-limit (1-1000)
Sample Configuration
^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/user/mgmtd.rst b/doc/user/mgmtd.rst
index 42bc860b72..aa7ccaac3a 100644
--- a/doc/user/mgmtd.rst
+++ b/doc/user/mgmtd.rst
@@ -371,22 +371,22 @@ MGMT Daemon debug commands
The following debug commands enable debugging within the management daemon:
-.. clicmd:: [no] debug mgmt backend
+.. clicmd:: debug mgmt backend
Enable[/Disable] debugging messages related to backend operations within the
management daemon.
-.. clicmd:: [no] debug mgmt datastore
+.. clicmd:: debug mgmt datastore
Enable[/Disable] debugging messages related to YANG datastore operations
within the management daemon.
-.. clicmd:: [no] debug mgmt frontend
+.. clicmd:: debug mgmt frontend
Enable[/Disable] debugging messages related to frontend operations within the
management daemon.
-.. clicmd:: [no] debug mgmt transaction
+.. clicmd:: debug mgmt transaction
Enable[/Disable] debugging messages related to transactions within the
management daemon.
@@ -398,12 +398,12 @@ MGMT Client debug commands
The following debug commands enable debugging within the management front and
backend clients:
-.. clicmd:: [no] debug mgmt client backend
+.. clicmd:: debug mgmt client backend
Enable[/Disable] debugging messages related to backend operations inside the
backend mgmtd clients.
-.. clicmd:: [no] debug mgmt client frontend
+.. clicmd:: debug mgmt client frontend
Enable[/Disable] debugging messages related to frontend operations inside the
frontend mgmtd clients.
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 18a261d940..791762aa7b 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -380,13 +380,13 @@ Route Map Exit Action Command
.. clicmd:: on-match next
-.. clicmd:: continue
-
Proceed on to the next entry in the route-map.
-.. clicmd:: on-match goto N
+.. clicmd:: continue (1-65535)
-.. clicmd:: continue N
+ Proceed to the specified sequence in the route-map.
+
+.. clicmd:: on-match goto N
Proceed processing the route-map at the first entry whose order is >= N
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index a80580ec71..30b0204254 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -246,7 +246,7 @@ Under link parameter statement, the following commands set the different TE valu
as specified in RFC3630 (OSPF) or RFC5305 (ISIS). Admin-group is also known
as Resource Class/Color in the OSPF protocol.
-.. clicmd:: [no] affinity AFFINITY-MAP-NAME
+.. clicmd:: affinity AFFINITY-MAP-NAME
This commands configures the Traffic Engineering Admin-Group of the
interface using the affinity-map definitions (:ref:`affinity-map`).
@@ -257,7 +257,7 @@ Under link parameter statement, the following commands set the different TE valu
``admin-grp`` and ``affinity`` commands provide two ways of setting
admin-groups. They cannot be both set on the same interface.
-.. clicmd:: [no] affinity-mode [extended|standard|both]
+.. clicmd:: affinity-mode [extended|standard|both]
This commands configures which admin-group format is set by the affinity
command. ``extended`` Admin-Group is the default and uses the RFC7308 format.
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index 28790f69e7..c40c2a75fe 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -128,7 +128,7 @@ static int filter_remove_check_empty(struct vty *vty, const char *ftype,
*/
DEFPY_YANG(
access_list_std, access_list_std_cmd,
- "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>",
+ "access-list ACCESSLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>",
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_SEQ_STR
@@ -204,7 +204,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list_std, no_access_list_std_cmd,
- "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>",
+ "no access-list ACCESSLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -251,7 +251,7 @@ DEFPY_YANG(
DEFPY_YANG(
access_list_ext, access_list_ext_cmd,
- "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
+ "access-list ACCESSLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_SEQ_STR
@@ -369,7 +369,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list_ext, no_access_list_ext_cmd,
- "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
+ "no access-list ACCESSLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -448,7 +448,7 @@ DEFPY_YANG(
*/
DEFPY_YANG(
access_list, access_list_cmd,
- "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <A.B.C.D/M$prefix [exact-match$exact]|any>",
+ "access-list ACCESSLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <A.B.C.D/M$prefix [exact-match$exact]|any>",
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_SEQ_STR
@@ -521,7 +521,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list, no_access_list_cmd,
- "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <A.B.C.D/M$prefix [exact-match$exact]|any>",
+ "no access-list ACCESSLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <A.B.C.D/M$prefix [exact-match$exact]|any>",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -567,7 +567,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list_all, no_access_list_all_cmd,
- "no access-list WORD$name",
+ "no access-list ACCESSLIST4_NAME$name",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR)
@@ -583,7 +583,7 @@ DEFPY_YANG(
DEFPY_YANG(
access_list_remark, access_list_remark_cmd,
- "access-list WORD$name remark LINE...",
+ "access-list ACCESSLIST4_NAME$name remark LINE...",
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_REMARK_STR
@@ -607,7 +607,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_access_list_remark, no_access_list_remark_cmd,
- "no access-list WORD$name remark",
+ "no access-list ACCESSLIST4_NAME$name remark",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -618,7 +618,7 @@ DEFPY_YANG(
ALIAS(
no_access_list_remark, no_access_list_remark_line_cmd,
- "no access-list WORD$name remark LINE...",
+ "no access-list ACCESSLIST4_NAME$name remark LINE...",
NO_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -627,7 +627,7 @@ ALIAS(
DEFPY_YANG(
ipv6_access_list, ipv6_access_list_cmd,
- "ipv6 access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X::X:X/M$prefix [exact-match$exact]|any>",
+ "ipv6 access-list ACCESSLIST6_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X::X:X/M$prefix [exact-match$exact]|any>",
IPV6_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -701,7 +701,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_access_list, no_ipv6_access_list_cmd,
- "no ipv6 access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X::X:X/M$prefix [exact-match$exact]|any>",
+ "no ipv6 access-list ACCESSLIST6_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X::X:X/M$prefix [exact-match$exact]|any>",
NO_STR
IPV6_STR
ACCESS_LIST_STR
@@ -748,7 +748,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_access_list_all, no_ipv6_access_list_all_cmd,
- "no ipv6 access-list WORD$name",
+ "no ipv6 access-list ACCESSLIST6_NAME$name",
NO_STR
IPV6_STR
ACCESS_LIST_STR
@@ -765,7 +765,7 @@ DEFPY_YANG(
DEFPY_YANG(
ipv6_access_list_remark, ipv6_access_list_remark_cmd,
- "ipv6 access-list WORD$name remark LINE...",
+ "ipv6 access-list ACCESSLIST6_NAME$name remark LINE...",
IPV6_STR
ACCESS_LIST_STR
ACCESS_LIST_ZEBRA_STR
@@ -790,7 +790,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_access_list_remark, no_ipv6_access_list_remark_cmd,
- "no ipv6 access-list WORD$name remark",
+ "no ipv6 access-list ACCESSLIST6_NAME$name remark",
NO_STR
IPV6_STR
ACCESS_LIST_STR
@@ -1166,7 +1166,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
DEFPY_YANG(
ip_prefix_list, ip_prefix_list_cmd,
- "ip prefix-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <any|A.B.C.D/M$prefix [{ge (0-32)$ge|le (0-32)$le}]>",
+ "ip prefix-list PREFIXLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <any|A.B.C.D/M$prefix [{ge (0-32)$ge|le (0-32)$le}]>",
IP_STR
PREFIX_LIST_STR
PREFIX_LIST_NAME_STR
@@ -1260,7 +1260,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ip_prefix_list, no_ip_prefix_list_cmd,
- "no ip prefix-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <any|A.B.C.D/M$prefix [{ge (0-32)|le (0-32)}]>",
+ "no ip prefix-list PREFIXLIST4_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <any|A.B.C.D/M$prefix [{ge (0-32)|le (0-32)}]>",
NO_STR
IP_STR
PREFIX_LIST_STR
@@ -1280,7 +1280,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ip_prefix_list_seq, no_ip_prefix_list_seq_cmd,
- "no ip prefix-list WORD$name seq (1-4294967295)$seq",
+ "no ip prefix-list PREFIXLIST4_NAME$name seq (1-4294967295)$seq",
NO_STR
IP_STR
PREFIX_LIST_STR
@@ -1292,7 +1292,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ip_prefix_list_all, no_ip_prefix_list_all_cmd,
- "no ip prefix-list WORD$name",
+ "no ip prefix-list PREFIXLIST4_NAME$name",
NO_STR
IP_STR
PREFIX_LIST_STR
@@ -1309,7 +1309,7 @@ DEFPY_YANG(
DEFPY_YANG(
ip_prefix_list_remark, ip_prefix_list_remark_cmd,
- "ip prefix-list WORD$name description LINE...",
+ "ip prefix-list PREFIXLIST4_NAME$name description LINE...",
IP_STR
PREFIX_LIST_STR
PREFIX_LIST_NAME_STR
@@ -1334,7 +1334,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ip_prefix_list_remark, no_ip_prefix_list_remark_cmd,
- "no ip prefix-list WORD$name description",
+ "no ip prefix-list PREFIXLIST4_NAME$name description",
NO_STR
IP_STR
PREFIX_LIST_STR
@@ -1346,7 +1346,7 @@ DEFPY_YANG(
ALIAS(
no_ip_prefix_list_remark, no_ip_prefix_list_remark_line_cmd,
- "no ip prefix-list WORD$name description LINE...",
+ "no ip prefix-list PREFIXLIST4_NAME$name description LINE...",
NO_STR
IP_STR
PREFIX_LIST_STR
@@ -1356,7 +1356,7 @@ ALIAS(
DEFPY_YANG(
ipv6_prefix_list, ipv6_prefix_list_cmd,
- "ipv6 prefix-list WORD$name [seq (1-4294967295)] <deny|permit>$action <any|X:X::X:X/M$prefix [{ge (0-128)$ge|le (0-128)$le}]>",
+ "ipv6 prefix-list PREFIXLIST6_NAME$name [seq (1-4294967295)] <deny|permit>$action <any|X:X::X:X/M$prefix [{ge (0-128)$ge|le (0-128)$le}]>",
IPV6_STR
PREFIX_LIST_STR
PREFIX_LIST_NAME_STR
@@ -1450,7 +1450,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_prefix_list, no_ipv6_prefix_list_cmd,
- "no ipv6 prefix-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <any|X:X::X:X/M$prefix [{ge (0-128)$ge|le (0-128)$le}]>",
+ "no ipv6 prefix-list PREFIXLIST6_NAME$name [seq (1-4294967295)$seq] <deny|permit>$action <any|X:X::X:X/M$prefix [{ge (0-128)$ge|le (0-128)$le}]>",
NO_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1470,7 +1470,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_prefix_list_seq, no_ipv6_prefix_list_seq_cmd,
- "no ipv6 prefix-list WORD$name seq (1-4294967295)$seq",
+ "no ipv6 prefix-list PREFIXLIST6_NAME$name seq (1-4294967295)$seq",
NO_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1482,7 +1482,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_prefix_list_all, no_ipv6_prefix_list_all_cmd,
- "no ipv6 prefix-list WORD$name",
+ "no ipv6 prefix-list PREFIXLIST6_NAME$name",
NO_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1499,7 +1499,7 @@ DEFPY_YANG(
DEFPY_YANG(
ipv6_prefix_list_remark, ipv6_prefix_list_remark_cmd,
- "ipv6 prefix-list WORD$name description LINE...",
+ "ipv6 prefix-list PREFIXLIST6_NAME$name description LINE...",
IPV6_STR
PREFIX_LIST_STR
PREFIX_LIST_NAME_STR
@@ -1524,7 +1524,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_cmd,
- "no ipv6 prefix-list WORD$name description",
+ "no ipv6 prefix-list PREFIXLIST6_NAME$name description",
NO_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1536,7 +1536,7 @@ DEFPY_YANG(
ALIAS(
no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_line_cmd,
- "no ipv6 prefix-list WORD$name description LINE...",
+ "no ipv6 prefix-list PREFIXLIST6_NAME$name description LINE...",
NO_STR
IPV6_STR
PREFIX_LIST_STR
diff --git a/lib/if.c b/lib/if.c
index 1328e21874..a344c2b865 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1748,6 +1748,8 @@ lib_interface_state_phy_address_get_elem(struct nb_cb_get_elem_args *args)
}
/* clang-format off */
+
+/* cli_show callbacks are kept here for daemons not yet converted to mgmtd */
const struct frr_yang_module_info frr_interface_info = {
.name = "frr-interface",
.nodes = {
@@ -1830,3 +1832,26 @@ const struct frr_yang_module_info frr_interface_info = {
},
}
};
+
+const struct frr_yang_module_info frr_interface_cli_info = {
+ .name = "frr-interface",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-interface:lib/interface",
+ .cbs = {
+ .cli_show = cli_show_interface,
+ .cli_show_end = cli_show_interface_end,
+ },
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/description",
+ .cbs = {
+ .cli_show = cli_show_interface_desc,
+ },
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/lib/if.h b/lib/if.h
index 548a91b948..0dc56bd210 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -636,6 +636,7 @@ extern void if_down_via_zapi(struct interface *ifp);
extern void if_destroy_via_zapi(struct interface *ifp);
extern const struct frr_yang_module_info frr_interface_info;
+extern const struct frr_yang_module_info frr_interface_cli_info;
#ifdef __cplusplus
}
diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c
index 198d96e381..4942d66850 100644
--- a/lib/northbound_sysrepo.c
+++ b/lib/northbound_sysrepo.c
@@ -279,11 +279,12 @@ static int frr_sr_config_change_cb_prepare(sr_session_ctx_t *session,
ret = nb_candidate_commit_prepare(context, candidate, NULL,
&transaction, false, false, errmsg,
sizeof(errmsg));
- if (ret != NB_OK && ret != NB_ERR_NO_CHANGES)
- flog_warn(
- EC_LIB_LIBSYSREPO,
- "%s: failed to prepare configuration transaction: %s (%s)",
- __func__, nb_err_name(ret), errmsg);
+ if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) {
+ flog_warn(EC_LIB_LIBSYSREPO,
+ "%s: failed to prepare configuration transaction: %s (%s)",
+ __func__, nb_err_name(ret), errmsg);
+ sr_session_set_error_message(session, errmsg);
+ }
if (!transaction)
nb_config_free(candidate);
diff --git a/lib/plist.c b/lib/plist.c
index 605e7e73ea..618d92b549 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1229,7 +1229,7 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
DEFPY (show_ip_prefix_list,
show_ip_prefix_list_cmd,
- "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]] [json$uj]",
+ "show ip prefix-list [PREFIXLIST4_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
SHOW_STR
IP_STR
PREFIX_LIST_STR
@@ -1242,13 +1242,13 @@ DEFPY (show_ip_prefix_list,
if (dseq)
dtype = sequential_display;
- return vty_show_prefix_list(vty, AFI_IP, prefix_list, arg_str, dtype,
+ return vty_show_prefix_list(vty, AFI_IP, name, arg_str, dtype,
!!uj);
}
DEFPY (show_ip_prefix_list_prefix,
show_ip_prefix_list_prefix_cmd,
- "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]",
+ "show ip prefix-list PREFIXLIST4_NAME$name A.B.C.D/M$prefix [longer$dl|first-match$dfm]",
SHOW_STR
IP_STR
PREFIX_LIST_STR
@@ -1263,13 +1263,13 @@ DEFPY (show_ip_prefix_list_prefix,
else if (dfm)
dtype = first_match_display;
- return vty_show_prefix_list_prefix(vty, AFI_IP, prefix_list, prefix_str,
+ return vty_show_prefix_list_prefix(vty, AFI_IP, name, prefix_str,
dtype);
}
DEFPY (show_ip_prefix_list_summary,
show_ip_prefix_list_summary_cmd,
- "show ip prefix-list summary [WORD$prefix_list] [json$uj]",
+ "show ip prefix-list summary [PREFIXLIST4_NAME$name] [json$uj]",
SHOW_STR
IP_STR
PREFIX_LIST_STR
@@ -1277,13 +1277,13 @@ DEFPY (show_ip_prefix_list_summary,
"Name of a prefix list\n"
JSON_STR)
{
- return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL,
+ return vty_show_prefix_list(vty, AFI_IP, name, NULL,
summary_display, !!uj);
}
DEFPY (show_ip_prefix_list_detail,
show_ip_prefix_list_detail_cmd,
- "show ip prefix-list detail [WORD$prefix_list] [json$uj]",
+ "show ip prefix-list detail [PREFIXLIST4_NAME$name] [json$uj]",
SHOW_STR
IP_STR
PREFIX_LIST_STR
@@ -1291,25 +1291,25 @@ DEFPY (show_ip_prefix_list_detail,
"Name of a prefix list\n"
JSON_STR)
{
- return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL,
+ return vty_show_prefix_list(vty, AFI_IP, name, NULL,
detail_display, !!uj);
}
DEFPY (clear_ip_prefix_list,
clear_ip_prefix_list_cmd,
- "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]",
+ "clear ip prefix-list [PREFIXLIST4_NAME$name [A.B.C.D/M$prefix]]",
CLEAR_STR
IP_STR
PREFIX_LIST_STR
"Name of a prefix list\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str);
+ return vty_clear_prefix_list(vty, AFI_IP, name, prefix_str);
}
DEFPY (show_ipv6_prefix_list,
show_ipv6_prefix_list_cmd,
- "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]] [json$uj]",
+ "show ipv6 prefix-list [PREFIXLIST6_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
SHOW_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1322,13 +1322,13 @@ DEFPY (show_ipv6_prefix_list,
if (dseq)
dtype = sequential_display;
- return vty_show_prefix_list(vty, AFI_IP6, prefix_list, arg_str, dtype,
+ return vty_show_prefix_list(vty, AFI_IP6, name, arg_str, dtype,
!!uj);
}
DEFPY (show_ipv6_prefix_list_prefix,
show_ipv6_prefix_list_prefix_cmd,
- "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]",
+ "show ipv6 prefix-list PREFIXLIST6_NAME$name X:X::X:X/M$prefix [longer$dl|first-match$dfm]",
SHOW_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1343,13 +1343,13 @@ DEFPY (show_ipv6_prefix_list_prefix,
else if (dfm)
dtype = first_match_display;
- return vty_show_prefix_list_prefix(vty, AFI_IP6, prefix_list,
+ return vty_show_prefix_list_prefix(vty, AFI_IP6, name,
prefix_str, dtype);
}
DEFPY (show_ipv6_prefix_list_summary,
show_ipv6_prefix_list_summary_cmd,
- "show ipv6 prefix-list summary [WORD$prefix-list] [json$uj]",
+ "show ipv6 prefix-list summary [PREFIXLIST6_NAME$name] [json$uj]",
SHOW_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1357,13 +1357,13 @@ DEFPY (show_ipv6_prefix_list_summary,
"Name of a prefix list\n"
JSON_STR)
{
- return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL,
+ return vty_show_prefix_list(vty, AFI_IP6, name, NULL,
summary_display, !!uj);
}
DEFPY (show_ipv6_prefix_list_detail,
show_ipv6_prefix_list_detail_cmd,
- "show ipv6 prefix-list detail [WORD$prefix-list] [json$uj]",
+ "show ipv6 prefix-list detail [PREFIXLIST6_NAME$name] [json$uj]",
SHOW_STR
IPV6_STR
PREFIX_LIST_STR
@@ -1371,20 +1371,20 @@ DEFPY (show_ipv6_prefix_list_detail,
"Name of a prefix list\n"
JSON_STR)
{
- return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL,
+ return vty_show_prefix_list(vty, AFI_IP6, name, NULL,
detail_display, !!uj);
}
DEFPY (clear_ipv6_prefix_list,
clear_ipv6_prefix_list_cmd,
- "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]",
+ "clear ipv6 prefix-list [PREFIXLIST6_NAME$name [X:X::X:X/M$prefix]]",
CLEAR_STR
IPV6_STR
PREFIX_LIST_STR
"Name of a prefix list\n"
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
{
- return vty_clear_prefix_list(vty, AFI_IP6, prefix_list, prefix_str);
+ return vty_clear_prefix_list(vty, AFI_IP6, name, prefix_str);
}
DEFPY (debug_prefix_list_match,
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index f24d574278..88b341cac0 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -188,7 +188,7 @@ DEFPY_YANG(
DEFPY_YANG(
match_ip_address_prefix_list,
match_ip_address_prefix_list_cmd,
- "match ip address prefix-list PREFIXLIST_NAME$name",
+ "match ip address prefix-list PREFIXLIST4_NAME$name",
MATCH_STR
IP_STR
"Match address of route\n"
@@ -209,7 +209,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_cmd,
- "no match ip address prefix-list [PREFIXLIST_NAME]",
+ "no match ip address prefix-list [PREFIXLIST4_NAME]",
NO_STR
MATCH_STR
IP_STR
@@ -265,7 +265,7 @@ DEFPY_YANG(
DEFPY_YANG(
match_ip_next_hop_prefix_list,
match_ip_next_hop_prefix_list_cmd,
- "match ip next-hop prefix-list PREFIXLIST_NAME$name",
+ "match ip next-hop prefix-list PREFIXLIST4_NAME$name",
MATCH_STR
IP_STR
"Match next-hop address of route\n"
@@ -287,7 +287,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_match_ip_next_hop_prefix_list,
no_match_ip_next_hop_prefix_list_cmd,
- "no match ip next-hop prefix-list [PREFIXLIST_NAME]",
+ "no match ip next-hop prefix-list [PREFIXLIST4_NAME]",
NO_STR
MATCH_STR
IP_STR
@@ -379,7 +379,7 @@ DEFPY_YANG(
DEFPY_YANG(
match_ipv6_address_prefix_list, match_ipv6_address_prefix_list_cmd,
- "match ipv6 address prefix-list PREFIXLIST_NAME$name",
+ "match ipv6 address prefix-list PREFIXLIST6_NAME$name",
MATCH_STR
IPV6_STR
"Match address of route\n"
@@ -401,7 +401,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_match_ipv6_address_prefix_list,
no_match_ipv6_address_prefix_list_cmd,
- "no match ipv6 address prefix-list [PREFIXLIST_NAME]",
+ "no match ipv6 address prefix-list [PREFIXLIST6_NAME]",
NO_STR
MATCH_STR
IPV6_STR
diff --git a/lib/routing_nb.c b/lib/routing_nb.c
index 3d837bcc11..33372d113a 100644
--- a/lib/routing_nb.c
+++ b/lib/routing_nb.c
@@ -27,3 +27,13 @@ const struct frr_yang_module_info frr_routing_info = {
},
}
};
+
+const struct frr_yang_module_info frr_routing_cli_info = {
+ .name = "frr-routing",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/lib/routing_nb.h b/lib/routing_nb.h
index cc83d8469d..e805e1cd0f 100644
--- a/lib/routing_nb.h
+++ b/lib/routing_nb.h
@@ -6,6 +6,7 @@ extern "C" {
#endif
extern const struct frr_yang_module_info frr_routing_info;
+extern const struct frr_yang_module_info frr_routing_cli_info;
/* Mandatory callbacks. */
int routing_control_plane_protocols_control_plane_protocol_create(
diff --git a/lib/sockopt.c b/lib/sockopt.c
index b9b9a71167..74bc034ccd 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -672,6 +672,9 @@ int sockopt_tcp_mss_get(int sock)
int tcp_maxseg = 0;
socklen_t tcp_maxseg_len = sizeof(tcp_maxseg);
+ if (sock < 0)
+ return 0;
+
ret = getsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg,
&tcp_maxseg_len);
if (ret != 0) {
diff --git a/lib/vrf.c b/lib/vrf.c
index f8fa70bfe8..9f4c5cdddc 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -1034,6 +1034,8 @@ lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args *args)
}
/* clang-format off */
+
+/* cli_show callbacks are kept here for daemons not yet converted to mgmtd */
const struct frr_yang_module_info frr_vrf_info = {
.name = "frr-vrf",
.nodes = {
@@ -1069,3 +1071,19 @@ const struct frr_yang_module_info frr_vrf_info = {
}
};
+const struct frr_yang_module_info frr_vrf_cli_info = {
+ .name = "frr-vrf",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-vrf:lib/vrf",
+ .cbs = {
+ .cli_show = lib_vrf_cli_write,
+ .cli_show_end = lib_vrf_cli_write_end,
+ },
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/lib/vrf.h b/lib/vrf.h
index f66a9e6b32..4277a51bb1 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -294,6 +294,7 @@ extern int vrf_enable(struct vrf *vrf);
extern void vrf_delete(struct vrf *vrf);
extern const struct frr_yang_module_info frr_vrf_info;
+extern const struct frr_yang_module_info frr_vrf_cli_info;
#ifdef __cplusplus
}
diff --git a/lib/vty.h b/lib/vty.h
index 06973da916..a59ac7a652 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -232,10 +232,6 @@ struct vty {
uintptr_t mgmt_req_pending_data;
bool mgmt_locked_candidate_ds;
bool mgmt_locked_running_ds;
- /* Need to track when we file-lock in vtysh to re-lock on end/conf t
- * workaround
- */
- bool vtysh_file_locked;
};
static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
diff --git a/lib/yang.c b/lib/yang.c
index 2b360376d3..adf2ba2ab0 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -40,7 +40,8 @@ static LY_ERR yang_module_imp_clb(const char *mod_name, const char *mod_rev,
struct yang_module_embed *e;
if (!strcmp(mod_name, "ietf-inet-types") ||
- !strcmp(mod_name, "ietf-yang-types"))
+ !strcmp(mod_name, "ietf-yang-types") ||
+ !strcmp(mod_name, "ietf-yang-metadata"))
/* libyang has these built in, don't try finding them here */
return LY_ENOTFOUND;
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index 001da7680b..ec8e773354 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -711,9 +711,6 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
}
if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
- /* as we have the lock no-one else should have a config txn */
- assert(!mgmt_config_txn_in_progress());
-
/* Start a CONFIG Transaction (if not started already) */
session->cfg_txn_id = mgmt_create_txn(session->session_id,
MGMTD_TXN_TYPE_CONFIG);
diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c
index 5be849b63c..cce16f51f6 100644
--- a/mgmtd/mgmt_main.c
+++ b/mgmtd/mgmt_main.c
@@ -48,7 +48,6 @@ struct zebra_privs_t mgmt_privs = {
};
static struct frr_daemon_info mgmtd_di;
-char backup_config_file[256];
/* SIGHUP handler. */
static void sighup(void)
@@ -171,10 +170,10 @@ const struct frr_yang_module_info zebra_route_map_info = {
*/
static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
&frr_filter_cli_info,
- &frr_interface_info,
+ &frr_interface_cli_info,
&frr_route_map_cli_info,
- &frr_routing_info,
- &frr_vrf_info,
+ &frr_routing_cli_info,
+ &frr_vrf_cli_info,
&frr_affinity_map_cli_info,
/* mgmtd-only modules */
@@ -212,7 +211,7 @@ FRR_DAEMON_INFO(mgmtd, MGMTD,
.n_yang_modules = array_size(mgmt_yang_modules),
/* avoid libfrr trying to read our config file for us */
- .flags = FRR_MANUAL_VTY_START,
+ .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG,
);
/* clang-format on */
@@ -230,8 +229,9 @@ int main(int argc, char **argv)
frr_preinit(&mgmtd_di, argc, argv);
frr_opt_add(
- "s:" DEPRECATED_OPTIONS, longopts,
- " -s, --socket_size Set MGMTD peer socket send buffer size\n");
+ "s:n" DEPRECATED_OPTIONS, longopts,
+ " -s, --socket_size Set MGMTD peer socket send buffer size\n"
+ " -n, --vrfwnetns Use NetNS as VRF backend\n");
/* Command line argument treatment. */
while (1) {
@@ -274,11 +274,6 @@ int main(int argc, char **argv)
/* MGMTD related initialization. */
mgmt_init();
- snprintf(backup_config_file, sizeof(backup_config_file),
- "%s/zebra.conf", frr_sysconfdir);
- mgmtd_di.backup_config_file = backup_config_file;
-
- /* this will queue a read configs event */
frr_config_fork();
frr_run(mm->master);
diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c
index df2a1d852d..664f42f4ba 100644
--- a/mgmtd/mgmt_txn.c
+++ b/mgmtd/mgmt_txn.c
@@ -105,6 +105,7 @@ struct mgmt_commit_cfg_req {
uint8_t abort : 1;
uint8_t implicit : 1;
uint8_t rollback : 1;
+ uint8_t init : 1;
/* Track commit phases */
enum mgmt_commit_phase phase;
@@ -750,6 +751,14 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
mgmt_history_rollback_complete(success);
}
+ if (txn->commit_cfg_req->req.commit_cfg.init) {
+ /*
+ * This is the backend init request.
+ * We need to unlock the running datastore.
+ */
+ mgmt_ds_unlock(txn->commit_cfg_req->req.commit_cfg.dst_ds_ctx);
+ }
+
txn->commit_cfg_req->req.commit_cfg.cmt_stats = NULL;
mgmt_txn_req_free(&txn->commit_cfg_req);
@@ -2081,15 +2090,26 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter,
struct mgmt_commit_cfg_req *cmtcfg_req;
static struct mgmt_commit_stats dummy_stats;
struct nb_config_cbs *adapter_cfgs = NULL;
+ struct mgmt_ds_ctx *ds_ctx;
memset(&dummy_stats, 0, sizeof(dummy_stats));
if (connect) {
- /* Get config for this single backend client */
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, MGMTD_DS_RUNNING);
+ assert(ds_ctx);
+
+ /*
+ * Lock the running datastore to prevent any changes while we
+ * are initializing the backend.
+ */
+ if (mgmt_ds_lock(ds_ctx, 0) != 0)
+ return -1;
+ /* Get config for this single backend client */
mgmt_be_get_adapter_config(adapter, &adapter_cfgs);
if (!adapter_cfgs || RB_EMPTY(nb_config_cbs, adapter_cfgs)) {
SET_FLAG(adapter->flags,
MGMTD_BE_ADAPTER_FLAGS_CFG_SYNCED);
+ mgmt_ds_unlock(ds_ctx);
return 0;
}
@@ -2101,6 +2121,7 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter,
if (!txn) {
__log_err("Failed to create CONFIG Transaction for downloading CONFIGs for client '%s'",
adapter->name);
+ mgmt_ds_unlock(ds_ctx);
nb_config_diff_del_changes(adapter_cfgs);
return -1;
}
@@ -2114,10 +2135,11 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter,
txn_req = mgmt_txn_req_alloc(txn, 0, MGMTD_TXN_PROC_COMMITCFG);
txn_req->req.commit_cfg.src_ds_id = MGMTD_DS_NONE;
txn_req->req.commit_cfg.src_ds_ctx = 0;
- txn_req->req.commit_cfg.dst_ds_id = MGMTD_DS_NONE;
- txn_req->req.commit_cfg.dst_ds_ctx = 0;
+ txn_req->req.commit_cfg.dst_ds_id = MGMTD_DS_RUNNING;
+ txn_req->req.commit_cfg.dst_ds_ctx = ds_ctx;
txn_req->req.commit_cfg.validate_only = false;
txn_req->req.commit_cfg.abort = false;
+ txn_req->req.commit_cfg.init = true;
txn_req->req.commit_cfg.cmt_stats = &dummy_stats;
txn_req->req.commit_cfg.cfg_chgs = adapter_cfgs;
diff --git a/mgmtd/subdir.am b/mgmtd/subdir.am
index 0af64dc0be..1624c6e4f9 100644
--- a/mgmtd/subdir.am
+++ b/mgmtd/subdir.am
@@ -19,7 +19,6 @@ mgmtd_libmgmt_be_nb_la_SOURCES = \
zebra/zebra_cli.c \
# end
nodist_mgmtd_libmgmt_be_nb_la_SOURCES = \
- lib/affinitymap_cli.c \
# end
mgmtd_libmgmt_be_nb_la_CFLAGS = $(AM_CFLAGS) -DINCLUDE_MGMTD_CMDDEFS_ONLY
mgmtd_libmgmt_be_nb_la_CPPFLAGS = $(AM_CPPFLAGS) -DINCLUDE_MGMTD_CMDDEFS_ONLY
@@ -61,6 +60,7 @@ mgmtd_mgmtd_SOURCES = \
# end
nodist_mgmtd_mgmtd_SOURCES = \
yang/frr-zebra.yang.c \
+ yang/frr-zebra-route-map.yang.c \
yang/ietf/ietf-netconf-acm.yang.c \
yang/ietf/ietf-netconf.yang.c \
yang/ietf/ietf-netconf-with-defaults.yang.c \
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index 88628999ab..be909c862a 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -191,6 +191,11 @@ int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
"Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
&addr, ifp->name, &c->cur.remote_nbma_natoa,
&c->cur.peer->vc->remote.nbma, &lladdr);
+
+ if (lladdr.sa.sa_family == AF_UNSPEC)
+ /* nothing from zebra, so use nhrp peer */
+ lladdr = c->cur.peer->vc->remote.nbma;
+
/* In case of shortcuts, nbma is given by lladdr, not
* vc->remote.nbma.
*/
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 69c711bf06..cf5479e18c 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -731,7 +731,7 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
DEFUN (area_filter_list,
area_filter_list_cmd,
- "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
+ "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST6_NAME <in|out>",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
"OSPF6 area ID as a decimal value\n"
@@ -774,7 +774,7 @@ DEFUN (area_filter_list,
DEFUN (no_area_filter_list,
no_area_filter_list_cmd,
- "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
+ "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST6_NAME <in|out>",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 652d502c8e..b9dace2fe8 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -2396,7 +2396,7 @@ DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd,
}
DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd,
- "ipv6 ospf6 advertise prefix-list WORD",
+ "ipv6 ospf6 advertise prefix-list PREFIXLIST6_NAME",
IP6_STR OSPF6_STR "Advertising options\n"
"Filter prefix using prefix-list\n"
"Prefix list name\n")
@@ -2431,7 +2431,7 @@ DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd,
DEFUN(no_ipv6_ospf6_advertise_prefix_list,
no_ipv6_ospf6_advertise_prefix_list_cmd,
- "no ipv6 ospf6 advertise prefix-list [WORD]",
+ "no ipv6 ospf6 advertise prefix-list [PREFIXLIST6_NAME]",
NO_STR IP6_STR OSPF6_STR "Advertising options\n"
"Filter prefix using prefix-list\n"
"Prefix list name\n")
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 877c9bd634..93dd12ce49 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -1872,7 +1872,7 @@ DEFUN (no_ospf_area_import_list,
DEFUN (ospf_area_filter_list,
ospf_area_filter_list_cmd,
- "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
+ "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST4_NAME <in|out>",
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n"
@@ -1917,7 +1917,7 @@ DEFUN (ospf_area_filter_list,
DEFUN (no_ospf_area_filter_list,
no_ospf_area_filter_list_cmd,
- "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>",
+ "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST4_NAME <in|out>",
NO_STR
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c
index 262ce86c29..4db11572d8 100644
--- a/pimd/pim6_cmd.c
+++ b/pimd/pim6_cmd.c
@@ -77,7 +77,7 @@ DEFPY (ipv6_pim_spt_switchover_infinity,
DEFPY (ipv6_pim_spt_switchover_infinity_plist,
ipv6_pim_spt_switchover_infinity_plist_cmd,
- "ipv6 pim spt-switchover infinity-and-beyond prefix-list WORD$plist",
+ "ipv6 pim spt-switchover infinity-and-beyond prefix-list PREFIXLIST6_NAME$plist",
IPV6_STR
PIM_STR
"SPT-Switchover\n"
@@ -102,7 +102,7 @@ DEFPY (no_ipv6_pim_spt_switchover_infinity,
DEFPY (no_ipv6_pim_spt_switchover_infinity_plist,
no_ipv6_pim_spt_switchover_infinity_plist_cmd,
- "no ipv6 pim spt-switchover infinity-and-beyond prefix-list WORD",
+ "no ipv6 pim spt-switchover infinity-and-beyond prefix-list PREFIXLIST6_NAME",
NO_STR
IPV6_STR
PIM_STR
@@ -436,7 +436,7 @@ DEFPY (no_ipv6_pim_rp,
DEFPY (ipv6_pim_rp_prefix_list,
ipv6_pim_rp_prefix_list_cmd,
- "ipv6 pim rp X:X::X:X$rp prefix-list WORD$plist",
+ "ipv6 pim rp X:X::X:X$rp prefix-list PREFIXLIST6_NAME$plist",
IPV6_STR
PIM_STR
"Rendezvous Point\n"
@@ -449,7 +449,7 @@ DEFPY (ipv6_pim_rp_prefix_list,
DEFPY (no_ipv6_pim_rp_prefix_list,
no_ipv6_pim_rp_prefix_list_cmd,
- "no ipv6 pim rp X:X::X:X$rp prefix-list WORD$plist",
+ "no ipv6 pim rp X:X::X:X$rp prefix-list PREFIXLIST6_NAME$plist",
NO_STR
IPV6_STR
PIM_STR
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 628a445945..be36a07687 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -2999,7 +2999,7 @@ DEFUN (ip_pim_spt_switchover_infinity,
DEFPY (ip_pim_spt_switchover_infinity_plist,
ip_pim_spt_switchover_infinity_plist_cmd,
- "ip pim spt-switchover infinity-and-beyond prefix-list WORD$plist",
+ "ip pim spt-switchover infinity-and-beyond prefix-list PREFIXLIST4_NAME$plist",
IP_STR
PIM_STR
"SPT-Switchover\n"
@@ -3024,7 +3024,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
DEFUN (no_ip_pim_spt_switchover_infinity_plist,
no_ip_pim_spt_switchover_infinity_plist_cmd,
- "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
+ "no ip pim spt-switchover infinity-and-beyond prefix-list PREFIXLIST4_NAME",
NO_STR
IP_STR
PIM_STR
@@ -3038,7 +3038,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
DEFPY (pim_register_accept_list,
pim_register_accept_list_cmd,
- "[no] ip pim register-accept-list WORD$word",
+ "[no] ip pim register-accept-list PREFIXLIST4_NAME$word",
NO_STR
IP_STR
PIM_STR
@@ -3283,7 +3283,7 @@ DEFPY (ip_pim_rp,
DEFPY (ip_pim_rp_prefix_list,
ip_pim_rp_prefix_list_cmd,
- "ip pim rp A.B.C.D$rp prefix-list WORD$plist",
+ "ip pim rp A.B.C.D$rp prefix-list PREFIXLIST4_NAME$plist",
IP_STR
"pim multicast routing\n"
"Rendezvous Point\n"
@@ -3311,7 +3311,7 @@ DEFPY (no_ip_pim_rp,
DEFPY (no_ip_pim_rp_prefix_list,
no_ip_pim_rp_prefix_list_cmd,
- "no ip pim rp A.B.C.D$rp prefix-list WORD$plist",
+ "no ip pim rp A.B.C.D$rp prefix-list PREFIXLIST4_NAME$plist",
NO_STR
IP_STR
"pim multicast routing\n"
@@ -3325,7 +3325,7 @@ DEFPY (no_ip_pim_rp_prefix_list,
DEFUN (ip_pim_ssm_prefix_list,
ip_pim_ssm_prefix_list_cmd,
- "ip pim ssm prefix-list WORD",
+ "ip pim ssm prefix-list PREFIXLIST4_NAME",
IP_STR
"pim multicast routing\n"
"Source Specific Multicast\n"
@@ -3376,7 +3376,7 @@ DEFUN (no_ip_pim_ssm_prefix_list,
DEFUN (no_ip_pim_ssm_prefix_list_name,
no_ip_pim_ssm_prefix_list_name_cmd,
- "no ip pim ssm prefix-list WORD",
+ "no ip pim ssm prefix-list PREFIXLIST4_NAME",
NO_STR
IP_STR
"pim multicast routing\n"
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 66659e9034..c4efc14a9d 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -164,10 +164,14 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
static void zebra_connected(struct zclient *zclient)
{
+ struct vrf *vrf;
+
zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST, zclient, true);
zclient_send_reg_requests(zclient, VRF_DEFAULT);
- static_fixup_vrf_ids(vrf_lookup_by_id(VRF_DEFAULT));
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ assert(vrf);
+ static_fixup_vrf_ids(vrf);
}
/* API to check whether the configured nexthop address is
diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json
index 9f78447255..2ce936b291 100644
--- a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json
+++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json
@@ -12,7 +12,7 @@
{
"fib": true,
"directlyConnected": true,
- "interfaceName": "eth0",
+ "interfaceName": "vrf10",
"vrf": "vrf10",
"active": true
}
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf b/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
index 03dfbf9322..f52f56b0e0 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
+++ b/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
@@ -1,10 +1,19 @@
hostname r1
+router bgp 99
+ no bgp ebgp-requires-policy
+ address-family ipv4 unicast
+ redistribute connected
+ import vrf DONNA
+ !
+!
router bgp 99 vrf DONNA
no bgp ebgp-requires-policy
address-family ipv4 unicast
redistribute connected
import vrf EVA
+ import vrf NOTEXISTING
+ import vrf default
!
!
router bgp 99 vrf EVA
@@ -12,5 +21,13 @@ router bgp 99 vrf EVA
address-family ipv4 unicast
redistribute connected
import vrf DONNA
+ import vrf NOTEXISTING
+ !
+!
+router bgp 99 vrf NOTEXISTING
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ address-family ipv4 unicast
+ network 172.16.101.0/24
!
!
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf b/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf
index 35038557df..4de9e895a2 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf
+++ b/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf
@@ -1,5 +1,9 @@
hostname r1
+int dummy0
+ ip address 10.0.4.1/24
+ no shut
+!
int dummy1
ip address 10.0.0.1/24
no shut
@@ -16,3 +20,9 @@ int dummy4
ip address 10.0.3.1/24
no shut
!
+int EVA
+ no shut
+!
+int DONNA
+ no shut
+!
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/setup_vrfs b/tests/topotests/bgp_vrf_route_leak_basic/setup_vrfs
index fb67953fe3..f62c5cd211 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/setup_vrfs
+++ b/tests/topotests/bgp_vrf_route_leak_basic/setup_vrfs
@@ -3,6 +3,7 @@
ip link add DONNA type vrf table 1001
ip link add EVA type vrf table 1002
+ip link add dummy0 type dummy # vrf default
ip link add dummy1 type dummy
ip link add dummy2 type dummy
ip link add dummy3 type dummy
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
index fd7ffff17c..ef813e9541 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
+++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
@@ -64,7 +64,7 @@ def teardown_module(mod):
tgen.stop_topology()
-def test_vrf_route_leak():
+def test_vrf_route_leak_donna():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
@@ -81,11 +81,59 @@ def test_vrf_route_leak():
}
],
"10.0.1.0/24": [
- {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": True,
+ },
+ ],
+ },
],
"10.0.2.0/24": [{"protocol": "connected"}],
"10.0.3.0/24": [
- {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.4.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "lo",
+ "vrf": "default",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "172.16.101.0/24": [
+ {
+ "protocol": "bgp",
+ "nexthops": [
+ {
+ "interfaceIndex": 0,
+ "interfaceName": "unknown",
+ "vrf": "Unknown",
+ },
+ ],
+ },
],
}
@@ -95,10 +143,31 @@ def test_vrf_route_leak():
result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+def test_vrf_route_leak_eva():
+ logger.info("Ensure that routes are leaked back and forth")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
# Test EVA VRF.
expect = {
"10.0.0.0/24": [
- {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ },
+ ],
+ },
],
"10.0.1.0/24": [
{
@@ -106,13 +175,36 @@ def test_vrf_route_leak():
}
],
"10.0.2.0/24": [
- {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ },
+ ],
+ },
],
"10.0.3.0/24": [
{
"protocol": "connected",
}
],
+ "172.16.101.0/24": [
+ {
+ "protocol": "bgp",
+ "nexthops": [
+ {
+ "interfaceIndex": 0,
+ "interfaceName": "unknown",
+ "vrf": "Unknown",
+ },
+ ],
+ },
+ ],
}
test_func = partial(
@@ -122,6 +214,217 @@ def test_vrf_route_leak():
assert result, "BGP VRF EVA check failed:\n{}".format(diff)
+def test_vrf_route_leak_donna():
+ logger.info("Ensure that routes are leaked back and forth")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ # Test DONNA VRF.
+ expect = {
+ "10.0.0.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ "10.0.1.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.2.0/24": [{"protocol": "connected"}],
+ "10.0.3.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.4.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "lo",
+ "vrf": "default",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "172.16.101.0/24": [
+ {
+ "protocol": "bgp",
+ "nexthops": [
+ {
+ "interfaceIndex": 0,
+ "interfaceName": "unknown",
+ "vrf": "Unknown",
+ },
+ ],
+ },
+ ],
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+
+def test_vrf_route_leak_eva():
+ logger.info("Ensure that routes are leaked back and forth")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ # Test EVA VRF.
+ expect = {
+ "10.0.0.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.1.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ "10.0.2.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.3.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ "172.16.101.0/24": [
+ {
+ "protocol": "bgp",
+ "nexthops": [
+ {
+ "interfaceIndex": 0,
+ "interfaceName": "unknown",
+ "vrf": "Unknown",
+ },
+ ],
+ },
+ ],
+ }
+
+
+def test_vrf_route_leak_default():
+ logger.info("Ensure that routes are leaked back and forth")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ # Test default VRF.
+ expect = {
+ "10.0.0.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.2.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.4.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ }
+
+ test_func = partial(topotest.router_json_cmp, r1, "show ip route json", expect)
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF default check failed:\n{}".format(diff)
+
+
+def test_ping():
+ "Simple ping tests"
+
+ tgen = get_topogen()
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ logger.info("Ping from default to DONNA")
+ output = r1.run("ping -c 4 -w 4 -I 10.0.4.1 10.0.0.1")
+ assert " 0% packet loss" in output, "Ping default->DONNA FAILED"
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt
index ca9ca77bf5..248375dc6c 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt
@@ -7,5 +7,5 @@ O>* 10.0.4.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
O 10.0.20.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r1-eth1, XX:XX:XX
L>* 10.0.20.1/32 is directly connected, r1-eth1, XX:XX:XX
-B>* 10.0.30.0/24 [20/0] is directly connected, r1-eth2 (vrf neno), weight 1, XX:XX:XX
+B>* 10.0.30.0/24 [20/0] is directly connected, neno (vrf neno), weight 1, XX:XX:XX
O>* 10.0.40.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt
index 70ae987894..d7d31434c6 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt
@@ -9,4 +9,4 @@ O 10.0.20.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r2-eth1, XX:XX:XX
L>* 10.0.20.2/32 is directly connected, r2-eth1, XX:XX:XX
O>* 10.0.30.0/24 [110/20] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
-B>* 10.0.40.0/24 [20/0] is directly connected, r2-eth2 (vrf ray), weight 1, XX:XX:XX
+B>* 10.0.40.0/24 [20/0] is directly connected, ray (vrf ray), weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt
index 1495c88936..6ab1bb8f92 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt
@@ -1,9 +1,9 @@
VRF ray:
B 10.0.1.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX
-B 10.0.2.0/24 [20/0] is directly connected, r2-eth0 (vrf default) inactive, weight 1, XX:XX:XX
+B 10.0.2.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX
B>* 10.0.3.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O>* 10.0.4.0/24 [110/20] via 10.0.40.4, r2-eth2, weight 1, XX:XX:XX
-B 10.0.20.0/24 [20/0] is directly connected, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX
+B 10.0.20.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX
B>* 10.0.30.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O 10.0.40.0/24 [110/10] is directly connected, r2-eth2, weight 1, XX:XX:XX
C>* 10.0.40.0/24 is directly connected, r2-eth2, XX:XX:XX
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 4cb46b87a5..3290c8d54a 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1669,7 +1669,6 @@ static int vtysh_end(void)
/* Nothing to do. */
break;
default:
- vty->vtysh_file_locked = false;
vty->node = ENABLE_NODE;
break;
}
@@ -2393,23 +2392,12 @@ DEFUNSH(VTYSH_REALLYALL, vtysh_disable, vtysh_disable_cmd, "disable",
}
DEFUNSH(VTYSH_REALLYALL, vtysh_config_terminal, vtysh_config_terminal_cmd,
- "configure [terminal]",
- "Configuration from vty interface\n"
- "Configuration terminal\n")
-{
- vty->node = CONFIG_NODE;
- return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_REALLYALL, vtysh_config_terminal_file_lock,
- vtysh_config_terminal_file_lock_cmd,
- "configure terminal file-lock",
+ "configure [terminal [file-lock]]",
"Configuration from vty interface\n"
"Configuration terminal\n"
"Configuration with locked datastores\n")
{
vty->node = CONFIG_NODE;
- vty->vtysh_file_locked = true;
return CMD_SUCCESS;
}
@@ -2424,21 +2412,6 @@ static int vtysh_exit(struct vty *vty)
if (cnode->parent_node)
vty->node = cnode->parent_node;
- if (vty->node == CONFIG_NODE) {
- bool locked = vty->vtysh_file_locked;
-
- /* resync in case one of the daemons is somewhere else */
- vtysh_execute("end");
- /* NOTE: a rather expensive thing to do, can we avoid it? */
-
- if (locked)
- vtysh_execute("configure terminal file-lock");
- else
- vtysh_execute("configure terminal");
- } else if (vty->node == ENABLE_NODE) {
- vty->vtysh_file_locked = false;
- }
-
return CMD_SUCCESS;
}
@@ -5125,7 +5098,6 @@ void vtysh_init_vty(void)
if (!user_mode)
install_element(VIEW_NODE, &vtysh_enable_cmd);
install_element(ENABLE_NODE, &vtysh_config_terminal_cmd);
- install_element(ENABLE_NODE, &vtysh_config_terminal_file_lock_cmd);
install_element(ENABLE_NODE, &vtysh_disable_cmd);
/* "exit" command. */
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 888f6a8c21..c207e4d427 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -616,8 +616,13 @@ static int vtysh_read_file(FILE *confp, bool dry_run)
vty->node = CONFIG_NODE;
vtysh_execute_no_pager("enable");
- vtysh_execute_no_pager("conf term file-lock");
- vty->vtysh_file_locked = true;
+ /*
+ * When reading the config, we need to wait until the lock is acquired.
+ * If we ignore the failure and continue without the lock, the config
+ * will be fully ignored.
+ */
+ while (vtysh_execute_no_pager("conf term file-lock") == CMD_WARNING_CONFIG_FAILED)
+ usleep(100000);
if (!dry_run)
vtysh_execute_no_pager("XFRR_start_configuration");
@@ -629,7 +634,6 @@ static int vtysh_read_file(FILE *confp, bool dry_run)
vtysh_execute_no_pager("XFRR_end_configuration");
vtysh_execute_no_pager("end");
- vty->vtysh_file_locked = false;
vtysh_execute_no_pager("disable");
vty_close(vty);
diff --git a/zebra/rib.h b/zebra/rib.h
index 4c817eca71..a721f4bac4 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -85,25 +85,12 @@ struct route_entry {
*/
struct nhg_hash_entry *nhe;
- /* Nexthop group from FIB (optional), reflecting what is actually
- * installed in the FIB if that differs. The 'backup' group is used
- * when backup nexthops are present in the route's nhg.
- */
- struct nexthop_group fib_ng;
- struct nexthop_group fib_backup_ng;
-
/* Nexthop group hash entry IDs. The "installed" id is the id
* used in linux/netlink, if available.
*/
uint32_t nhe_id;
uint32_t nhe_installed_id;
- /* Tag */
- route_tag_t tag;
-
- /* Uptime. */
- time_t uptime;
-
/* Type of this route. */
int type;
@@ -160,7 +147,20 @@ struct route_entry {
/* Distance. */
uint8_t distance;
+ /* Tag */
+ route_tag_t tag;
+
+ /* Uptime. */
+ time_t uptime;
+
struct re_opaque *opaque;
+
+ /* Nexthop group from FIB (optional), reflecting what is actually
+ * installed in the FIB if that differs. The 'backup' group is used
+ * when backup nexthops are present in the route's nhg.
+ */
+ struct nexthop_group fib_ng;
+ struct nexthop_group fib_backup_ng;
};
#define RIB_SYSTEM_ROUTE(R) RSYSTEM_ROUTE((R)->type)
diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c
index 8fedcfedc0..00e0a49cb8 100644
--- a/zebra/zebra_cli.c
+++ b/zebra/zebra_cli.c
@@ -437,13 +437,19 @@ DEFPY_YANG (link_params_admin_grp,
char value_str[YANG_VALUE_MAXLEN];
if (!no) {
+ assert(bitpattern);
+
if (bitpattern[0] != '0' || bitpattern[1] != 'x' ||
strlen(bitpattern) > 10) {
vty_out(vty, "Invalid bitpattern value\n");
return CMD_WARNING_CONFIG_FAILED;
}
- sscanf(bitpattern, "%x", &value);
+ if (sscanf(bitpattern, "%x", &value) != 1) {
+ vty_out(vty, "Invalid bitpattern value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
snprintf(value_str, sizeof(value_str), "%u", value);
nb_cli_enqueue_change(vty, "./legacy-admin-group", NB_OP_MODIFY,
@@ -610,6 +616,8 @@ DEFPY_YANG (link_params_res_bw,
float bw;
if (!no) {
+ assert(bandwidth);
+
if (sscanf(bandwidth, "%g", &bw) != 1) {
vty_out(vty, "Invalid bandwidth value\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -647,6 +655,8 @@ DEFPY_YANG (link_params_ava_bw,
float bw;
if (!no) {
+ assert(bandwidth);
+
if (sscanf(bandwidth, "%g", &bw) != 1) {
vty_out(vty, "Invalid bandwidth value\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -684,6 +694,8 @@ DEFPY_YANG (link_params_use_bw,
float bw;
if (!no) {
+ assert(bandwidth);
+
if (sscanf(bandwidth, "%g", &bw) != 1) {
vty_out(vty, "Invalid bandwidth value\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -817,6 +829,7 @@ DEFPY_YANG (ip_address,
strlcpy(ip, address_str, sizeof(ip));
mask = strchr(ip, '/');
+ assert(mask);
*mask = 0;
mask++;
@@ -886,6 +899,7 @@ DEFPY_YANG (ip_address_peer,
strlcpy(peer_ip, peer_str, sizeof(peer_ip));
peer_mask = strchr(peer_ip, '/');
+ assert(peer_mask);
*peer_mask = 0;
peer_mask++;
@@ -934,6 +948,7 @@ DEFPY_YANG (ipv6_address,
strlcpy(ip, address_str, sizeof(ip));
mask = strchr(ip, '/');
+ assert(mask);
*mask = 0;
mask++;
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 6080048976..34ef79f155 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -154,7 +154,7 @@ struct zebra_evpn_es_vtep {
/* Parameters for DF election */
uint8_t df_alg;
- uint32_t df_pref;
+ uint16_t df_pref;
/* XXX - maintain a backpointer to struct zebra_vtep */
};
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index f24af16a2e..46c95e6c0f 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -2220,7 +2220,8 @@ int lib_interface_zebra_link_params_packet_loss_destroy(
static bool evpn_mh_dnode_to_esi(const struct lyd_node *dnode, esi_t *esi)
{
if (yang_dnode_exists(dnode, "type-0/esi")) {
- str_to_esi(yang_dnode_get_string(dnode, "type-0/esi"), esi);
+ if (!str_to_esi(yang_dnode_get_string(dnode, "type-0/esi"), esi))
+ assert(false);
} else if (yang_dnode_exists(dnode, "type-3/system-mac") &&
yang_dnode_exists(dnode, "type-3/local-discriminator")) {
struct ethaddr mac;
@@ -2301,7 +2302,8 @@ int lib_interface_zebra_evpn_mh_type_0_esi_modify(struct nb_cb_modify_args *args
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
- str_to_esi(yang_dnode_get_string(args->dnode, NULL), &esi);
+ if (!str_to_esi(yang_dnode_get_string(args->dnode, NULL), &esi))
+ assert(false);
zebra_evpn_es_type0_esi_update(ifp->info, &esi);
break;
}
@@ -3031,7 +3033,7 @@ int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
- struct rtadv_rdnss rdnss, *p;
+ struct rtadv_rdnss rdnss = {0}, *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
@@ -3110,7 +3112,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
- struct rtadv_dnssl dnssl, *p;
+ struct rtadv_dnssl dnssl = {0}, *p;
int ret;
strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"),