summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md4
-rw-r--r--.gitignore1
-rw-r--r--babeld/babel_zebra.c2
-rw-r--r--bfdd/ptm_adapter.c17
-rw-r--r--bgpd/bgp_addpath.c422
-rw-r--r--bgpd/bgp_addpath.h72
-rw-r--r--bgpd/bgp_addpath_types.h55
-rw-r--r--bgpd/bgp_evpn.c5
-rw-r--r--bgpd/bgp_main.c10
-rw-r--r--bgpd/bgp_mplsvpn.c2
-rw-r--r--bgpd/bgp_network.c6
-rw-r--r--bgpd/bgp_nht.c45
-rw-r--r--bgpd/bgp_nht.h9
-rw-r--r--bgpd/bgp_open.c5
-rw-r--r--bgpd/bgp_route.c69
-rw-r--r--bgpd/bgp_route.h3
-rw-r--r--bgpd/bgp_routemap.c6
-rw-r--r--bgpd/bgp_table.c10
-rw-r--r--bgpd/bgp_table.h3
-rw-r--r--bgpd/bgp_updgrp.c24
-rw-r--r--bgpd/bgp_updgrp.h5
-rw-r--r--bgpd/bgp_updgrp_adv.c97
-rw-r--r--bgpd/bgp_updgrp_packet.c1
-rw-r--r--bgpd/bgp_vty.c161
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/bgpd.c133
-rw-r--r--bgpd/bgpd.h19
-rw-r--r--bgpd/rfapi/vnc_zebra.c2
-rw-r--r--bgpd/subdir.am3
-rwxr-xr-xconfigure.ac698
-rw-r--r--doc/developer/building-frr-for-centos6.rst6
-rw-r--r--doc/developer/building-frr-for-ubuntu1804.rst2
-rw-r--r--doc/developer/building-libyang.rst20
-rw-r--r--doc/developer/conf.py2
-rw-r--r--doc/developer/index.rst1
-rw-r--r--doc/developer/maintainer-release-build.rst4
-rw-r--r--doc/developer/modules.rst6
-rw-r--r--doc/developer/next-hop-tracking.rst2
-rw-r--r--doc/developer/packaging-debian.rst4
-rw-r--r--doc/developer/packaging.rst1
-rw-r--r--doc/developer/process-architecture.rst4
-rw-r--r--doc/developer/vtysh.rst201
-rw-r--r--doc/developer/workflow.rst58
-rw-r--r--doc/developer/zebra.rst383
-rw-r--r--doc/user/installation.rst22
-rw-r--r--doc/user/isisd.rst25
-rw-r--r--doc/user/ospfd.rst9
-rw-r--r--doc/user/static.rst6
-rw-r--r--doc/user/zebra.rst14
-rw-r--r--eigrpd/eigrp_zebra.c2
-rw-r--r--isisd/isis_lsp.c53
-rw-r--r--isisd/isis_zebra.c14
-rw-r--r--isisd/isisd.c188
-rw-r--r--isisd/isisd.h28
-rw-r--r--ldpd/lde.c2
-rw-r--r--ldpd/ldp_zebra.c2
-rw-r--r--lib/agentx.c3
-rw-r--r--lib/id_alloc.c406
-rw-r--r--lib/id_alloc.h90
-rw-r--r--lib/lib_errors.h2
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h1
-rw-r--r--lib/zclient.c6
-rw-r--r--lib/zclient.h17
-rw-r--r--nhrpd/nhrp_route.c2
-rw-r--r--ospf6d/ospf6_area.c18
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospfd/ospf_memory.c1
-rw-r--r--ospfd/ospf_memory.h1
-rw-r--r--ospfd/ospf_ri.c576
-rw-r--r--ospfd/ospf_ri.h66
-rw-r--r--ospfd/ospf_te.c8
-rw-r--r--ospfd/ospf_vty.c7
-rw-r--r--ospfd/ospf_zebra.c2
-rw-r--r--ospfd/ospfd.c26
-rw-r--r--ospfd/ospfd.h2
-rw-r--r--pbrd/pbr_zebra.c2
-rw-r--r--pimd/pim_zebra.c2
-rw-r--r--pimd/pim_zlookup.c2
-rw-r--r--ripd/rip_zebra.c2
-rw-r--r--ripngd/ripng_zebra.c2
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--staticd/static_routes.c60
-rw-r--r--staticd/static_routes.h2
-rw-r--r--staticd/static_zebra.c16
-rw-r--r--tests/.gitignore8
-rw-r--r--tests/bgpd/test_bgp_table.c2
-rw-r--r--tests/bgpd/test_mpath.c2
-rw-r--r--tests/bgpd/test_peer_attr.c13
-rw-r--r--tests/bgpd/test_peer_attr.py12
-rw-r--r--tests/isisd/test_isis_lspdb.c87
-rw-r--r--tests/isisd/test_isis_lspdb.py6
-rw-r--r--tests/lib/test_idalloc.c193
-rw-r--r--tests/lib/test_idalloc.py6
-rw-r--r--tests/subdir.am10
-rw-r--r--tests/test_lblmgr.c2
-rw-r--r--tools/etc/frr/daemons.conf3
-rwxr-xr-xtools/frr.in10
-rw-r--r--zebra/if_netlink.c31
-rw-r--r--zebra/interface.c69
-rw-r--r--zebra/interface.h10
-rw-r--r--zebra/label_manager.c2
-rw-r--r--zebra/rt_netlink.c2
-rw-r--r--zebra/rt_socket.c2
-rw-r--r--zebra/zapi_msg.c4
-rw-r--r--zebra/zebra_l2.c38
-rw-r--r--zebra/zebra_l2.h11
-rw-r--r--zebra/zebra_l2_null.c72
-rw-r--r--zebra/zebra_rib.c5
-rw-r--r--zebra/zebra_routemap.c41
-rw-r--r--zebra/zebra_router.c1
-rw-r--r--zebra/zebra_vrf.c1
113 files changed, 3558 insertions, 1370 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 0a8aa03c8d..9f44f712b1 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -6,7 +6,3 @@
### Components
[bgpd, build, doc, ripd, ospfd, eigrpd, isisd, etc. etc.]
-
-Always remember to follow proper coding style etc. as
-described in the FRRouting Dev Guide.
-http://docs.frrouting.org/projects/dev-guide/en/latest/workflow.html
diff --git a/.gitignore b/.gitignore
index ad3e3c80e0..05fcd6ce4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@
/conftest.err
/aclocal.m4
/libtool
+/libtool.orig
/Makefile
/Makefile.in
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c
index 8dea1431e2..e909f8ea7a 100644
--- a/babeld/babel_zebra.c
+++ b/babeld/babel_zebra.c
@@ -237,7 +237,7 @@ babel_zebra_connected (struct zclient *zclient)
void babelz_zebra_init(void)
{
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);
zclient->zebra_connected = babel_zebra_connected;
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index a5fae3383c..f9c7c16fb1 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -381,6 +381,21 @@ static int _ptm_msg_read(struct stream *msg, int command,
if (bpc->bpc_has_localif) {
STREAM_GET(bpc->bpc_localif, msg, ifnamelen);
bpc->bpc_localif[ifnamelen] = 0;
+
+ /*
+ * IPv6 link-local addresses must use scope id,
+ * otherwise the session lookup will always fail
+ * and we'll have multiple sessions showing up.
+ *
+ * This problem only happens with single hop
+ * since it is not possible to have link-local
+ * address for multi hop sessions.
+ */
+ if (bpc->bpc_ipv4 == false
+ && IN6_IS_ADDR_LINKLOCAL(
+ &bpc->bpc_peer.sa_sin6.sin6_addr))
+ bpc->bpc_peer.sa_sin6.sin6_scope_id =
+ ptm_bfd_fetch_ifindex(bpc->bpc_localif);
}
}
@@ -566,7 +581,7 @@ static void bfdd_zebra_connected(struct zclient *zc)
void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
{
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
assert(zclient != NULL);
zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
new file mode 100644
index 0000000000..22401f0017
--- /dev/null
+++ b/bgpd/bgp_addpath.c
@@ -0,0 +1,422 @@
+/*
+ * Addpath TX ID selection, and related utilities
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "bgp_addpath.h"
+#include "bgp_route.h"
+
+static struct bgp_addpath_strategy_names strat_names[BGP_ADDPATH_MAX] = {
+ {
+ .config_name = "addpath-tx-all-paths",
+ .human_name = "All",
+ .human_description = "Advertise all paths via addpath",
+ .type_json_name = "addpathTxAllPaths",
+ .id_json_name = "addpathTxIdAll"
+ },
+ {
+ .config_name = "addpath-tx-bestpath-per-AS",
+ .human_name = "Best-Per-AS",
+ .human_description = "Advertise bestpath per AS via addpath",
+ .type_json_name = "addpathTxBestpathPerAS",
+ .id_json_name = "addpathTxIdBestPerAS"
+ }
+};
+
+static struct bgp_addpath_strategy_names unknown_names = {
+ .config_name = "addpath-tx-unknown",
+ .human_name = "Unknown-Addpath-Strategy",
+ .human_description = "Unknown Addpath Strategy",
+ .type_json_name = "addpathTxUnknown",
+ .id_json_name = "addpathTxIdUnknown"
+};
+
+/*
+ * Returns a structure full of strings associated with an addpath type. Will
+ * never return null.
+ */
+struct bgp_addpath_strategy_names *
+bgp_addpath_names(enum bgp_addpath_strat strat)
+{
+ if (strat < BGP_ADDPATH_MAX)
+ return &(strat_names[strat]);
+ else
+ return &unknown_names;
+};
+
+/*
+ * Returns if any peer is transmitting addpaths for a given afi/safi.
+ */
+int bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi,
+ safi_t safi)
+{
+ return d->total_peercount[afi][safi] > 0;
+}
+
+/*
+ * Initialize the BGP instance level data for addpath.
+ */
+void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d)
+{
+ safi_t safi;
+ afi_t afi;
+ int i;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ d->id_allocators[afi][safi][i] = NULL;
+ d->peercount[afi][safi][i] = 0;
+ }
+ d->total_peercount[afi][safi] = 0;
+ }
+ }
+}
+
+/*
+ * Free up resources associated with BGP route info structures.
+ */
+void bgp_addpath_free_info_data(struct bgp_addpath_info_data *d,
+ struct bgp_addpath_node_data *nd)
+{
+ int i;
+
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ if (d->addpath_tx_id[i] != IDALLOC_INVALID)
+ idalloc_free_to_pool(&nd->free_ids[i],
+ d->addpath_tx_id[i]);
+ }
+}
+
+/*
+ * Return the addpath ID used to send a particular route, to a particular peer,
+ * in a particular AFI/SAFI.
+ */
+uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi,
+ struct bgp_addpath_info_data *d)
+{
+ if (peer->addpath_type[afi][safi] < BGP_ADDPATH_MAX)
+ return d->addpath_tx_id[peer->addpath_type[afi][safi]];
+ else
+ return IDALLOC_INVALID;
+}
+
+/*
+ * Returns true if the path has an assigned addpath ID for any of the addpath
+ * strategies.
+ */
+int bgp_addpath_info_has_ids(struct bgp_addpath_info_data *d)
+{
+ int i;
+
+ for (i = 0; i < BGP_ADDPATH_MAX; i++)
+ if (d->addpath_tx_id[i] != 0)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Releases any ID's associated with the BGP prefix.
+ */
+void bgp_addpath_free_node_data(struct bgp_addpath_bgp_data *bd,
+ struct bgp_addpath_node_data *nd, afi_t afi,
+ safi_t safi)
+{
+ int i;
+
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ idalloc_drain_pool(bd->id_allocators[afi][safi][i],
+ &(nd->free_ids[i]));
+ }
+}
+
+/*
+ * Check to see if the addpath strategy requires DMED to be configured to work.
+ */
+int bgp_addpath_dmed_required(int strategy)
+{
+ return strategy == BGP_ADDPATH_BEST_PER_AS;
+}
+
+/*
+ * Return true if this is a path we should advertise due to a
+ * configured addpath-tx knob
+ */
+int bgp_addpath_tx_path(enum bgp_addpath_strat strat,
+ struct bgp_path_info *pi)
+{
+ switch (strat) {
+ case BGP_ADDPATH_NONE:
+ return 0;
+ case BGP_ADDPATH_ALL:
+ return 1;
+ case BGP_ADDPATH_BEST_PER_AS:
+ if (CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))
+ return 1;
+ else
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Purge all addpath ID's on a BGP instance associated with the addpath
+ * strategy, and afi/safi combination. This lets us let go of all memory held to
+ * track ID numbers associated with an addpath type not in use. Since
+ * post-bestpath ID processing is skipped for types not used, this is the only
+ * chance to free this data.
+ */
+static void bgp_addpath_flush_type(struct bgp *bgp, afi_t afi, safi_t safi,
+ enum bgp_addpath_strat addpath_type)
+{
+ struct bgp_node *rn;
+ struct bgp_path_info *pi;
+
+ for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
+ rn = bgp_route_next(rn)) {
+ idalloc_drain_pool(
+ bgp->tx_addpath.id_allocators[afi][safi][addpath_type],
+ &(rn->tx_addpath.free_ids[addpath_type]));
+ for (pi = rn->info; pi; pi = pi->next) {
+ if (pi->tx_addpath.addpath_tx_id[addpath_type]
+ != IDALLOC_INVALID) {
+ idalloc_free(
+ bgp->tx_addpath
+ .id_allocators[afi][safi]
+ [addpath_type],
+ pi->tx_addpath
+ .addpath_tx_id[addpath_type]);
+ pi->tx_addpath.addpath_tx_id[addpath_type] =
+ IDALLOC_INVALID;
+ }
+ }
+ }
+
+ idalloc_destroy(bgp->tx_addpath.id_allocators[afi][safi][addpath_type]);
+ bgp->tx_addpath.id_allocators[afi][safi][addpath_type] = NULL;
+}
+
+/*
+ * Allocate an Addpath ID for the given type on a path, if necessary.
+ */
+static void bgp_addpath_populate_path(struct id_alloc *allocator,
+ struct bgp_path_info *path,
+ enum bgp_addpath_strat addpath_type)
+{
+ if (bgp_addpath_tx_path(addpath_type, path)) {
+ path->tx_addpath.addpath_tx_id[addpath_type] =
+ idalloc_allocate(allocator);
+ }
+}
+
+/*
+ * Compute addpath ID's on a BGP instance associated with the addpath strategy,
+ * and afi/safi combination. Since we won't waste the time computing addpath IDs
+ * for unused strategies, the first time a peer is configured to use a strategy,
+ * we have to backfill the data.
+ */
+static void bgp_addpath_populate_type(struct bgp *bgp, afi_t afi, safi_t safi,
+ enum bgp_addpath_strat addpath_type)
+{
+ struct bgp_node *rn;
+ struct bgp_path_info *bi;
+ char buf[200];
+ struct id_alloc *allocator;
+
+ snprintf(buf, sizeof(buf), "Addpath ID Allocator %s:%d/%d",
+ bgp_addpath_names(addpath_type)->config_name, (int)afi,
+ (int)safi);
+ buf[sizeof(buf) - 1] = '\0';
+ zlog_info("Computing addpath IDs for addpath type %s",
+ bgp_addpath_names(addpath_type)->human_name);
+
+ bgp->tx_addpath.id_allocators[afi][safi][addpath_type] =
+ idalloc_new(buf);
+
+ idalloc_reserve(bgp->tx_addpath.id_allocators[afi][safi][addpath_type],
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+
+ allocator = bgp->tx_addpath.id_allocators[afi][safi][addpath_type];
+
+ for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
+ rn = bgp_route_next(rn))
+ for (bi = rn->info; bi; bi = bi->next)
+ bgp_addpath_populate_path(allocator, bi, addpath_type);
+}
+
+/*
+ * Handle updates to a peer or group's addpath strategy. If after adjusting
+ * counts a addpath strategy is in use for the first time, or no longer in use,
+ * the IDs for that strategy will be populated or flushed.
+ */
+void bgp_addpath_type_changed(struct bgp *bgp)
+{
+ afi_t afi;
+ safi_t safi;
+ struct listnode *node, *nnode;
+ struct peer *peer;
+ int peer_count[AFI_MAX][SAFI_MAX][BGP_ADDPATH_MAX];
+ enum bgp_addpath_strat type;
+
+ FOREACH_AFI_SAFI(afi, safi) {
+ for (type=0; type<BGP_ADDPATH_MAX; type++) {
+ peer_count[afi][safi][type] = 0;
+ }
+ }
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ FOREACH_AFI_SAFI(afi, safi) {
+ type = peer->addpath_type[afi][safi];
+ if (type != BGP_ADDPATH_NONE) {
+ peer_count[afi][safi][type] += 1;
+ }
+ }
+ }
+
+ FOREACH_AFI_SAFI(afi, safi) {
+ for (type=0; type<BGP_ADDPATH_MAX; type++) {
+ int old = bgp->tx_addpath.peercount[afi][safi][type];
+ int new = peer_count[afi][safi][type];
+
+ bgp->tx_addpath.peercount[afi][safi][type] = new;
+
+ if (old == 0 && new != 0) {
+ bgp_addpath_populate_type(bgp, afi, safi,
+ type);
+ } else if (old != 0 && new == 0) {
+ bgp_addpath_flush_type(bgp, afi, safi, type);
+ }
+ }
+ }
+}
+
+/*
+ * Change the addpath type assigned to a peer, or peer group. In addition to
+ * adjusting the counts, peer sessions will be reset as needed to make the
+ * change take effect.
+ */
+void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
+ enum bgp_addpath_strat addpath_type)
+{
+ struct bgp *bgp = peer->bgp;
+ enum bgp_addpath_strat old_type = peer->addpath_type[afi][safi];
+ struct listnode *node, *nnode;
+ struct peer *tmp_peer;
+ struct peer_group *group;
+
+ if (addpath_type == old_type)
+ return;
+
+ if (addpath_type == BGP_ADDPATH_NONE && peer->group &&
+ !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* A "no" config on a group member inherits group */
+ addpath_type = peer->group->conf->addpath_type[afi][safi];
+ }
+
+ peer->addpath_type[afi][safi] = addpath_type;
+
+ bgp_addpath_type_changed(bgp);
+
+ if (addpath_type != BGP_ADDPATH_NONE) {
+ if (bgp_addpath_dmed_required(addpath_type)) {
+ if (!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
+ zlog_warn(
+ "%s: enabling bgp deterministic-med, this is required for addpath-tx-bestpath-per-AS",
+ peer->host);
+ bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED);
+ bgp_recalculate_all_bestpaths(bgp);
+ }
+ }
+ }
+
+ zlog_info("Resetting peer %s%s due to change in addpath config\n",
+ CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) ? "group " : "",
+ peer->host);
+
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ group = peer->group;
+
+ /* group will be null as peer_group_delete calls peer_delete on
+ * group->conf. That peer_delete will eventuallly end up here
+ * if the group was configured to tx addpaths.
+ */
+ if (group != NULL) {
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
+ tmp_peer)) {
+ if (tmp_peer->addpath_type[afi][safi] ==
+ old_type) {
+ bgp_addpath_set_peer_type(tmp_peer,
+ afi,
+ safi,
+ addpath_type);
+ }
+ }
+ }
+ } else {
+ peer_change_action(peer, afi, safi, peer_change_reset);
+ }
+
+}
+
+/*
+ * Intended to run after bestpath. This function will take TX IDs from paths
+ * that no longer need them, and give them to paths that do. This prevents
+ * best-per-as updates from needing to do a separate withdraw and update just to
+ * swap out which path is sent.
+ */
+void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_node *bn, afi_t afi,
+ safi_t safi)
+{
+ int i;
+ struct bgp_path_info *pi;
+ struct id_alloc_pool **pool_ptr;
+
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ struct id_alloc *alloc =
+ bgp->tx_addpath.id_allocators[afi][safi][i];
+ pool_ptr = &(bn->tx_addpath.free_ids[i]);
+
+ if (bgp->tx_addpath.peercount[afi][safi][i] == 0)
+ continue;
+
+ /* Free Unused IDs back to the pool.*/
+ for (pi = bn->info; pi; pi = pi->next) {
+ if (pi->tx_addpath.addpath_tx_id[i] != IDALLOC_INVALID
+ && !bgp_addpath_tx_path(i, pi)) {
+ idalloc_free_to_pool(pool_ptr,
+ pi->tx_addpath.addpath_tx_id[i]);
+ pi->tx_addpath.addpath_tx_id[i] =
+ IDALLOC_INVALID;
+ }
+ }
+
+ /* Give IDs to paths that need them (pulling from the pool) */
+ for (pi = bn->info; pi; pi = pi->next) {
+ if (pi->tx_addpath.addpath_tx_id[i] == IDALLOC_INVALID
+ && bgp_addpath_tx_path(i, pi)) {
+ pi->tx_addpath.addpath_tx_id[i] =
+ idalloc_allocate_prefer_pool(
+ alloc, pool_ptr);
+ }
+ }
+
+ /* Free any IDs left in the pool to the main allocator */
+ idalloc_drain_pool(alloc, pool_ptr);
+ }
+}
diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h
new file mode 100644
index 0000000000..c0c182791b
--- /dev/null
+++ b/bgpd/bgp_addpath.h
@@ -0,0 +1,72 @@
+/*
+ * Addpath TX ID selection, and related utilities
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _QUAGGA_BGPD_TX_ADDPATH_H
+#define _QUAGGA_BGPD_TX_ADDPATH_H
+
+#include <stdint.h>
+#include <zebra.h>
+
+#include "bgpd/bgp_addpath_types.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_table.h"
+#include "lib/json.h"
+
+#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
+
+void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d);
+
+int bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi,
+ safi_t safi);
+
+void bgp_addpath_free_node_data(struct bgp_addpath_bgp_data *bd,
+ struct bgp_addpath_node_data *nd,
+ afi_t afi, safi_t safi);
+
+void bgp_addpath_free_info_data(struct bgp_addpath_info_data *d,
+ struct bgp_addpath_node_data *nd);
+
+
+int bgp_addpath_info_has_ids(struct bgp_addpath_info_data *d);
+
+uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi,
+ struct bgp_addpath_info_data *d);
+
+struct bgp_addpath_strategy_names *
+bgp_addpath_names(enum bgp_addpath_strat strat);
+
+int bgp_addpath_dmed_required(int strategy);
+
+/*
+ * Return true if this is a path we should advertise due to a configured
+ * addpath-tx knob
+ */
+int bgp_addpath_tx_path(enum bgp_addpath_strat strat,
+ struct bgp_path_info *pi);
+/*
+ * Change the type of addpath used for a peer.
+ */
+void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
+ enum bgp_addpath_strat addpath_type);
+
+void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_node *bn, afi_t afi,
+ safi_t safi);
+
+void bgp_addpath_type_changed(struct bgp *bgp);
+#endif
diff --git a/bgpd/bgp_addpath_types.h b/bgpd/bgp_addpath_types.h
new file mode 100644
index 0000000000..b0b3302979
--- /dev/null
+++ b/bgpd/bgp_addpath_types.h
@@ -0,0 +1,55 @@
+/*
+ * Addpath TX ID selection, and related utilities
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _QUAGGA_BGPD_TX_ADDPATH_DATA_H
+#define _QUAGGA_BGPD_TX_ADDPATH_DATA_H
+#include "lib/id_alloc.h"
+#include <stdint.h>
+
+enum bgp_addpath_strat {
+ BGP_ADDPATH_ALL = 0,
+ BGP_ADDPATH_BEST_PER_AS,
+ BGP_ADDPATH_MAX,
+ BGP_ADDPATH_NONE,
+};
+
+/* TX Addpath structures */
+struct bgp_addpath_bgp_data {
+ unsigned int peercount[AFI_MAX][SAFI_MAX][BGP_ADDPATH_MAX];
+ unsigned int total_peercount[AFI_MAX][SAFI_MAX];
+ struct id_alloc *id_allocators[AFI_MAX][SAFI_MAX][BGP_ADDPATH_MAX];
+};
+
+struct bgp_addpath_node_data {
+ struct id_alloc_pool *free_ids[BGP_ADDPATH_MAX];
+};
+
+struct bgp_addpath_info_data {
+ uint32_t addpath_tx_id[BGP_ADDPATH_MAX];
+};
+
+struct bgp_addpath_strategy_names {
+ const char *config_name;
+ const char *human_name; /* path detail non-json */
+ const char *human_description; /* non-json peer descriptions */
+ const char *type_json_name; /* json peer listings */
+ const char *id_json_name; /* path json output for tx ID# */
+};
+
+#endif
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index cff050a9ef..fc3ac28723 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -47,6 +47,7 @@
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_addpath.h"
/*
* Definitions and external declarations.
@@ -1059,7 +1060,7 @@ static int evpn_es_route_select_install(struct bgp *bgp,
&& old_select->sub_type == BGP_ROUTE_IMPORTED
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
- && !bgp->addpath_tx_used[afi][safi]) {
+ && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
if (bgp_zebra_has_route_changed(rn, old_select)) {
ret = evpn_es_install_vtep(bgp, es,
(struct prefix_evpn *)&rn->p,
@@ -1142,7 +1143,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
&& old_select->sub_type == BGP_ROUTE_IMPORTED
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
- && !bgp->addpath_tx_used[afi][safi]) {
+ && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
if (bgp_zebra_has_route_changed(rn, old_select)) {
if (old_select->attr->sticky)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index bee885cff2..f8ff4f2f07 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -375,6 +375,7 @@ int main(int argc, char **argv)
int bgp_port = BGP_PORT_DEFAULT;
char *bgp_address = NULL;
int no_fib_flag = 0;
+ int no_zebra_flag = 0;
int skip_runas = 0;
int instance = 0;
@@ -384,6 +385,7 @@ int main(int argc, char **argv)
" -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
" -l, --listenon Listen on specified address (implies -n)\n"
" -n, --no_kernel Do not install route to kernel.\n"
+ " -Z, --no_zebra Do not communicate with Zebra.\n"
" -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
" -e, --ecmp Specify ECMP to use.\n"
" -I, --int_num Set instance number (label-manager)\n");
@@ -430,6 +432,9 @@ int main(int argc, char **argv)
case 'n':
no_fib_flag = 1;
break;
+ case 'Z':
+ no_zebra_flag = 1;
+ break;
case 'S':
skip_runas = 1;
break;
@@ -453,9 +458,10 @@ int main(int argc, char **argv)
if (bgp_port == 0)
bgp_option_set(BGP_OPT_NO_LISTEN);
bm->address = bgp_address;
- if (no_fib_flag)
+ if (no_fib_flag || no_zebra_flag)
bgp_option_set(BGP_OPT_NO_FIB);
-
+ if (no_zebra_flag)
+ bgp_option_set(BGP_OPT_NO_ZEBRA);
bgp_error_init();
/* Initializations. */
bgp_vrf_init();
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index d4204126e1..6668823d64 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -578,7 +578,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
return bpi;
}
- new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
+ new = info_make(bpi_ultimate->type, bpi_ultimate->sub_type, 0,
bgp->peer_self, new_attr, bn);
if (nexthop_self_flag)
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 191b1641b2..e15b8f4ec3 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -708,7 +708,11 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
gai_strerror(ret));
return -1;
}
-
+ if (bgp_option_check(BGP_OPT_NO_ZEBRA) &&
+ bgp->vrf_id != VRF_DEFAULT) {
+ freeaddrinfo(ainfo_save);
+ return -1;
+ }
count = 0;
for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) {
int sock;
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 8aa7798af4..0dce96f432 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -838,3 +838,48 @@ void bgp_nht_register_nexthops(struct bgp *bgp)
}
}
}
+
+void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
+{
+ struct bgp *bgp;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct nexthop *nhop;
+ struct interface *ifp;
+ struct prefix p;
+
+ if (peer->ifp)
+ return;
+
+ bgp = peer->bgp;
+
+ if (!bgp->nexthop_cache_table[AFI_IP6])
+ return;
+
+ if (!sockunion2hostprefix(&peer->su, &p)) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s: Unable to convert prefix to sockunion",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+
+ if (p.family != AF_INET6)
+ return;
+ rn = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
+
+ bnc = bgp_nexthop_get_node_info(rn);
+ if (!bnc)
+ return;
+
+ if (peer != bnc->nht_info)
+ return;
+
+ for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
+ ifp = if_lookup_by_index(nhop->ifindex,
+ nhop->vrf_id);
+ zclient_send_interface_radv_req(zclient,
+ nhop->vrf_id,
+ ifp, true,
+ BGP_UNNUM_DEFAULT_RA_INTERVAL);
+ }
+}
diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h
index 96dd915596..7daae93b25 100644
--- a/bgpd/bgp_nht.h
+++ b/bgpd/bgp_nht.h
@@ -88,4 +88,13 @@ extern void path_nh_map(struct bgp_path_info *path,
*/
extern void bgp_nht_register_nexthops(struct bgp *bgp);
+/*
+ * When we have the the PEER_FLAG_CAPABILITY_ENHE flag
+ * set on a peer *after* it has been brought up we need
+ * to notice and setup the interface based RA,
+ * this code can walk the registered nexthops and
+ * register the important ones with zebra for RA.
+ */
+extern void bgp_nht_register_enhe_capability_interfaces(struct peer *peer);
+
#endif /* _BGP_NHT_H */
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index cf5901df5a..3018124f45 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1387,10 +1387,7 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
/* Only advertise addpath TX if a feature that
* will use it is
* configured */
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_ALL_PATHS)
- || CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
+ if (peer->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
adv_addpath_tx = 1;
}
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 8ae74a008c..bb8c5d8f6e 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -65,6 +65,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_label.h"
+#include "bgpd/bgp_addpath.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -247,6 +248,8 @@ static void bgp_path_info_free(struct bgp_path_info *path)
bgp_unlink_nexthop(path);
bgp_path_info_extra_free(&path->extra);
bgp_path_info_mpath_free(&path->mpath);
+ bgp_addpath_free_info_data(&path->tx_addpath,
+ path->net ? &path->net->tx_addpath : NULL);
peer_unlock(path->peer); /* bgp_path_info peer reference */
@@ -1472,7 +1475,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
* addpath
* feature that requires us to advertise it */
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
- if (!bgp_addpath_tx_path(peer, afi, safi, pi)) {
+ if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
return 0;
}
}
@@ -2078,6 +2081,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
bgp_path_info_mpath_aggregate_update(new_select, old_select);
bgp_mp_list_clear(&mp_list);
+ bgp_addpath_update_ids(bgp, rn, afi, safi);
+
result->old = old_select;
result->new = new_select;
@@ -2127,7 +2132,7 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp,
bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
else
bgp_adj_out_unset_subgroup(rn, subgrp, 1,
- selected->addpath_tx_id);
+ addpath_tx_id);
}
/* If selected is NULL we must withdraw the path using addpath_tx_id */
@@ -2303,7 +2308,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
if (old_select && old_select == new_select
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
- && !bgp->addpath_tx_used[afi][safi]) {
+ && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
if (bgp_zebra_has_route_changed(rn, old_select)) {
#if ENABLE_BGP_VNC
vnc_import_bgp_add_route(bgp, p, old_select);
@@ -2776,7 +2781,6 @@ struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
new->attr = attr;
new->uptime = bgp_clock();
new->net = rn;
- new->addpath_tx_id = ++peer->bgp->addpath_tx_id;
return new;
}
@@ -7486,6 +7490,18 @@ static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
}
}
+static void route_vty_out_tx_ids(struct vty *vty,
+ struct bgp_addpath_info_data *d)
+{
+ int i;
+
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
+ d->addpath_tx_id[i],
+ i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
+ }
+}
+
void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
struct bgp_path_info *path, afi_t afi, safi_t safi,
json_object *json_paths)
@@ -7517,6 +7533,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
unsigned int first_as;
bool nexthop_self =
CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
+ int i;
if (json_paths) {
json_path = json_object_new_object();
@@ -8228,29 +8245,53 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
}
/* Line 8 display Addpath IDs */
- if (path->addpath_rx_id || path->addpath_tx_id) {
+ if (path->addpath_rx_id
+ || bgp_addpath_info_has_ids(&path->tx_addpath)) {
if (json_paths) {
json_object_int_add(json_path, "addpathRxId",
path->addpath_rx_id);
- json_object_int_add(json_path, "addpathTxId",
- path->addpath_tx_id);
+
+ /* Keep backwards compatibility with the old API
+ * by putting TX All's ID in the old field
+ */
+ json_object_int_add(
+ json_path, "addpathTxId",
+ path->tx_addpath.addpath_tx_id
+ [BGP_ADDPATH_ALL]);
+
+ /* ... but create a specific field for each
+ * strategy
+ */
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ json_object_int_add(
+ json_path,
+ bgp_addpath_names(i)
+ ->id_json_name,
+ path->tx_addpath
+ .addpath_tx_id[i]);
+ }
} else {
- vty_out(vty, " AddPath ID: RX %u, TX %u\n",
- path->addpath_rx_id,
- path->addpath_tx_id);
+ vty_out(vty, " AddPath ID: RX %u, ",
+ path->addpath_rx_id);
+
+ route_vty_out_tx_ids(vty, &path->tx_addpath);
}
}
/* If we used addpath to TX a non-bestpath we need to display
- * "Advertised to" on a path-by-path basis */
- if (bgp->addpath_tx_used[afi][safi]) {
+ * "Advertised to" on a path-by-path basis
+ */
+ if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
first = 1;
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
addpath_capable =
bgp_addpath_encode_tx(peer, afi, safi);
has_adj = bgp_adj_out_lookup(
- peer, path->net, path->addpath_tx_id);
+ peer, path->net,
+ bgp_addpath_id_for_peer(
+ peer, afi, safi,
+ &path->tx_addpath));
if ((addpath_capable && has_adj)
|| (!addpath_capable && has_adj
@@ -8958,7 +8999,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
* show what peers we advertised the bestpath to. If we are using
* addpath
* though then we must display Advertised to on a path-by-path basis. */
- if (!bgp->addpath_tx_used[afi][safi]) {
+ if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (bgp_adj_out_lookup(peer, rn, 0)) {
if (json && !json_adv_to)
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index f0edc8d49a..466d52ed64 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -24,6 +24,7 @@
#include "queue.h"
#include "nexthop.h"
#include "bgp_table.h"
+#include "bgp_addpath_types.h"
struct bgp_nexthop_cache;
struct bgp_route_evpn;
@@ -220,7 +221,7 @@ struct bgp_path_info {
/* Addpath identifiers */
uint32_t addpath_rx_id;
- uint32_t addpath_tx_id;
+ struct bgp_addpath_info_data tx_addpath;
};
/* Structure used in BGP path selection */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index f7c4175383..fc27c546b4 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -4076,6 +4076,11 @@ DEFUN (no_set_aspath_exclude,
return ret;
}
+ALIAS(no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
+ "no set as-path exclude",
+ NO_STR SET_STR
+ "Transform BGP AS_PATH attribute\n"
+ "Exclude from the as-path\n")
DEFUN (set_community,
set_community_cmd,
@@ -4965,6 +4970,7 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_aspath_exclude_cmd);
install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
+ install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
install_element(RMAP_NODE, &set_origin_cmd);
install_element(RMAP_NODE, &no_set_origin_cmd);
install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 231f326cef..728eeaa3a9 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -29,6 +29,7 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
+#include "bgp_addpath.h"
void bgp_table_lock(struct bgp_table *rt)
{
@@ -76,7 +77,16 @@ static void bgp_node_destroy(route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
{
struct bgp_node *bgp_node;
+ struct bgp_table *rt;
bgp_node = bgp_node_from_rnode(node);
+ rt = table->info;
+
+ if (rt->bgp) {
+ bgp_addpath_free_node_data(&rt->bgp->tx_addpath,
+ &bgp_node->tx_addpath,
+ rt->afi, rt->safi);
+ }
+
XFREE(MTYPE_BGP_NODE, bgp_node);
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 60a26b76cc..c267b4fe8a 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -25,6 +25,7 @@
#include "table.h"
#include "queue.h"
#include "linklist.h"
+#include "bgpd.h"
struct bgp_table {
/* table belongs to this instance */
@@ -67,6 +68,8 @@ struct bgp_node {
#define BGP_NODE_USER_CLEAR (1 << 1)
#define BGP_NODE_LABEL_CHANGED (1 << 2)
#define BGP_NODE_REGISTERED_FOR_LABEL (1 << 3)
+
+ struct bgp_addpath_node_data tx_addpath;
};
/*
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 393586dbec..2e2ad88314 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -152,6 +152,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->af_cap[afi][safi] = src->af_cap[afi][safi];
dst->afc_nego[afi][safi] = src->afc_nego[afi][safi];
dst->orf_plist[afi][safi] = src->orf_plist[afi][safi];
+ dst->addpath_type[afi][safi] = src->addpath_type[afi][safi];
dst->local_as = src->local_as;
dst->change_local_as = src->change_local_as;
dst->shared_network = src->shared_network;
@@ -322,6 +323,7 @@ static unsigned int updgrp_hash_key_make(void *p)
key = jhash_1word(peer->sort, key); /* EBGP or IBGP */
key = jhash_1word((peer->flags & PEER_UPDGRP_FLAGS), key);
key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key);
+ key = jhash_1word((uint32_t)peer->addpath_type[afi][safi], key);
key = jhash_1word((peer->cap & PEER_UPDGRP_CAP_FLAGS), key);
key = jhash_1word((peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS),
key);
@@ -437,6 +439,9 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
if ((flags1 & PEER_UPDGRP_AF_FLAGS) != (flags2 & PEER_UPDGRP_AF_FLAGS))
return false;
+ if (pe1->addpath_type[afi][safi] != pe2->addpath_type[afi][safi])
+ return 0;
+
if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS)
!= (pe2->cap & PEER_UPDGRP_CAP_FLAGS))
return false;
@@ -1900,22 +1905,3 @@ int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi)
&& CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_RX_RCV));
}
-
-/*
- * Return true if this is a path we should advertise due to a
- * configured addpath-tx knob
- */
-int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_path_info *pi)
-{
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_ALL_PATHS))
- return 1;
-
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)
- && CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))
- return 1;
-
- return 0;
-}
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index b1d852d384..6b3bf9d1f7 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -64,8 +64,7 @@
| PEER_FLAG_REMOVE_PRIVATE_AS_ALL \
| PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \
| PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \
- | PEER_FLAG_ADDPATH_TX_ALL_PATHS \
- | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | PEER_FLAG_AS_OVERRIDE)
+ | PEER_FLAG_AS_OVERRIDE)
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
@@ -469,8 +468,6 @@ extern int update_group_clear_update_dbg(struct update_group *updgrp,
extern void update_bgp_group_free(struct bgp *bgp);
extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
-extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_path_info *pi);
/*
* Inline functions
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 81b782c2b0..7196bbbf12 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -49,6 +49,7 @@
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_addpath.h"
/********************
@@ -97,6 +98,40 @@ static void adj_free(struct bgp_adj_out *adj)
XFREE(MTYPE_BGP_ADJ_OUT, adj);
}
+static void subgrp_withdraw_stale_addpath(struct updwalk_context *ctx,
+ struct update_subgroup *subgrp)
+{
+ struct bgp_adj_out *adj, *adj_next;
+ uint32_t id;
+ struct bgp_path_info *pi;
+ afi_t afi = SUBGRP_AFI(subgrp);
+ safi_t safi = SUBGRP_SAFI(subgrp);
+ struct peer *peer = SUBGRP_PEER(subgrp);
+
+ /* Look through all of the paths we have advertised for this rn and send
+ * a withdraw for the ones that are no longer present */
+ for (adj = ctx->rn->adj_out; adj; adj = adj_next) {
+ adj_next = adj->next;
+
+ if (adj->subgroup == subgrp) {
+ for (pi = ctx->rn->info; pi; pi = pi->next) {
+ id = bgp_addpath_id_for_peer(peer, afi, safi,
+ &pi->tx_addpath);
+
+ if (id == adj->addpath_tx_id) {
+ break;
+ }
+ }
+
+ if (!pi) {
+ subgroup_process_announce_selected(
+ subgrp, NULL, ctx->rn,
+ adj->addpath_tx_id);
+ }
+ }
+ }
+}
+
static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
{
struct updwalk_context *ctx = arg;
@@ -131,31 +166,7 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
if (!subgrp->t_coalesce) {
/* An update-group that uses addpath */
if (addpath_capable) {
- /* Look through all of the paths we have
- * advertised for this rn and
- * send a withdraw for the ones that are no
- * longer present */
- for (adj = ctx->rn->adj_out; adj;
- adj = adj_next) {
- adj_next = adj->next;
-
- if (adj->subgroup == subgrp) {
- for (pi = ctx->rn->info; pi;
- pi = pi->next) {
- if (pi->addpath_tx_id
- == adj->addpath_tx_id) {
- break;
- }
- }
-
- if (!pi) {
- subgroup_process_announce_selected(
- subgrp, NULL,
- ctx->rn,
- adj->addpath_tx_id);
- }
- }
- }
+ subgrp_withdraw_stale_addpath(ctx, subgrp);
for (pi = ctx->rn->info; pi; pi = pi->next) {
/* Skip the bestpath for now */
@@ -164,7 +175,9 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
subgroup_process_announce_selected(
subgrp, pi, ctx->rn,
- pi->addpath_tx_id);
+ bgp_addpath_id_for_peer(
+ peer, afi, safi,
+ &pi->tx_addpath));
}
/* Process the bestpath last so the "show [ip]
@@ -174,7 +187,9 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
if (ctx->pi)
subgroup_process_announce_selected(
subgrp, ctx->pi, ctx->rn,
- ctx->pi->addpath_tx_id);
+ bgp_addpath_id_for_peer(
+ peer, afi, safi,
+ &ctx->pi->tx_addpath));
}
/* An update-group that does not use addpath */
@@ -182,7 +197,9 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
if (ctx->pi) {
subgroup_process_announce_selected(
subgrp, ctx->pi, ctx->rn,
- ctx->pi->addpath_tx_id);
+ bgp_addpath_id_for_peer(
+ peer, afi, safi,
+ &ctx->pi->tx_addpath));
} else {
/* Find the addpath_tx_id of the path we
* had advertised and
@@ -433,15 +450,27 @@ void bgp_adj_out_set_subgroup(struct bgp_node *rn,
{
struct bgp_adj_out *adj = NULL;
struct bgp_advertise *adv;
+ struct peer *peer;
+ afi_t afi;
+ safi_t safi;
+
+ peer = SUBGRP_PEER(subgrp);
+ afi = SUBGRP_AFI(subgrp);
+ safi = SUBGRP_SAFI(subgrp);
if (DISABLE_BGP_ANNOUNCE)
return;
/* Look for adjacency information. */
- adj = adj_lookup(rn, subgrp, path->addpath_tx_id);
+ adj = adj_lookup(
+ rn, subgrp,
+ bgp_addpath_id_for_peer(peer, afi, safi, &path->tx_addpath));
if (!adj) {
- adj = bgp_adj_out_alloc(subgrp, rn, path->addpath_tx_id);
+ adj = bgp_adj_out_alloc(
+ subgrp, rn,
+ bgp_addpath_id_for_peer(peer, afi, safi,
+ &path->tx_addpath));
if (!adj)
return;
}
@@ -597,7 +626,9 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)
|| (addpath_capable
- && bgp_addpath_tx_path(peer, afi, safi, ri))) {
+ && bgp_addpath_tx_path(
+ peer->addpath_type[afi][safi],
+ ri))) {
if (subgroup_announce_check(rn, ri, subgrp,
&rn->p, &attr))
bgp_adj_out_set_subgroup(rn, subgrp,
@@ -605,7 +636,9 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
else
bgp_adj_out_unset_subgroup(
rn, subgrp, 1,
- ri->addpath_tx_id);
+ bgp_addpath_id_for_peer(
+ peer, afi, safi,
+ &ri->tx_addpath));
}
/*
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index c4fcea948f..ca6bb5ab82 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -56,6 +56,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_label.h"
+#include "bgpd/bgp_addpath.h"
/********************
* PRIVATE FUNCTIONS
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index c57cd38151..85b6414e48 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -61,6 +61,7 @@
#include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_io.h"
#include "bgpd/bgp_evpn.h"
+#include "bgpd/bgp_addpath.h"
static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
@@ -1888,9 +1889,8 @@ DEFUN (no_bgp_deterministic_med,
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
FOREACH_AFI_SAFI (afi, safi)
- if (CHECK_FLAG(
- peer->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
+ if (bgp_addpath_dmed_required(
+ peer->addpath_type[afi][safi])) {
bestpath_per_as_used = 1;
break;
}
@@ -6234,9 +6234,9 @@ DEFUN (neighbor_addpath_tx_all_paths,
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
- bgp_node_safi(vty),
- PEER_FLAG_ADDPATH_TX_ALL_PATHS);
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_ALL);
+ return CMD_SUCCESS;
}
ALIAS_HIDDEN(neighbor_addpath_tx_all_paths,
@@ -6254,9 +6254,23 @@ DEFUN (no_neighbor_addpath_tx_all_paths,
"Use addpath to advertise all paths to a neighbor\n")
{
int idx_peer = 2;
- return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
- bgp_node_afi(vty), bgp_node_safi(vty),
- PEER_FLAG_ADDPATH_TX_ALL_PATHS);
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer->addpath_type[bgp_node_afi(vty)][bgp_node_safi(vty)]
+ != BGP_ADDPATH_ALL) {
+ vty_out(vty,
+ "%% Peer not currently configured to transmit all paths.");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_NONE);
+
+ return CMD_SUCCESS;
}
ALIAS_HIDDEN(no_neighbor_addpath_tx_all_paths,
@@ -6279,9 +6293,10 @@ DEFUN (neighbor_addpath_tx_bestpath_per_as,
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
- bgp_node_safi(vty),
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS);
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_BEST_PER_AS);
+
+ return CMD_SUCCESS;
}
ALIAS_HIDDEN(neighbor_addpath_tx_bestpath_per_as,
@@ -6299,9 +6314,23 @@ DEFUN (no_neighbor_addpath_tx_bestpath_per_as,
"Use addpath to advertise the bestpath per each neighboring AS\n")
{
int idx_peer = 2;
- return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
- bgp_node_afi(vty), bgp_node_safi(vty),
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS);
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer->addpath_type[bgp_node_afi(vty)][bgp_node_safi(vty)]
+ != BGP_ADDPATH_BEST_PER_AS) {
+ vty_out(vty,
+ "%% Peer not currently configured to transmit all best path per as.");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_NONE);
+
+ return CMD_SUCCESS;
}
ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as,
@@ -8656,15 +8685,11 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
json_addr,
"privateAsNumsRemovedInUpdatesToNbr");
- if (CHECK_FLAG(p->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_ALL_PATHS))
- json_object_boolean_true_add(json_addr,
- "addpathTxAllPaths");
-
- if (CHECK_FLAG(p->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
- json_object_boolean_true_add(json_addr,
- "addpathTxBestpathPerAS");
+ if (p->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
+ json_object_boolean_true_add(
+ json_addr,
+ bgp_addpath_names(p->addpath_type[afi][safi])
+ ->type_json_name);
if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
json_object_string_add(json_addr,
@@ -8930,14 +8955,10 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
vty_out(vty,
" Private AS numbers removed in updates to this neighbor\n");
- if (CHECK_FLAG(p->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_ALL_PATHS))
- vty_out(vty, " Advertise all paths via addpath\n");
-
- if (CHECK_FLAG(p->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
- vty_out(vty,
- " Advertise bestpath per AS via addpath\n");
+ if (p->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
+ vty_out(vty, " %s\n",
+ bgp_addpath_names(p->addpath_type[afi][safi])
+ ->human_description);
if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
vty_out(vty,
@@ -13965,6 +13986,7 @@ DEFUN (no_community_list_standard_all,
COMMUNITY_VAL_STR)
{
char *cl_name_or_number = NULL;
+ char *str = NULL;
int direct = 0;
int style = COMMUNITY_LIST_STANDARD;
@@ -13977,13 +13999,23 @@ DEFUN (no_community_list_standard_all,
zlog_warn("Deprecated option: 'no ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> |AA:NN' being used");
}
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+
+ if (idx) {
+ direct = argv_find(argv, argc, "permit", &idx)
+ ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "AA:NN", &idx);
+ str = argv_concat(argv, argc, idx);
+ }
+
+ idx = 0;
argv_find(argv, argc, "(1-99)", &idx);
argv_find(argv, argc, "WORD", &idx);
cl_name_or_number = argv[idx]->arg;
- direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
- : COMMUNITY_DENY;
- argv_find(argv, argc, "AA:NN", &idx);
- char *str = argv_concat(argv, argc, idx);
int ret = community_list_unset(bgp_clist, cl_name_or_number, str,
direct, style);
@@ -14010,6 +14042,20 @@ ALIAS (no_community_list_standard_all,
"Specify community to accept\n"
COMMUNITY_VAL_STR)
+ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cmd,
+ "no bgp community-list <(1-99)|standard WORD>",
+ NO_STR BGP_STR COMMUNITY_LIST_STR
+ "Community list number (standard)\n"
+ "Add an standard community-list entry\n"
+ "Community list name\n")
+
+ALIAS(no_community_list_standard_all, no_ip_community_list_standard_all_list_cmd,
+ "no ip community-list <(1-99)|standard WORD>",
+ NO_STR BGP_STR COMMUNITY_LIST_STR
+ "Community list number (standard)\n"
+ "Add an standard community-list entry\n"
+ "Community list name\n")
+
/*community-list expanded */
DEFUN (community_list_expanded_all,
bgp_community_list_expanded_all_cmd,
@@ -14082,6 +14128,7 @@ DEFUN (no_community_list_expanded_all,
COMMUNITY_VAL_STR)
{
char *cl_name_or_number = NULL;
+ char *str = NULL;
int direct = 0;
int style = COMMUNITY_LIST_EXPANDED;
@@ -14089,16 +14136,28 @@ DEFUN (no_community_list_expanded_all,
if (argv_find(argv, argc, "ip", &idx)) {
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
vty_out(vty, "if you are using this please migrate to the below command.\n");
- vty_out(vty, "'no community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN'\n");
- zlog_warn("Deprecated option: 'no community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN' being used");
+ vty_out(vty, "'no bgp community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN'\n");
+ zlog_warn("Deprecated option: 'no ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN' being used");
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+
+ if (idx) {
+ direct = argv_find(argv, argc, "permit", &idx)
+ ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "AA:NN", &idx);
+ str = argv_concat(argv, argc, idx);
}
+
+ idx = 0;
argv_find(argv, argc, "(100-500)", &idx);
argv_find(argv, argc, "WORD", &idx);
cl_name_or_number = argv[idx]->arg;
- direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
- : COMMUNITY_DENY;
- argv_find(argv, argc, "AA:NN", &idx);
- char *str = argv_concat(argv, argc, idx);
int ret = community_list_unset(bgp_clist, cl_name_or_number, str,
direct, style);
@@ -14126,6 +14185,20 @@ ALIAS (no_community_list_expanded_all,
"Specify community to accept\n"
COMMUNITY_VAL_STR)
+ALIAS(no_community_list_expanded_all, no_bgp_community_list_expanded_all_list_cmd,
+ "no bgp community-list <(100-500)|expanded WORD>",
+ NO_STR IP_STR COMMUNITY_LIST_STR
+ "Community list number (expanded)\n"
+ "Add an expanded community-list entry\n"
+ "Community list name\n")
+
+ALIAS(no_community_list_expanded_all, no_ip_community_list_expanded_all_list_cmd,
+ "no ip community-list <(100-500)|expanded WORD>",
+ NO_STR IP_STR COMMUNITY_LIST_STR
+ "Community list number (expanded)\n"
+ "Add an expanded community-list entry\n"
+ "Community list name\n")
+
/* Return configuration string of community-list entry. */
static const char *community_list_config_str(struct community_entry *entry)
{
@@ -15206,13 +15279,17 @@ static void community_list_vty(void)
install_element(CONFIG_NODE, &bgp_community_list_standard_cmd);
install_element(CONFIG_NODE, &bgp_community_list_expanded_all_cmd);
install_element(CONFIG_NODE, &no_bgp_community_list_standard_all_cmd);
+ install_element(CONFIG_NODE, &no_bgp_community_list_standard_all_list_cmd);
install_element(CONFIG_NODE, &no_bgp_community_list_expanded_all_cmd);
+ install_element(CONFIG_NODE, &no_bgp_community_list_expanded_all_list_cmd);
install_element(VIEW_NODE, &show_bgp_community_list_cmd);
install_element(VIEW_NODE, &show_bgp_community_list_arg_cmd);
install_element(CONFIG_NODE, &ip_community_list_standard_cmd);
install_element(CONFIG_NODE, &ip_community_list_expanded_all_cmd);
install_element(CONFIG_NODE, &no_ip_community_list_standard_all_cmd);
+ install_element(CONFIG_NODE, &no_ip_community_list_standard_all_list_cmd);
install_element(CONFIG_NODE, &no_ip_community_list_expanded_all_cmd);
+ install_element(CONFIG_NODE, &no_ip_community_list_expanded_all_list_cmd);
install_element(VIEW_NODE, &show_ip_community_list_cmd);
install_element(VIEW_NODE, &show_ip_community_list_arg_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 50b790eb11..62f977eee1 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2574,7 +2574,7 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)
zclient_num_connects = 0;
/* Set default values. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
zclient->router_id_update = bgp_router_id_update;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 19384eec2f..a078c4f587 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -85,6 +85,7 @@
#include "bgpd/bgp_flowspec.h"
#include "bgpd/bgp_labelpool.h"
#include "bgpd/bgp_pbr.h"
+#include "bgpd/bgp_addpath.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
DEFINE_QOBJ_TYPE(bgp_master)
@@ -170,6 +171,7 @@ int bgp_option_set(int flag)
case BGP_OPT_MULTIPLE_INSTANCE:
case BGP_OPT_CONFIG_CISCO:
case BGP_OPT_NO_LISTEN:
+ case BGP_OPT_NO_ZEBRA:
SET_FLAG(bm->options, flag);
break;
default:
@@ -185,6 +187,7 @@ int bgp_option_unset(int flag)
if (listcount(bm->bgp) > 1)
return BGP_ERR_MULTIPLE_INSTANCE_USED;
/* Fall through. */
+ case BGP_OPT_NO_ZEBRA:
case BGP_OPT_NO_FIB:
case BGP_OPT_CONFIG_CISCO:
UNSET_FLAG(bm->options, flag);
@@ -883,6 +886,31 @@ static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi,
}
}
+/* Return true if the addpath type is set for peer and different from
+ * peer-group.
+ */
+static int peergroup_af_addpath_check(struct peer *peer, afi_t afi, safi_t safi)
+{
+ enum bgp_addpath_strat type, g_type;
+
+ type = peer->addpath_type[afi][safi];
+
+ if (type != BGP_ADDPATH_NONE) {
+ if (peer_group_active(peer)) {
+ g_type = peer->group->conf->addpath_type[afi][safi];
+
+ if (type != g_type)
+ return 1;
+ else
+ return 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
/* Check peer's AS number and determines if this peer is IBGP or EBGP */
static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
{
@@ -960,6 +988,9 @@ bgp_peer_sort_t peer_sort(struct peer *peer)
static void peer_free(struct peer *peer)
{
+ afi_t afi;
+ safi_t safi;
+
assert(peer->status == Deleted);
QOBJ_UNREG(peer);
@@ -1032,6 +1063,13 @@ static void peer_free(struct peer *peer)
bfd_info_free(&(peer->bfd_info));
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ bgp_addpath_set_peer_type(peer, afi, safi,
+ BGP_ADDPATH_NONE);
+ }
+ }
+
bgp_unlock(peer->bgp);
memset(peer, 0, sizeof(struct peer));
@@ -1118,6 +1156,7 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->af_flags_invert[afi][safi],
PEER_FLAG_SEND_LARGE_COMMUNITY);
}
+ peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
}
/* set nexthop-unchanged for l2vpn evpn by default */
@@ -1210,6 +1249,8 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
peer_dst->allowas_in[afi][safi] =
peer_src->allowas_in[afi][safi];
peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
+ peer_dst->addpath_type[afi][safi] =
+ peer_src->addpath_type[afi][safi];
}
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
@@ -1808,6 +1849,11 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
}
+
+ if (peer->addpath_type[afi][safi] == BGP_ADDPATH_NONE) {
+ peer->addpath_type[afi][safi] = conf->addpath_type[afi][safi];
+ bgp_addpath_type_changed(conf->bgp);
+ }
}
static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
@@ -2836,7 +2882,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
#if DFLT_BGP_DETERMINISTIC_MED
bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED);
#endif
- bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
+ bgp_addpath_init_bgp_data(&bgp->tx_addpath);
bgp->as = *as;
@@ -3051,6 +3097,8 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
}
bgp = bgp_create(as, name, inst_type);
+ if (bgp_option_check(BGP_OPT_NO_ZEBRA) && name)
+ bgp->vrf_id = vrf_generate_id();
bgp_router_id_set(bgp, &bgp->router_id_zebra);
bgp_address_init(bgp);
bgp_tip_hash_init(bgp);
@@ -3627,15 +3675,7 @@ int peer_active_nego(struct peer *peer)
return 0;
}
-/* peer_flag_change_type. */
-enum peer_change_type {
- peer_change_none,
- peer_change_reset,
- peer_change_reset_in,
- peer_change_reset_out,
-};
-
-static void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
+void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
enum peer_change_type type)
{
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
@@ -3731,8 +3771,6 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
{PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
{PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
- {PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset},
- {PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset},
{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
{0, 0, 0}};
@@ -3905,6 +3943,9 @@ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
return 0;
}
+ if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
+ bgp_nht_register_enhe_capability_interfaces(peer);
+
/*
* Update peer-group members, unless they are explicitely overriding
* peer-group configuration.
@@ -3928,6 +3969,9 @@ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
/* Update flag on peer-group member. */
COND_FLAG(member->flags, flag, set != member_invert);
+ if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
+ bgp_nht_register_enhe_capability_interfaces(member);
+
/* Execute flag action on peer-group member. */
if (action.type == peer_change_reset)
peer_flag_modify_action(member, flag);
@@ -3951,9 +3995,7 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
{
int found;
int size;
- int addpath_tx_used;
bool invert, member_invert;
- struct bgp *bgp;
struct peer *member;
struct listnode *node, *nnode;
struct peer_flag_action action;
@@ -4116,45 +4158,6 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
}
}
- /* Track if addpath TX is in use */
- if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
- | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
- bgp = peer->bgp;
- addpath_tx_used = 0;
-
- if (set) {
- addpath_tx_used = 1;
-
- if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) {
- if (!bgp_flag_check(
- bgp, BGP_FLAG_DETERMINISTIC_MED)) {
- zlog_info(
- "%s: enabling bgp deterministic-med, this is required"
- " for addpath-tx-bestpath-per-AS",
- peer->host);
- bgp_flag_set(
- bgp,
- BGP_FLAG_DETERMINISTIC_MED);
- bgp_recalculate_all_bestpaths(bgp);
- }
- }
- } else {
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode,
- member)) {
- if (CHECK_FLAG(member->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_ALL_PATHS)
- || CHECK_FLAG(
- member->af_flags[afi][safi],
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
- addpath_tx_used = 1;
- break;
- }
- }
- }
-
- bgp->addpath_tx_used[afi][safi] = addpath_tx_used;
- }
-
return 0;
}
@@ -7059,15 +7062,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
/* addpath TX knobs */
- if (peergroup_af_flag_check(peer, afi, safi,
- PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
- vty_out(vty, " neighbor %s addpath-tx-all-paths\n", addr);
- }
-
- if (peergroup_af_flag_check(peer, afi, safi,
- PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
- vty_out(vty, " neighbor %s addpath-tx-bestpath-per-AS\n",
- addr);
+ if (peergroup_af_addpath_check(peer, afi, safi)) {
+ switch (peer->addpath_type[afi][safi]) {
+ case BGP_ADDPATH_ALL:
+ vty_out(vty, " neighbor %s addpath-tx-all-paths\n",
+ addr);
+ break;
+ case BGP_ADDPATH_BEST_PER_AS:
+ vty_out(vty,
+ " neighbor %s addpath-tx-bestpath-per-AS\n",
+ addr);
+ break;
+ case BGP_ADDPATH_MAX:
+ case BGP_ADDPATH_NONE:
+ break;
+ }
}
/* ORF capability. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index e14b0f39e0..70193104b4 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -39,6 +39,7 @@
#include "bitfield.h"
#include "vxlan.h"
#include "bgp_labelpool.h"
+#include "bgp_addpath_types.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
#define BGP_PEER_MAX_HASH_SIZE 16384
@@ -130,6 +131,7 @@ struct bgp_master {
#define BGP_OPT_MULTIPLE_INSTANCE (1 << 1)
#define BGP_OPT_CONFIG_CISCO (1 << 2)
#define BGP_OPT_NO_LISTEN (1 << 3)
+#define BGP_OPT_NO_ZEBRA (1 << 4)
uint64_t updgrp_idspace;
uint64_t subgrp_idspace;
@@ -462,8 +464,7 @@ struct bgp {
/* Auto-shutdown new peers */
bool autoshutdown;
- uint32_t addpath_tx_id;
- int addpath_tx_used[AFI_MAX][SAFI_MAX];
+ struct bgp_addpath_bgp_data tx_addpath;
#if ENABLE_BGP_VNC
struct rfapi_cfg *rfapi_cfg;
@@ -938,12 +939,12 @@ struct peer {
#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */
#define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */
#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1 << 21) /* remove-private-as all replace-as */
-#define PEER_FLAG_ADDPATH_TX_ALL_PATHS (1 << 22) /* addpath-tx-all-paths */
-#define PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS (1 << 23) /* addpath-tx-bestpath-per-AS */
#define PEER_FLAG_WEIGHT (1 << 24) /* weight */
#define PEER_FLAG_ALLOWAS_IN_ORIGIN (1 << 25) /* allowas-in origin */
#define PEER_FLAG_SEND_LARGE_COMMUNITY (1 << 26) /* Send large Communities */
+ enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
+
/* MD5 password */
char *password;
@@ -1466,6 +1467,14 @@ typedef enum {
BGP_POLICY_DISTRIBUTE_LIST,
} bgp_policy_type_e;
+/* peer_flag_change_type. */
+enum peer_change_type {
+ peer_change_none,
+ peer_change_reset,
+ peer_change_reset_in,
+ peer_change_reset_out,
+};
+
extern struct bgp_master *bm;
extern unsigned int multipath_num;
@@ -1597,6 +1606,8 @@ extern int peer_af_flag_unset(struct peer *, afi_t, safi_t, uint32_t);
extern int peer_af_flag_check(struct peer *, afi_t, safi_t, uint32_t);
extern void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
uint32_t flag);
+extern void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
+ enum peer_change_type type);
extern int peer_ebgp_multihop_set(struct peer *, int);
extern int peer_ebgp_multihop_unset(struct peer *);
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index 97d520eda7..a43cf1f6a9 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -913,7 +913,7 @@ extern struct zebra_privs_t bgpd_privs;
void vnc_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient_vnc = zclient_new_notify(master, &zclient_options_default);
+ zclient_vnc = zclient_new(master, &zclient_options_default);
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index 83f55939ce..a13f058f74 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -46,6 +46,7 @@ man8 += $(MANBUILD)/bgpd.8
endif
bgpd_libbgp_a_SOURCES = \
+ bgpd/bgp_addpath.c \
bgpd/bgp_advertise.c \
bgpd/bgp_aspath.c \
bgpd/bgp_attr.c \
@@ -115,6 +116,8 @@ bgpd_libbgp_a_SOURCES += \
endif
noinst_HEADERS += \
+ bgpd/bgp_addpath.h \
+ bgpd/bgp_addpath_types.h \
bgpd/bgp_advertise.h \
bgpd/bgp_aspath.h \
bgpd/bgp_attr.h \
diff --git a/configure.ac b/configure.ac
index 3a6e7883fb..13f6fdab72 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1,22 +1,22 @@
##
## Configure template file for FRRouting.
-## autoconf will generate configure script.
+## autoconf will generate a configure script.
##
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
##
-AC_PREREQ(2.60)
+AC_PREREQ([2.60])
-AC_INIT(frr, 6.1-dev, [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [6.1-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
-AC_SUBST(PACKAGE_URL)
+AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
-AC_SUBST(PACKAGE_FULLNAME)
+AC_SUBST([PACKAGE_FULLNAME])
CONFIG_ARGS="$ac_configure_args"
-AC_SUBST(CONFIG_ARGS)
+AC_SUBST([CONFIG_ARGS])
-AC_CONFIG_SRCDIR(lib/zebra.h)
+AC_CONFIG_SRCDIR([lib/zebra.h])
AC_CONFIG_MACRO_DIR([m4])
dnl -----------------------------------
@@ -52,7 +52,7 @@ AS_IF([test "$host" != "$build"], [
build_clippy="true"
HOSTTOOLS=""
])
-AC_SUBST(HOSTTOOLS)
+AC_SUBST([HOSTTOOLS])
AM_CONDITIONAL([BUILD_CLIPPY], [$build_clippy])
# Disable portability warnings -- our automake code (in particular
@@ -60,9 +60,9 @@ AM_CONDITIONAL([BUILD_CLIPPY], [$build_clippy])
AM_INIT_AUTOMAKE([1.12 -Wno-portability foreign])
m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])
AM_SILENT_RULES([yes])
-AC_CONFIG_HEADERS(config.h)
+AC_CONFIG_HEADERS([config.h])
-AC_PATH_PROG(PERL, perl)
+AC_PATH_PROG([PERL], [perl])
PKG_PROG_PKG_CONFIG
dnl default is to match previous behavior
@@ -72,7 +72,7 @@ AC_ARG_ENABLE([exampledir],
[specify alternate directory for examples]),
exampledir="$enableval",)
dnl XXX add --exampledir to autoconf standard directory list somehow
-AC_SUBST(exampledir)
+AC_SUBST([exampledir])
dnl default is to match previous behavior
pkgsrcrcdir=""
@@ -81,7 +81,7 @@ AC_ARG_ENABLE([pkgsrcrcdir],
[specify directory for rc.d scripts]),
pkgsrcrcdir="$enableval",)
dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
-AC_SUBST(pkgsrcrcdir)
+AC_SUBST([pkgsrcrcdir])
AM_CONDITIONAL([PKGSRC], [test "x$pkgsrcrcdir" != "x"])
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
@@ -97,14 +97,14 @@ AC_ARG_WITH([yangmodelsdir], [AS_HELP_STRING([--with-yangmodelsdir=DIR], [yang m
], [
yangmodelsdir="\${datarootdir}/yang"
])
-AC_SUBST(yangmodelsdir)
+AC_SUBST([yangmodelsdir])
AC_ARG_WITH([libyang_pluginsdir], [AS_HELP_STRING([--with-libyang-pluginsdir=DIR], [yangmodule plugins directory (${libdir}/frr/libyang_plugins)])], [
libyang_pluginsdir="$withval"
], [
libyang_pluginsdir="\${libdir}/frr/libyang_plugins"
])
-AC_SUBST(libyang_pluginsdir)
+AC_SUBST([libyang_pluginsdir])
AC_ARG_ENABLE(tcmalloc,
AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]),
@@ -113,7 +113,7 @@ AC_ARG_ENABLE(tcmalloc,
LIBS="$LIBS -ltcmalloc_minimal"
;;
no) tcmalloc_enabled=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-tcmalloc) ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-tcmalloc]) ;;
esac],[tcmalloc_enabled=false])
@@ -149,7 +149,7 @@ AC_USE_SYSTEM_EXTENSIONS
AC_DEFUN([AC_C_FLAG], [{
m4_pushdef([cachename],[m4_translit([frr_cv_$1],[ =-],[___])])
AC_CACHE_CHECK([[whether $CC supports $1]], cachename, [
- AC_LANG_PUSH(C)
+ AC_LANG_PUSH([C])
ac_c_flag_save="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_COMPILE_IFELSE(
@@ -160,7 +160,7 @@ AC_DEFUN([AC_C_FLAG], [{
cachename=no
])
CFLAGS="$ac_c_flag_save"
- AC_LANG_POP(C)
+ AC_LANG_POP([C])
])
if test "${cachename}" = yes; then
m4_if([$3], [], [CFLAGS="$CFLAGS $1"], [$3])
@@ -172,7 +172,7 @@ AC_DEFUN([AC_C_FLAG], [{
}])
AC_DEFUN([AC_LINK_IFELSE_FLAGS], [{
- AC_LANG_PUSH(C)
+ AC_LANG_PUSH([C])
ac_cflags_save="$CFLAGS"
ac_libs_save="$LIBS"
CFLAGS="$CFLAGS $1"
@@ -190,7 +190,7 @@ AC_DEFUN([AC_LINK_IFELSE_FLAGS], [{
LIBS="$ac_libs_save"
$4
])
- AC_LANG_POP(C)
+ AC_LANG_POP([C])
}])
dnl ICC won't bail on unknown options without -diag-error 10006
@@ -213,7 +213,7 @@ if test "x${enable_gcov}" = "xyes"; then
LDFLAGS="${LDFLAGS} -lgcov"
elif test "x${enable_dev_build}" = "xyes"; then
- AC_DEFINE(DEV_BUILD,,Build for development)
+ AC_DEFINE([DEV_BUILD], [1], [Build for development])
if test "z$orig_cflags" = "z"; then
AC_C_FLAG([-g3])
AC_C_FLAG([-O0])
@@ -221,7 +221,7 @@ elif test "x${enable_dev_build}" = "xyes"; then
if test "x${enable_lua}" = "xyes"; then
AC_CHECK_LIB([lua], [lua_newstate],
[LIBS="$LIBS -llua"])
- AC_DEFINE(HAVE_LUA,,Lua enabled for development)
+ AC_DEFINE([HAVE_LUA], [1], [Lua enabled for development])
fi
else
if test "x${enable_lua}" = "xyes"; then
@@ -269,7 +269,7 @@ AC_C_FLAG([-diag-disable 3179])
if test x"${enable_werror}" = x"yes" ; then
WERROR="-Werror"
fi
-AC_SUBST(WERROR)
+AC_SUBST([WERROR])
SAN_FLAGS=""
if test "$enable_address_sanitizer" = "yes"; then
@@ -311,7 +311,7 @@ AC_SEARCH_LIBS([pthread_condattr_setclock], [],
[frr_cv_pthread_condattr_setclock=yes],
[frr_cv_pthread_condattr_setclock=no])
if test "$frr_cv_pthread_condattr_setclock" = yes; then
- AC_DEFINE(HAVE_PTHREAD_CONDATTR_SETCLOCK, 1, [Have pthread.h pthread_condattr_setclock])
+ AC_DEFINE([HAVE_PTHREAD_CONDATTR_SETCLOCK], [1], [Have pthread.h pthread_condattr_setclock])
fi
dnl --------------
@@ -320,12 +320,12 @@ dnl --------------
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
-AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL([AR], [ar])
dnl -------
dnl libtool
dnl -------
-AC_ARG_ENABLE(static-bin,
+AC_ARG_ENABLE([static-bin],
AS_HELP_STRING([--enable-static-bin], [link binaries statically]))
LT_INIT
_LT_CONFIG_LIBTOOL([
@@ -335,7 +335,7 @@ _LT_CONFIG_LIBTOOL([
if test "$enable_static_bin" = "yes"; then
AC_LDFLAGS="-static"
fi
-AC_SUBST(AC_LDFLAGS)
+AC_SUBST([AC_LDFLAGS])
AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"])
dnl $AR and $RANLIB are set by LT_INIT above
@@ -350,8 +350,8 @@ else
ARFLAGS="cru"
AR_FLAGS="cru"
fi
-AC_SUBST(ARFLAGS)
-AC_SUBST(AR_FLAGS)
+AC_SUBST([ARFLAGS])
+AC_SUBST([AR_FLAGS])
AC_MSG_CHECKING([whether $RANLIB supports D option])
if $RANLIB -D conftest.a; then
@@ -360,7 +360,7 @@ if $RANLIB -D conftest.a; then
else
AC_MSG_RESULT([no])
fi
-AC_SUBST(RANLIB)
+AC_SUBST([RANLIB])
test -f conftest.a && rm conftest.a
@@ -372,7 +372,7 @@ if test -f config.version; then
elif test -f "${srcdir}/config.version"; then
. "${srcdir}/config.version"
fi
-AC_ARG_WITH(pkg-extra-version,
+AC_ARG_WITH([pkg-extra-version],
AS_HELP_STRING([--with-pkg-extra-version=VER], [add extra version field, for packagers/distributions]), [
if test "$withval" = "no"; then
EXTRAVERSION=
@@ -380,126 +380,126 @@ AC_ARG_WITH(pkg-extra-version,
EXTRAVERSION=$withval
fi
], [])
-AC_ARG_WITH(pkg-git-version,
+AC_ARG_WITH([pkg-git-version],
AS_HELP_STRING([--with-pkg-git-version], [add git information to MOTD and build version string]),
[ test "x$withval" != "xno" && with_pkg_git_version="yes" ])
-AC_ARG_WITH(vtysh_pager,
+AC_ARG_WITH([vtysh_pager],
AS_HELP_STRING([--with-vtysh-pager=PAGER], [control what pager is compiled in as default]),
VTYSH_PAGER=$withval, VTYSH_PAGER="more")
-AC_ARG_ENABLE(vtysh,
+AC_ARG_ENABLE([vtysh],
AS_HELP_STRING([--disable-vtysh], [do not build integrated vty shell for FRR]))
-AC_ARG_ENABLE(doc,
+AC_ARG_ENABLE([doc],
AS_HELP_STRING([--disable-doc], [do not build docs]))
-AC_ARG_ENABLE(doc-html,
+AC_ARG_ENABLE([doc-html],
AS_HELP_STRING([--enable-doc-html], [build HTML docs]))
-AC_ARG_ENABLE(zebra,
+AC_ARG_ENABLE([zebra],
AS_HELP_STRING([--disable-zebra], [do not build zebra daemon]))
-AC_ARG_ENABLE(bgpd,
+AC_ARG_ENABLE([bgpd],
AS_HELP_STRING([--disable-bgpd], [do not build bgpd]))
-AC_ARG_ENABLE(ripd,
+AC_ARG_ENABLE([ripd],
AS_HELP_STRING([--disable-ripd], [do not build ripd]))
-AC_ARG_ENABLE(ripngd,
+AC_ARG_ENABLE([ripngd],
AS_HELP_STRING([--disable-ripngd], [do not build ripngd]))
-AC_ARG_ENABLE(ospfd,
+AC_ARG_ENABLE([ospfd],
AS_HELP_STRING([--disable-ospfd], [do not build ospfd]))
-AC_ARG_ENABLE(ospf6d,
+AC_ARG_ENABLE([ospf6d],
AS_HELP_STRING([--disable-ospf6d], [do not build ospf6d]))
-AC_ARG_ENABLE(ldpd,
+AC_ARG_ENABLE([ldpd],
AS_HELP_STRING([--disable-ldpd], [do not build ldpd]))
-AC_ARG_ENABLE(nhrpd,
+AC_ARG_ENABLE([nhrpd],
AS_HELP_STRING([--disable-nhrpd], [do not build nhrpd]))
-AC_ARG_ENABLE(eigrpd,
+AC_ARG_ENABLE([eigrpd],
AS_HELP_STRING([--disable-eigrpd], [do not build eigrpd]))
-AC_ARG_ENABLE(babeld,
+AC_ARG_ENABLE([babeld],
AS_HELP_STRING([--disable-babeld], [do not build babeld]))
-AC_ARG_ENABLE(watchfrr,
+AC_ARG_ENABLE([watchfrr],
AS_HELP_STRING([--disable-watchfrr], [do not build watchfrr]))
-AC_ARG_ENABLE(isisd,
+AC_ARG_ENABLE([isisd],
AS_HELP_STRING([--disable-isisd], [do not build isisd]))
-AC_ARG_ENABLE(pimd,
+AC_ARG_ENABLE([pimd],
AS_HELP_STRING([--disable-pimd], [do not build pimd]))
-AC_ARG_ENABLE(pbrd,
+AC_ARG_ENABLE([pbrd],
AS_HELP_STRING([--disable-pbrd], [do not build pbrd]))
-AC_ARG_ENABLE(sharpd,
+AC_ARG_ENABLE([sharpd],
AS_HELP_STRING([--enable-sharpd], [build sharpd]))
-AC_ARG_ENABLE(staticd,
+AC_ARG_ENABLE([staticd],
AS_HELP_STRING([--disable-staticd], [do not build staticd]))
-AC_ARG_ENABLE(fabricd,
+AC_ARG_ENABLE([fabricd],
AS_HELP_STRING([--disable-fabricd], [do not build fabricd]))
-AC_ARG_ENABLE(bgp-announce,
+AC_ARG_ENABLE([bgp-announce],
AS_HELP_STRING([--disable-bgp-announce,], [turn off BGP route announcement]))
-AC_ARG_ENABLE(bgp-vnc,
+AC_ARG_ENABLE([bgp-vnc],
AS_HELP_STRING([--disable-bgp-vnc],[turn off BGP VNC support]))
-AC_ARG_ENABLE(snmp,
+AC_ARG_ENABLE([snmp],
AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
-AC_ARG_ENABLE(config_rollbacks,
+AC_ARG_ENABLE([config_rollbacks],
AS_HELP_STRING([--enable-config-rollbacks], [enable configuration rollbacks (requires sqlite3)]))
-AC_ARG_ENABLE(confd,
+AC_ARG_ENABLE([confd],
AS_HELP_STRING([--enable-confd=ARG], [enable confd integration]))
-AC_ARG_ENABLE(sysrepo,
+AC_ARG_ENABLE([sysrepo],
AS_HELP_STRING([--enable-sysrepo], [enable sysrepo integration]))
-AC_ARG_ENABLE(zeromq,
+AC_ARG_ENABLE([zeromq],
AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
-AC_ARG_WITH(libpam,
+AC_ARG_WITH([libpam],
AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh]))
-AC_ARG_ENABLE(ospfapi,
+AC_ARG_ENABLE([ospfapi],
AS_HELP_STRING([--disable-ospfapi], [do not build OSPFAPI to access the OSPF LSA Database]))
-AC_ARG_ENABLE(ospfclient,
+AC_ARG_ENABLE([ospfclient],
AS_HELP_STRING([--disable-ospfclient], [do not build OSPFAPI client for OSPFAPI,
(this is the default if --disable-ospfapi is set)]))
-AC_ARG_ENABLE(multipath,
+AC_ARG_ENABLE([multipath],
AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit]))
-AC_ARG_ENABLE(user,
+AC_ARG_ENABLE([user],
AS_HELP_STRING([--enable-user=USER], [user to run FRR suite as (default frr)]))
-AC_ARG_ENABLE(group,
+AC_ARG_ENABLE([group],
AS_HELP_STRING([--enable-group=GROUP], [group to run FRR suite as (default frr)]))
-AC_ARG_ENABLE(vty_group,
+AC_ARG_ENABLE([vty_group],
AS_HELP_STRING([--enable-vty-group=ARG], [set vty sockets to have specified group as owner]))
-AC_ARG_ENABLE(configfile_mask,
+AC_ARG_ENABLE([configfile_mask],
AS_HELP_STRING([--enable-configfile-mask=ARG], [set mask for config files]))
-AC_ARG_ENABLE(logfile_mask,
+AC_ARG_ENABLE([logfile_mask],
AS_HELP_STRING([--enable-logfile-mask=ARG], [set mask for log files]))
-AC_ARG_ENABLE(shell_access,
+AC_ARG_ENABLE([shell_access],
AS_HELP_STRING([--enable-shell-access], [Allow users to access shell/telnet/ssh]))
-AC_ARG_ENABLE(realms,
+AC_ARG_ENABLE([realms],
AS_HELP_STRING([--enable-realms], [enable REALMS support under Linux]))
-AC_ARG_ENABLE(rtadv,
+AC_ARG_ENABLE([rtadv],
AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement feature]))
-AC_ARG_ENABLE(irdp,
+AC_ARG_ENABLE([irdp],
AS_HELP_STRING([--disable-irdp], [enable IRDP server support in zebra (default if supported)]))
-AC_ARG_ENABLE(capabilities,
+AC_ARG_ENABLE([capabilities],
AS_HELP_STRING([--disable-capabilities], [disable using POSIX capabilities]))
-AC_ARG_ENABLE(rusage,
+AC_ARG_ENABLE([rusage],
AS_HELP_STRING([--disable-rusage], [disable using getrusage]))
-AC_ARG_ENABLE(gcc_ultra_verbose,
+AC_ARG_ENABLE([gcc_ultra_verbose],
AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings]))
-AC_ARG_ENABLE(backtrace,
+AC_ARG_ENABLE([backtrace],
AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)]))
-AC_ARG_ENABLE(time-check,
+AC_ARG_ENABLE([time-check],
AS_HELP_STRING([--disable-time-check], [disable slow thread warning messages]))
-AC_ARG_ENABLE(pcreposix,
+AC_ARG_ENABLE([pcreposix],
AS_HELP_STRING([--enable-pcreposix], [enable using PCRE Posix libs for regex functions]))
-AC_ARG_ENABLE(fpm,
+AC_ARG_ENABLE([fpm],
AS_HELP_STRING([--enable-fpm], [enable Forwarding Plane Manager support]))
-AC_ARG_ENABLE(systemd,
+AC_ARG_ENABLE([systemd],
AS_HELP_STRING([--enable-systemd], [enable Systemd support]))
-AC_ARG_ENABLE(werror,
+AC_ARG_ENABLE([werror],
AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for developers only)]))
-AC_ARG_ENABLE(cumulus,
+AC_ARG_ENABLE([cumulus],
AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions]))
-AC_ARG_ENABLE(datacenter,
+AC_ARG_ENABLE([datacenter],
AS_HELP_STRING([--enable-datacenter], [enable Compilation for Data Center Extensions]))
-AC_ARG_ENABLE(fuzzing,
+AC_ARG_ENABLE([fuzzing],
AS_HELP_STRING([--enable-fuzzing], [enable ability to fuzz various parts of FRR]))
-AC_ARG_ENABLE(netlink_fuzzing,
+AC_ARG_ENABLE([netlink_fuzzing],
AS_HELP_STRING([--enable-netlink-fuzzing], [enable ability to fuzz netlink listening socket in zebra]))
-AC_ARG_ENABLE(rr-semantics,
+AC_ARG_ENABLE([rr-semantics],
AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics]))
AC_ARG_ENABLE([protobuf],
AS_HELP_STRING([--enable-protobuf], [Enable experimental protobuf support]))
AC_ARG_ENABLE([oldvpn_commands],
AS_HELP_STRING([--enable-oldvpn-commands], [Keep old vpn commands]))
-AC_ARG_ENABLE(rpki,
+AC_ARG_ENABLE([rpki],
AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
AC_ARG_ENABLE([clippy-only],
AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
@@ -507,7 +507,7 @@ AC_ARG_ENABLE([numeric_version],
AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)]))
AC_ARG_ENABLE([gcov],
AS_HELP_STRING([--enable-gcov], [Add code coverage information]))
-AC_ARG_ENABLE(bfdd,
+AC_ARG_ENABLE([bfdd],
AS_HELP_STRING([--disable-bfdd], [do not build bfdd]))
AC_ARG_ENABLE([address-sanitizer],
AS_HELP_STRING([--enable-address-sanitizer], [enable AddressSanitizer support for detecting a wide variety of memory allocation and deallocation errors]))
@@ -517,10 +517,10 @@ AC_ARG_ENABLE([memory-sanitizer],
AS_HELP_STRING([--enable-memory-sanitizer], [enable MemorySanitizer support for detecting uninitialized memory reads]))
AS_IF([test "${enable_clippy_only}" != "yes"], [
-AC_CHECK_HEADERS(json-c/json.h)
-AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm])
+AC_CHECK_HEADERS([json-c/json.h])
+AC_CHECK_LIB([json-c], [json_object_get], [LIBS="$LIBS -ljson-c"], [], [-lm])
if test "$ac_cv_lib_json_c_json_object_get" = no; then
- AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson")
+ AC_CHECK_LIB([json], [json_object_get], [LIBS="$LIBS -ljson"])
if test "$ac_cv_lib_json_json_object_get" = no; then
AC_MSG_ERROR([libjson is needed to compile])
fi
@@ -535,53 +535,53 @@ AC_ARG_ENABLE([lua],
if test x"${enable_time_check}" != x"no" ; then
if test x"${enable_time_check}" = x"yes" -o x"${enable_time_check}" = x ; then
- AC_DEFINE(CONSUMED_TIME_CHECK,5000000,Consumed Time Check)
+ AC_DEFINE([CONSUMED_TIME_CHECK], [5000000], [Consumed Time Check])
else
- AC_DEFINE_UNQUOTED(CONSUMED_TIME_CHECK,$enable_time_check,Consumed Time Check)
+ AC_DEFINE_UNQUOTED([CONSUMED_TIME_CHECK], [$enable_time_check], [Consumed Time Check])
fi
fi
case "${enable_systemd}" in
"no") ;;
"yes")
- AC_CHECK_LIB(systemd, sd_notify, LIBS="$LIBS -lsystemd")
+ AC_CHECK_LIB([systemd], [sd_notify], [LIBS="$LIBS -lsystemd"])
if test $ac_cv_lib_systemd_sd_notify = no; then
AC_MSG_ERROR([enable systemd has been specified but systemd development env not found on your system])
else
- AC_DEFINE(HAVE_SYSTEMD,,Compile systemd support in)
+ AC_DEFINE([HAVE_SYSTEMD], [1], [Compile systemd support in])
fi
;;
"*") ;;
esac
if test "${enable_rr_semantics}" != "no" ; then
- AC_DEFINE(HAVE_V6_RR_SEMANTICS,, Compile in v6 Route Replacement Semantics)
+ AC_DEFINE([HAVE_V6_RR_SEMANTICS], [1], [Compile in v6 Route Replacement Semantics])
fi
if test "${enable_datacenter}" = "yes" ; then
- AC_DEFINE(HAVE_DATACENTER,,Compile extensions for a DataCenter)
+ AC_DEFINE([HAVE_DATACENTER], [1], [Compile extensions for a DataCenter])
DFLT_NAME="datacenter"
else
DFLT_NAME="traditional"
fi
if test "${enable_fuzzing}" = "yes" ; then
- AC_DEFINE(HANDLE_ZAPI_FUZZING,,Compile extensions to use with a fuzzer)
+ AC_DEFINE([HANDLE_ZAPI_FUZZING], [1], [Compile extensions to use with a fuzzer])
fi
if test "${enable_netlink_fuzzing}" = "yes" ; then
- AC_DEFINE(HANDLE_NETLINK_FUZZING,,Compile extensions to use with a fuzzer for netlink)
+ AC_DEFINE([HANDLE_NETLINK_FUZZING], [1], [Compile extensions to use with a fuzzer for netlink])
fi
if test "${enable_cumulus}" = "yes" ; then
- AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in)
+ AC_DEFINE([HAVE_CUMULUS], [1], [Compile Special Cumulus Code in])
fi
-AC_SUBST(DFLT_NAME)
-AC_DEFINE_UNQUOTED(DFLT_NAME,["$DFLT_NAME"], Name of the configuration default set)
+AC_SUBST([DFLT_NAME])
+AC_DEFINE_UNQUOTED([DFLT_NAME], ["$DFLT_NAME"], [Name of the configuration default set])
if test "${enable_shell_access}" = "yes"; then
- AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash)
+ AC_DEFINE([HAVE_SHELL_ACCESS], [1], [Allow user to use ssh/telnet/bash])
fi
AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"])
@@ -659,12 +659,12 @@ AS_IF([test "$host" = "$build"], [
fi
if test -z "$PYTHONCONFIG"; then
- PKG_CHECK_MODULES([PYTHON], python-3.6, [], [
- PKG_CHECK_MODULES([PYTHON], python-3.5, [], [
- PKG_CHECK_MODULES([PYTHON], python-3.4, [], [
- PKG_CHECK_MODULES([PYTHON], python-3.3, [], [
- PKG_CHECK_MODULES([PYTHON], python-3.2, [], [
- PKG_CHECK_MODULES([PYTHON], python-2.7, [], [
+ PKG_CHECK_MODULES([PYTHON], [python-3.6], [], [
+ PKG_CHECK_MODULES([PYTHON], [python-3.5], [], [
+ PKG_CHECK_MODULES([PYTHON], [python-3.4], [], [
+ PKG_CHECK_MODULES([PYTHON], [python-3.3], [], [
+ PKG_CHECK_MODULES([PYTHON], [python-3.2], [], [
+ PKG_CHECK_MODULES([PYTHON], [python-2.7], [], [
AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar])
])])])])])])
@@ -674,8 +674,8 @@ AS_IF([test "$host" = "$build"], [
])
fi
])
-AC_SUBST(PYTHON_CFLAGS)
-AC_SUBST(PYTHON_LIBS)
+AC_SUBST([PYTHON_CFLAGS])
+AC_SUBST([PYTHON_LIBS])
#
# Logic for protobuf support.
@@ -698,27 +698,27 @@ if test "$enable_protobuf" = "yes"; then
AC_MSG_FAILURE([protobuf requested but protobuf-c.h not found. Install protobuf-c.])
])
- AC_DEFINE(HAVE_PROTOBUF,, protobuf)
+ AC_DEFINE([HAVE_PROTOBUF], [1], [protobuf])
fi
AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$enable_protobuf" = "xyes"])
#
-# Logic for old vpn commans support.
+# Logic for old vpn commands support.
#
if test "$enable_oldvpn_commands" = "yes"; then
- AC_DEFINE(KEEP_OLD_VPN_COMMANDS,, [Define for compiling with old vpn commands])
+ AC_DEFINE([KEEP_OLD_VPN_COMMANDS], [1], [Define for compiling with old vpn commands])
fi
#
# End of logic for protobuf support.
#
-AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements)
+AC_MSG_CHECKING([if zebra should be configurable to send Route Advertisements])
if test "${enable_rtadv}" != "no"; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_RTADV,,Enable IPv6 Routing Advertisement support)
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_RTADV], [1], [Enable IPv6 Routing Advertisement support])
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
fi
if test x"${enable_user}" = x"no"; then
@@ -727,7 +727,7 @@ else
if test x"${enable_user}" = x"yes" || test x"${enable_user}" = x""; then
enable_user="frr"
fi
- AC_DEFINE_UNQUOTED(FRR_USER, "${enable_user}", frr User)
+ AC_DEFINE_UNQUOTED([FRR_USER], ["${enable_user}"], [frr User])
fi
if test x"${enable_group}" = x"no"; then
@@ -736,14 +736,14 @@ else
if test x"${enable_group}" = x"yes" || test x"${enable_group}" = x""; then
enable_group="frr"
fi
- AC_DEFINE_UNQUOTED(FRR_GROUP, "${enable_group}", frr Group)
+ AC_DEFINE_UNQUOTED([FRR_GROUP], ["${enable_group}"], [frr Group])
fi
if test x"${enable_vty_group}" = x"yes" ; then
AC_MSG_ERROR([--enable-vty-group requires a group as argument, not yes])
elif test x"${enable_vty_group}" != x""; then
if test x"${enable_vty_group}" != x"no"; then
- AC_DEFINE_UNQUOTED(VTY_GROUP, "${enable_vty_group}", VTY Sockets Group)
+ AC_DEFINE_UNQUOTED([VTY_GROUP], ["${enable_vty_group}"], [VTY Sockets Group])
fi
fi
AC_SUBST([enable_user])
@@ -751,10 +751,10 @@ AC_SUBST([enable_group])
AC_SUBST([enable_vty_group])
enable_configfile_mask=${enable_configfile_mask:-0600}
-AC_DEFINE_UNQUOTED(CONFIGFILE_MASK, ${enable_configfile_mask}, Mask for config files)
+AC_DEFINE_UNQUOTED([CONFIGFILE_MASK], [${enable_configfile_mask}], [Mask for config files])
enable_logfile_mask=${enable_logfile_mask:-0600}
-AC_DEFINE_UNQUOTED(LOGFILE_MASK, ${enable_logfile_mask}, Mask for log files)
+AC_DEFINE_UNQUOTED([LOGFILE_MASK], [${enable_logfile_mask}], [Mask for log files])
MPATH_NUM=1
@@ -772,14 +772,14 @@ case "${enable_multipath}" in
;;
esac
-AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a route)
+AC_DEFINE_UNQUOTED([MULTIPATH_NUM], [$MPATH_NUM], [Maximum number of paths for a route])
-AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use])
+AC_DEFINE_UNQUOTED([VTYSH_PAGER], ["$VTYSH_PAGER"], [What pager to use])
dnl --------------------
dnl Enable code coverage
dnl --------------------
-AM_CONDITIONAL([HAVE_GCOV],[test '!' "$enable_gcov" = no])
+AM_CONDITIONAL([HAVE_GCOV], [test '!' "$enable_gcov" = no])
dnl ------------------------------------
dnl Alpine only accepts numeric versions
@@ -799,11 +799,11 @@ if test "x${EXTRAVERSION}" != "x" ; then
AC_SUBST(PACKAGE_EXTRAVERSION, ["${EXTRAVERSION}"])
PACKAGE_STRING="${PACKAGE_STRING}${EXTRAVERSION}"
fi
-AC_SUBST(EXTRAVERSION)
+AC_SUBST([EXTRAVERSION])
if test "x$with_pkg_git_version" = "xyes"; then
if test -d "${srcdir}/.git"; then
- AC_DEFINE(GIT_VERSION, [1], [include git version info])
+ AC_DEFINE([GIT_VERSION], [1], [include git version info])
else with_pkg_git_version="no"
AC_MSG_WARN([--with-pkg-git-version given, but this is not a git checkout])
fi
@@ -821,7 +821,7 @@ AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [
])
])
if test -n "$frr_cv_interp"; then
- AC_DEFINE_UNQUOTED(INTERP, ["$frr_cv_interp"], [.interp value])
+ AC_DEFINE_UNQUOTED([INTERP], ["$frr_cv_interp"], [.interp value])
fi
dnl ------------------------------------
@@ -845,7 +845,7 @@ AC_CHECK_HEADERS([stropts.h sys/ksym.h \
sys/cdefs.h])
ac_stdatomic_ok=false
-AC_DEFINE(FRR_AUTOCONF_ATOMIC, 1, [did autoconf checks for atomic funcs])
+AC_DEFINE([FRR_AUTOCONF_ATOMIC], [1], [did autoconf checks for atomic funcs])
AC_CHECK_HEADER([stdatomic.h],[
AC_MSG_CHECKING([whether _Atomic qualifier works])
@@ -856,7 +856,7 @@ int main(int argc, char **argv) {
return i;
}
]])], [
- AC_DEFINE(HAVE_STDATOMIC_H, 1, [found stdatomic.h])
+ AC_DEFINE([HAVE_STDATOMIC_H], [1], [found stdatomic.h])
AC_MSG_RESULT([yes])
ac_stdatomic_ok=true
], [
@@ -873,7 +873,7 @@ int main(int argc, char **argv) {
return __atomic_load_n (&i, __ATOMIC_ACQUIRE);
}
]])], [
- AC_DEFINE(HAVE___ATOMIC, 1, [found __atomic builtins])
+ AC_DEFINE([HAVE___ATOMIC], [1], [found __atomic builtins])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
@@ -887,7 +887,7 @@ int main(int argc, char **argv) {
return __sync_val_compare_and_swap (&i, 0, 1);
}
]])], [
- AC_DEFINE(HAVE___SYNC, 1, [found __sync builtins])
+ AC_DEFINE([HAVE___SYNC], [1], [found __sync builtins])
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for __sync_swap builtin])
@@ -897,7 +897,7 @@ int main(int argc, char **argv) {
return __sync_swap (&i, 2);
}
]])], [
- AC_DEFINE(HAVE___SYNC_SWAP, 1, [found __sync_swap builtin])
+ AC_DEFINE([HAVE___SYNC_SWAP], 1, [found __sync_swap builtin])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
@@ -943,7 +943,7 @@ dnl Same applies for HAVE_NET_IF_VAR_H, which HAVE_NETINET6_ND6_H and
dnl HAVE_NETINET_IN_VAR_H depend upon. But if_var.h depends on if.h, hence
dnl an additional round for it.
-AC_CHECK_HEADERS([net/if_var.h], [], [], FRR_INCLUDES)
+AC_CHECK_HEADERS([net/if_var.h], [], [], [FRR_INCLUDES])
m4_define([FRR_INCLUDES],
FRR_INCLUDES
@@ -956,7 +956,7 @@ AC_CHECK_HEADERS([netinet/in_var.h \
net/if_dl.h net/netopt.h \
inet/nd.h netinet/ip_icmp.h \
sys/sysctl.h sys/sockio.h kvm.h sys/conf.h],
- [], [], FRR_INCLUDES)
+ [], [], [FRR_INCLUDES])
AC_CHECK_HEADERS([ucontext.h], [], [],
[#ifndef __USE_GNU
@@ -1009,35 +1009,35 @@ case "$host_os" in
sunos* | solaris2*)
AC_MSG_RESULT([Solaris])
- AC_DEFINE(SUNOS_5, 1, [SunOS 5])
- AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6)
- AC_DEFINE(_POSIX_C_SOURCE, 200809L, [enable POSIX.1-2008 and XPG7/SUSv4])
+ AC_DEFINE([SUNOS_5], [1], [SunOS 5])
+ AC_DEFINE([SOLARIS_IPV6], [1], Solaris IPv6)
+ AC_DEFINE([_POSIX_C_SOURCE], [200809L], [enable POSIX.1-2008 and XPG7/SUSv4])
- AC_CHECK_LIB(socket, main)
- AC_CHECK_LIB(nsl, main)
- AC_CHECK_LIB(umem, main)
+ AC_CHECK_LIB([socket], [main])
+ AC_CHECK_LIB([nsl], [main])
+ AC_CHECK_LIB([umem], [main])
SOLARIS="solaris"
;;
linux*)
AC_MSG_RESULT([Linux])
- AC_DEFINE(GNU_LINUX,,GNU Linux)
- AC_DEFINE(HAVE_NETLINK,,netlink)
- AC_DEFINE(LINUX_IPV6,1,Linux IPv6 stack)
+ AC_DEFINE([GNU_LINUX], [1], [GNU Linux])
+ AC_DEFINE([HAVE_NETLINK], [1], [netlink])
+ AC_DEFINE([LINUX_IPV6], [1], [Linux IPv6 stack])
dnl Linux has a compilation problem with mixing
dnl netinet/in.h and linux/in6.h they are not
dnl compatible. There has been discussion on
dnl how to fix it but no real progress on implementation
dnl when they fix it, remove this
- AC_DEFINE(IPV6_MINHOPCOUNT, 73, Linux ipv6 Min Hop Count)
+ AC_DEFINE([IPV6_MINHOPCOUNT], [73], [Linux ipv6 Min Hop Count])
;;
openbsd*)
AC_MSG_RESULT([OpenBSD])
- AC_DEFINE(OPEN_BSD,,OpenBSD)
- AC_DEFINE(KAME,1,KAME IPv6)
- AC_DEFINE(BSD_V6_SYSCTL,1,BSD v6 sysctl to turn on and off forwarding)
+ AC_DEFINE([OPEN_BSD], [1], [OpenBSD])
+ AC_DEFINE([KAME], [1], [KAME IPv6])
+ AC_DEFINE([BSD_V6_SYSCTL], [1], [BSD v6 sysctl to turn on and off forwarding])
if test "x${enable_pimd}" != "xno"; then
case "$host_os" in
@@ -1052,12 +1052,12 @@ case "$host_os" in
*)
AC_MSG_RESULT([BSD])
- AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
- AC_DEFINE(KAME,1,KAME IPv6)
- AC_DEFINE(BSD_V6_SYSCTL,1,BSD v6 sysctl to turn on and off forwarding)
+ AC_DEFINE([HAVE_NET_RT_IFLIST], [1], [NET_RT_IFLIST])
+ AC_DEFINE([KAME], [1], [KAME IPv6])
+ AC_DEFINE([BSD_V6_SYSCTL], [1], [BSD v6 sysctl to turn on and off forwarding])
;;
esac
-AM_CONDITIONAL(SOLARIS, test "${SOLARIS}" = "solaris")
+AM_CONDITIONAL([SOLARIS], [test "${SOLARIS}" = "solaris"])
AC_SYS_LARGEFILE
@@ -1067,7 +1067,7 @@ dnl ------------------------
if test "${enable_realms}" = "yes"; then
case "$host_os" in
linux*)
- AC_DEFINE(SUPPORT_REALMS,, Realms support)
+ AC_DEFINE([SUPPORT_REALMS], [1], [Realms support])
;;
*)
echo "Sorry, only Linux has REALMS support"
@@ -1085,15 +1085,15 @@ case "${enable_vtysh}" in
VTYSH="";;
*)
VTYSH="vtysh";
- AC_DEFINE(VTYSH,,VTY shell)
+ AC_DEFINE([VTYSH], [1], [VTY shell])
prev_libs="$LIBS"
- AC_CHECK_LIB(readline, main, [
+ AC_CHECK_LIB([readline], [main], [
LIBREADLINE="-lreadline"
], [
dnl readline failed - it might be incorrectly linked and missing its
dnl termcap/tinfo/curses dependency. see if we can fix that...
- AC_SEARCH_LIBS(tputs, [termcap tinfo curses ncurses], [
+ AC_SEARCH_LIBS([tputs], [termcap tinfo curses ncurses], [
LIBREADLINE="$ac_cv_search_tputs"
], [
AC_MSG_ERROR([libreadline (needed for vtysh) not found and/or missing dependencies])
@@ -1101,7 +1101,7 @@ case "${enable_vtysh}" in
dnl re-try with the lib we found above
unset ac_cv_lib_readline_main
- AC_CHECK_LIB(readline, main, [
+ AC_CHECK_LIB([readline], [main], [
LIBREADLINE="-lreadline $LIBREADLINE"
], [
AC_MSG_ERROR([libreadline (needed for vtysh) not found and/or missing dependencies])
@@ -1109,22 +1109,22 @@ case "${enable_vtysh}" in
], [])
LIBS="$prev_libs"
- AC_CHECK_HEADER(readline/history.h)
+ AC_CHECK_HEADER([readline/history.h])
if test $ac_cv_header_readline_history_h = no;then
AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.])
fi
- AC_CHECK_LIB(readline, rl_completion_matches, [true], [], [$LIBREADLINE])
+ AC_CHECK_LIB([readline], [rl_completion_matches], [true], [], [$LIBREADLINE])
if test $ac_cv_lib_readline_rl_completion_matches = no; then
- AC_DEFINE(rl_completion_matches,completion_matches,Old readline)
+ AC_DEFINE([rl_completion_matches], [completion_matches], [Old readline])
fi
- AC_CHECK_LIB(readline, [append_history], [frr_cv_append_history=yes], [frr_cv_append_history=no], [$LIBREADLINE])
+ AC_CHECK_LIB([readline], [append_history], [frr_cv_append_history=yes], [frr_cv_append_history=no], [$LIBREADLINE])
if test "$frr_cv_append_history" = yes; then
- AC_DEFINE(HAVE_APPEND_HISTORY, 1, [Have history.h append_history])
+ AC_DEFINE([HAVE_APPEND_HISTORY], [1], [Have history.h append_history])
fi
;;
esac
-AC_SUBST(LIBREADLINE)
-AM_CONDITIONAL(VTYSH, test "x$VTYSH" = "xvtysh")
+AC_SUBST([LIBREADLINE])
+AM_CONDITIONAL([VTYSH], test "x$VTYSH" = "xvtysh")
dnl ----------
dnl PAM module
@@ -1138,14 +1138,14 @@ dnl of OpenPAM.
dnl ----------
if test "$with_libpam" = "yes"; then
AC_CHECK_HEADER([security/pam_misc.h],
- [AC_DEFINE(HAVE_PAM_MISC_H,,Have pam_misc.h)
- AC_DEFINE(PAM_CONV_FUNC,misc_conv,Have misc_conv)
+ [AC_DEFINE([HAVE_PAM_MISC_H], [1], [Have pam_misc.h])
+ AC_DEFINE([PAM_CONV_FUNC], [misc_conv], [Have misc_conv])
pam_conv_func="misc_conv"
],
[], FRR_INCLUDES)
AC_CHECK_HEADER([security/openpam.h],
- [AC_DEFINE(HAVE_OPENPAM_H,,Have openpam.h)
- AC_DEFINE(PAM_CONV_FUNC,openpam_ttyconv,Have openpam_ttyconv)
+ [AC_DEFINE([HAVE_OPENPAM_H], [1], [Have openpam.h])
+ AC_DEFINE([PAM_CONV_FUNC], [openpam_ttyconv], [Have openpam_ttyconv])
pam_conv_func="openpam_ttyconv"
],
[], FRR_INCLUDES[#include <security/pam_appl.h>])
@@ -1163,20 +1163,20 @@ dnl This next check looks funky due to a linker problem with some versions
dnl of the PAM library. Prior to 0.72 release, the Linux PAM shared library
dnl omitted requiring libdl linking information. PAM-0.72 or better ships
dnl with RedHat 6.2 and Debian 2.2 or better.
-AC_CHECK_LIB(pam, pam_start,
- [AC_CHECK_LIB(pam, $pam_conv_func,
- [AC_DEFINE(USE_PAM,,Use PAM for authentication)
+AC_CHECK_LIB([pam], [pam_start],
+ [AC_CHECK_LIB([pam], [$pam_conv_func],
+ [AC_DEFINE([USE_PAM], [1], [Use PAM for authentication])
LIBPAM="-lpam"],
- [AC_DEFINE(USE_PAM,,Use PAM for authentication)
+ [AC_DEFINE([USE_PAM], [1], [Use PAM for authentication])
LIBPAM="-lpam -lpam_misc"]
)
],
- [AC_CHECK_LIB(pam, pam_end,
- [AC_CHECK_LIB(pam, $pam_conv_func,
- [AC_DEFINE(USE_PAM,,Use PAM for authentication)
+ [AC_CHECK_LIB([pam], [pam_end],
+ [AC_CHECK_LIB([pam], [$pam_conv_func],
+ [AC_DEFINE([USE_PAM], [1], [Use PAM for authentication])
LIBPAM="-lpam -ldl"],
- [AC_DEFINE(USE_PAM,,Use PAM for authentication)
+ [AC_DEFINE([USE_PAM], [1], [Use PAM for authentication])
LIBPAM="-lpam -ldl -lpam_misc"]
)
],AC_MSG_WARN([*** pam support will not be built ***]),
@@ -1184,7 +1184,7 @@ AC_CHECK_LIB(pam, pam_start,
]
)
fi
-AC_SUBST(LIBPAM)
+AC_SUBST([LIBPAM])
dnl -------------------------------
dnl Endian-ness check
@@ -1223,13 +1223,13 @@ if test x"$LIBM" = x ; then
fi
LIBS="$TMPLIBS"
-AC_SUBST(LIBM)
+AC_SUBST([LIBM])
AC_CHECK_FUNCS([ppoll], [
- AC_DEFINE([HAVE_PPOLL], 1, [have Linux/BSD ppoll()])
+ AC_DEFINE([HAVE_PPOLL], [1], [have Linux/BSD ppoll()])
])
AC_CHECK_FUNCS([pollts], [
- AC_DEFINE([HAVE_POLLTS], 1, [have NetBSD pollts()])
+ AC_DEFINE([HAVE_POLLTS], [1], [have NetBSD pollts()])
])
dnl ---------------
@@ -1241,35 +1241,35 @@ AC_CHECK_FUNCS([ \
AC_CHECK_HEADER([asm-generic/unistd.h],
[AC_CHECK_DECL(__NR_setns,
- AC_DEFINE(HAVE_NETNS,, Have netns),,
+ AC_DEFINE([HAVE_NETNS], [1], [Have netns]),,
FRR_INCLUDES [#include <asm-generic/unistd.h>
])
- AC_CHECK_FUNCS(setns)]
+ AC_CHECK_FUNCS([setns])]
)
dnl --------------------------
dnl Determine IS-IS I/O method
dnl --------------------------
-AC_DEFINE(ISIS_METHOD_PFPACKET, 1, [ constant value for isis method pfpacket ])
-AC_DEFINE(ISIS_METHOD_DLPI, 2, [ constant value for isis method dlpi ])
-AC_DEFINE(ISIS_METHOD_BPF, 3, [ constant value for isis method bpf ])
-AC_CHECK_HEADER(net/bpf.h)
-AC_CHECK_HEADER(sys/dlpi.h)
-AC_MSG_CHECKING(zebra IS-IS I/O method)
+AC_DEFINE([ISIS_METHOD_PFPACKET], [1], [constant value for isis method pfpacket])
+AC_DEFINE([ISIS_METHOD_DLPI], [2], [constant value for isis method dlpi])
+AC_DEFINE([ISIS_METHOD_BPF], [3], [constant value for isis method bpf])
+AC_CHECK_HEADER([net/bpf.h])
+AC_CHECK_HEADER([sys/dlpi.h])
+AC_MSG_CHECKING([zebra IS-IS I/O method])
case "$host_os" in
linux*)
- AC_MSG_RESULT(pfpacket)
+ AC_MSG_RESULT([pfpacket])
ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET"
;;
solaris* | sunos*)
- AC_MSG_RESULT(DLPI)
+ AC_MSG_RESULT([DLPI])
ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
;;
*)
if test $ac_cv_header_net_bpf_h = no; then
if test $ac_cv_header_sys_dlpi_h = no; then
- AC_MSG_RESULT(none)
+ AC_MSG_RESULT([none])
if test "${enable_isisd}" = yes -o "${enable_fabricd}" = yes; then
AC_MSG_FAILURE([IS-IS support requested but no packet backend found])
fi
@@ -1277,16 +1277,16 @@ case "$host_os" in
enable_isisd="no"
enable_fabricd="no"
else
- AC_MSG_RESULT(DLPI)
+ AC_MSG_RESULT([DLPI])
fi
ISIS_METHOD_MACRO="ISIS_METHOD_DLPI"
else
- AC_MSG_RESULT(BPF)
+ AC_MSG_RESULT([BPF])
ISIS_METHOD_MACRO="ISIS_METHOD_BPF"
fi
;;
esac
-AC_DEFINE_UNQUOTED(ISIS_METHOD, $ISIS_METHOD_MACRO, [ selected method for isis, == one of the constants ])
+AC_DEFINE_UNQUOTED([ISIS_METHOD], [$ISIS_METHOD_MACRO], [selected method for isis, == one of the constants])
dnl ---------------------------------------------------------------
dnl figure out how to specify an interface in multicast sockets API
@@ -1327,29 +1327,29 @@ AC_TRY_COMPILE([#include <sys/param.h>],
return (0);
#else
#error No support for BSD struct ip_mreq hack detected
-#endif],[AC_MSG_RESULT(yes)
-AC_DEFINE(HAVE_BSD_STRUCT_IP_MREQ_HACK,,[Can pass ifindex in struct ip_mreq])],
-AC_MSG_RESULT(no))
+#endif],[AC_MSG_RESULT([yes])
+AC_DEFINE([HAVE_BSD_STRUCT_IP_MREQ_HACK], [1], [Can pass ifindex in struct ip_mreq])],
+AC_MSG_RESULT([no]))
AC_MSG_CHECKING([for RFC3678 protocol-independed API])
AC_TRY_COMPILE([
#include <sys/types.h>
#include <netinet/in.h>
], [struct group_req gr; int sock; setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void*)&gr, sizeof(gr));
-], [AC_MSG_RESULT(yes)
-AC_DEFINE(HAVE_RFC3678,1,[Have RFC3678 protocol-independed API])],
-AC_MSG_RESULT(no))
+], [AC_MSG_RESULT([yes])
+AC_DEFINE([HAVE_RFC3678], [1], [Have RFC3678 protocol-independed API])],
+AC_MSG_RESULT([no]))
dnl ---------------------------------------------------------------
dnl figure out how to check link-state
dnl ---------------------------------------------------------------
-AC_CHECK_HEADER( [net/if_media.h],
+AC_CHECK_HEADER([net/if_media.h],
[m4_define([LINK_DETECT_INCLUDES],
FRR_INCLUDES
[#include <net/if_media.h>
])
- AC_CHECK_MEMBERS( [struct ifmediareq.ifm_status],
- AC_DEFINE(HAVE_BSD_LINK_DETECT,,[BSD link-detect]),
+ AC_CHECK_MEMBERS([struct ifmediareq.ifm_status],
+ AC_DEFINE([HAVE_BSD_LINK_DETECT], [1], [BSD link-detect]),
[], LINK_DETECT_INCLUDES)],
[],
FRR_INCLUDES)
@@ -1359,7 +1359,7 @@ dnl Additional, newer way to check link-state using ifi_link_state.
dnl Not available in all BSD's when ifmediareq available
dnl ---------------------------------------------------------------
AC_CHECK_MEMBERS([struct if_data.ifi_link_state],
- AC_DEFINE(HAVE_BSD_IFI_LINK_STATE,,[BSD ifi_link_state available]),
+ AC_DEFINE([HAVE_BSD_IFI_LINK_STATE], [1], [BSD ifi_link_state available]),
[], FRR_INCLUDES)
dnl ------------------------
@@ -1419,48 +1419,48 @@ if test "$SPHINXBUILD" = "/bin/false"; then
AC_MSG_ERROR([Documentation was explicitly requested with --enable-doc but sphinx-build is not available. Please disable docs or install sphinx.])
fi
fi
-AM_CONDITIONAL(DOC, test "${enable_doc}" != "no" -a "$SPHINXBUILD" != "/bin/false")
-AM_CONDITIONAL(DOC_HTML, test "${enable_doc_html}" = "yes")
+AM_CONDITIONAL([DOC], [test "${enable_doc}" != "no" -a "$SPHINXBUILD" != "/bin/false"])
+AM_CONDITIONAL([DOC_HTML], [test "${enable_doc_html}" = "yes"])
dnl --------------------
dnl Daemon disable check
dnl --------------------
-AM_CONDITIONAL(ZEBRA, test "${enable_zebra}" != "no")
+AM_CONDITIONAL([ZEBRA], [test "${enable_zebra}" != "no"])
if test "${enable_bgpd}" = "no";then
BGPD=""
else
BGPD="bgpd"
fi
-AM_CONDITIONAL(BGPD, test "x$BGPD" = "xbgpd")
+AM_CONDITIONAL([BGPD], [test "x$BGPD" = "xbgpd"])
-AM_CONDITIONAL(RIPD, test "${enable_ripd}" != "no")
-AM_CONDITIONAL(OSPFD, test "${enable_ospfd}" != "no")
-AM_CONDITIONAL(LDPD, test "${enable_ldpd}" != "no")
+AM_CONDITIONAL([RIPD], [test "${enable_ripd}" != "no"])
+AM_CONDITIONAL([OSPFD], [test "${enable_ospfd}" != "no"])
+AM_CONDITIONAL([LDPD], [test "${enable_ldpd}" != "no"])
AS_IF([test "${enable_ldpd}" != "no"], [
- AC_DEFINE(HAVE_LDPD, 1, ldpd)
+ AC_DEFINE([HAVE_LDPD], [1], [ldpd])
])
if test "$enable_bfdd" = "no"; then
- AC_DEFINE(HAVE_BFDD, 0, bfdd)
+ AC_DEFINE([HAVE_BFDD], [0], [bfdd])
BFDD=""
else
- AC_DEFINE(HAVE_BFDD, 1, bfdd)
+ AC_DEFINE([HAVE_BFDD], [1], [bfdd])
BFDD="bfdd"
case $host_os in
linux*)
- AC_DEFINE(BFD_LINUX, 1, bfdd)
+ AC_DEFINE([BFD_LINUX], [1], [bfdd])
;;
*)
- AC_DEFINE(BFD_BSD, 1, bfdd)
+ AC_DEFINE([BFD_BSD], [1], [bfdd])
;;
esac
fi
-AM_CONDITIONAL(BFDD, [test "x$BFDD" = "xbfdd"])
+AM_CONDITIONAL([BFDD], [test "x$BFDD" = "xbfdd"])
if test "$ac_cv_lib_json_c_json_object_get" = no -a "x$BFDD" = "xbfdd"; then
AC_MSG_ERROR(["you must use json-c library to use bfdd"])
@@ -1479,68 +1479,68 @@ case "$host_os" in
fi
;;
esac
-AM_CONDITIONAL(NHRPD, test "x$NHRPD" = "xnhrpd")
+AM_CONDITIONAL([NHRPD], [test "x$NHRPD" = "xnhrpd"])
-AM_CONDITIONAL(EIGRPD, test "${enable_eigrpd}" != "no")
+AM_CONDITIONAL([EIGRPD], [test "${enable_eigrpd}" != "no"])
if test "${enable_watchfrr}" = "no";then
WATCHFRR=""
else
WATCHFRR="watchfrr"
fi
-AM_CONDITIONAL(WATCHFRR, test "x$WATCHFRR" = "xwatchfrr")
+AM_CONDITIONAL([WATCHFRR], [test "x$WATCHFRR" = "xwatchfrr"])
OSPFCLIENT=""
if test "${enable_ospfapi}" != "no";then
- AC_DEFINE(SUPPORT_OSPF_API,,OSPFAPI)
+ AC_DEFINE([SUPPORT_OSPF_API], [1], [OSPFAPI])
if test "${enable_ospfclient}" != "no";then
OSPFCLIENT="ospfclient"
fi
fi
-AM_CONDITIONAL(OSPFCLIENT, test "x$OSPFCLIENT" = "xospfclient")
-AM_CONDITIONAL(RIPNGD, test "${enable_ripngd}" != "no")
-AM_CONDITIONAL(BABELD, test "${enable_babeld}" != "no")
-AM_CONDITIONAL(OSPF6D, test "${enable_ospf6d}" != "no")
-AM_CONDITIONAL(ISISD, test "${enable_isisd}" != "no")
-AM_CONDITIONAL(PIMD, test "${enable_pimd}" != "no")
-AM_CONDITIONAL(PBRD, test "${enable_pbrd}" != "no")
-AM_CONDITIONAL(SHARPD, test "${enable_sharpd}" = "yes")
-AM_CONDITIONAL(STATICD, test "${enable_staticd}" != "no")
-AM_CONDITIONAL(FABRICD, test "${enable_fabricd}" != "no")
+AM_CONDITIONAL([OSPFCLIENT], [test "x$OSPFCLIENT" = "xospfclient"])
+AM_CONDITIONAL([RIPNGD], [test "${enable_ripngd}" != "no"])
+AM_CONDITIONAL([BABELD], [test "${enable_babeld}" != "no"])
+AM_CONDITIONAL([OSPF6D], [test "${enable_ospf6d}" != "no"])
+AM_CONDITIONAL([ISISD], [test "${enable_isisd}" != "no"])
+AM_CONDITIONAL([PIMD], [test "${enable_pimd}" != "no"])
+AM_CONDITIONAL([PBRD], [test "${enable_pbrd}" != "no"])
+AM_CONDITIONAL([SHARPD], [test "${enable_sharpd}" = "yes"])
+AM_CONDITIONAL([STATICD], [test "${enable_staticd}" != "no"])
+AM_CONDITIONAL([FABRICD], [test "${enable_fabricd}" != "no"])
if test "${enable_bgp_announce}" = "no";then
- AC_DEFINE(DISABLE_BGP_ANNOUNCE,1,Disable BGP installation to zebra)
+ AC_DEFINE([DISABLE_BGP_ANNOUNCE], [1], [Disable BGP installation to zebra])
else
- AC_DEFINE(DISABLE_BGP_ANNOUNCE,0,Disable BGP installation to zebra)
+ AC_DEFINE([DISABLE_BGP_ANNOUNCE], [0], [Disable BGP installation to zebra])
fi
if test "${enable_bgp_vnc}" != "no";then
- AC_DEFINE(ENABLE_BGP_VNC,1,Enable BGP VNC support)
+ AC_DEFINE([ENABLE_BGP_VNC], [1], [Enable BGP VNC support])
fi
AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno])
-AC_SUBST(SOLARIS)
-AC_CHECK_LIB(crypt, crypt, [],
- [AC_CHECK_LIB(crypto, DES_crypt)])
-AC_CHECK_LIB(resolv, res_init)
+AC_SUBST([SOLARIS])
+AC_CHECK_LIB([crypt], [crypt], [],
+ [AC_CHECK_LIB([crypto], [DES_crypt])])
+AC_CHECK_LIB([resolv], [res_init])
dnl ---------------------------
dnl check system has PCRE regexp
dnl ---------------------------
if test "x$enable_pcreposix" = "xyes"; then
- AC_CHECK_LIB(pcreposix, regexec, [], [
+ AC_CHECK_LIB([pcreposix], [regexec], [], [
AC_MSG_ERROR([--enable-pcreposix given but unable to find libpcreposix])
])
fi
-AC_SUBST(HAVE_LIBPCREPOSIX)
+AC_SUBST([HAVE_LIBPCREPOSIX])
dnl ------------------
dnl check C-Ares library
dnl ------------------
if test "${NHRPD}" != ""; then
- PKG_CHECK_MODULES([CARES], [libcares], , [
+ PKG_CHECK_MODULES([CARES], [libcares], ,[
AC_MSG_ERROR([trying to build nhrpd, but libcares not found. install c-ares and its -dev headers.])
])
fi
@@ -1583,16 +1583,16 @@ int main(void);
;;
esac
AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd])
- AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd)
+ AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,[SNMP method to interface with snmpd])
fi
AM_CONDITIONAL([SNMP], [test "x${SNMP_METHOD}" != "x"])
-AC_SUBST(SNMP_LIBS)
-AC_SUBST(SNMP_CFLAGS)
+AC_SUBST([SNMP_LIBS])
+AC_SUBST([SNMP_CFLAGS])
dnl ---------------
dnl libyang
dnl ---------------
-PKG_CHECK_MODULES(libyang, [libyang >= 0.16.7], , [
+PKG_CHECK_MODULES([libyang], [libyang >= 0.16.7], , [
AC_MSG_ERROR([libyang (>= 0.16.7) was not found on your system.])
])
AC_CHECK_MEMBER([struct lyd_node.priv], [], [
@@ -1607,15 +1607,15 @@ dnl configuration rollbacks
dnl ---------------
SQLITE3=false
if test "$enable_config_rollbacks" = "yes"; then
- PKG_CHECK_MODULES(sqlite3,[sqlite3], [
- AC_DEFINE(HAVE_CONFIG_ROLLBACKS,1,Enable configuration rollbacks)
- AC_DEFINE(HAVE_SQLITE3,1,Enable sqlite3 database)
+ PKG_CHECK_MODULES([sqlite3], [sqlite3], [
+ AC_DEFINE([HAVE_CONFIG_ROLLBACKS], [1], [Enable configuration rollbacks])
+ AC_DEFINE([HAVE_SQLITE3], [1], [Enable sqlite3 database])
SQLITE3=true
], [
AC_MSG_ERROR([--enable-config-rollbacks given but sqlite3 was not found on your system.])
])
fi
-AM_CONDITIONAL(SQLITE3, $SQLITE3)
+AM_CONDITIONAL([SQLITE3], [$SQLITE3])
dnl ---------------
dnl confd
@@ -1626,8 +1626,8 @@ if test "$enable_confd" != "" -a "$enable_confd" != "no"; then
AC_MSG_ERROR([confd was not found on your system.])]
fi
CONFD_CFLAGS="-I${enable_confd}/include -L${enable_confd}/lib"
- AC_SUBST(CONFD_CFLAGS)
- AC_DEFINE(HAVE_CONFD,1,Enable confd integration)
+ AC_SUBST([CONFD_CFLAGS])
+ AC_DEFINE([HAVE_CONFD], [1], [Enable confd integration])
fi
AM_CONDITIONAL([CONFD], [test "x$enable_confd" != "x"])
@@ -1635,8 +1635,8 @@ dnl ---------------
dnl sysrepo
dnl ---------------
if test "$enable_sysrepo" = "yes"; then
- PKG_CHECK_MODULES(sysrepo,[libsysrepo],
- [AC_DEFINE(HAVE_SYSREPO,1,Enable sysrepo integration)
+ PKG_CHECK_MODULES([sysrepo], [libsysrepo],
+ [AC_DEFINE([HAVE_SYSREPO], [1], [Enable sysrepo integration])
SYSREPO=true],
[SYSREPO=false
AC_MSG_ERROR([sysrepo was not found on your system.])]
@@ -1652,7 +1652,7 @@ AC_SEARCH_LIBS([sqrt], [m])
dnl ---------------
dnl dlopen & dlinfo
dnl ---------------
-AC_SEARCH_LIBS(dlopen, [dl dld], [], [
+AC_SEARCH_LIBS([dlopen], [dl dld], [], [
AC_MSG_ERROR([unable to find the dlopen()])
])
@@ -1675,7 +1675,7 @@ AC_CACHE_CHECK([for dlinfo(RTLD_DI_ORIGIN)], [frr_cv_rtld_di_origin], [
])
])
if test "$frr_cv_rtld_di_origin" = yes; then
- AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN])
+ AC_DEFINE([HAVE_DLINFO_ORIGIN], [1], [Have dlinfo RTLD_DI_ORIGIN])
fi
AC_CACHE_CHECK([for dlinfo(RTLD_DI_LINKMAP)], [frr_cv_rtld_di_linkmap], [
@@ -1695,10 +1695,10 @@ AC_CACHE_CHECK([for dlinfo(RTLD_DI_LINKMAP)], [frr_cv_rtld_di_linkmap], [
])
])
if test "$frr_cv_rtld_di_linkmap" = yes; then
- AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP])
+ AC_DEFINE([HAVE_DLINFO_LINKMAP], [1], [Have dlinfo RTLD_DI_LINKMAP])
fi
-AM_CONDITIONAL(SNMP, test "x$SNMP_METHOD" = "xagentx")
+AM_CONDITIONAL([SNMP], [test "x$SNMP_METHOD" = "xagentx"])
dnl ---------------------------
dnl sockaddr and netinet checks
@@ -1742,71 +1742,71 @@ no)
;;
esac
-AM_CONDITIONAL(IRDP, $IRDP)
+AM_CONDITIONAL([IRDP], [$IRDP])
dnl -----------------------
dnl checking for IP_PKTINFO
dnl -----------------------
-AC_MSG_CHECKING(for IP_PKTINFO)
+AC_MSG_CHECKING([for IP_PKTINFO])
AC_TRY_COMPILE([#include <netdb.h>], [
int opt = IP_PKTINFO;
], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IP_PKTINFO, 1, [Have IP_PKTINFO])
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_IP_PKTINFO], [1], [Have IP_PKTINFO])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
])
dnl ---------------------------
dnl checking for IP_RECVDSTADDR
dnl ---------------------------
-AC_MSG_CHECKING(for IP_RECVDSTADDR)
+AC_MSG_CHECKING([for IP_RECVDSTADDR])
AC_TRY_COMPILE([#include <netinet/in.h>], [
int opt = IP_RECVDSTADDR;
], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IP_RECVDSTADDR, 1, [Have IP_RECVDSTADDR])
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_IP_RECVDSTADDR], [1], [Have IP_RECVDSTADDR])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
])
dnl ----------------------
dnl checking for IP_RECVIF
dnl ----------------------
-AC_MSG_CHECKING(for IP_RECVIF)
+AC_MSG_CHECKING([for IP_RECVIF])
AC_TRY_COMPILE([#include <netinet/in.h>], [
int opt = IP_RECVIF;
], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IP_RECVIF, 1, [Have IP_RECVIF])
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_IP_RECVIF], [1], [Have IP_RECVIF])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
])
dnl ----------------------
dnl checking for SO_BINDANY
dnl ----------------------
-AC_MSG_CHECKING(for SO_BINDANY)
+AC_MSG_CHECKING([for SO_BINDANY])
AC_TRY_COMPILE([#include <sys/socket.h>], [
int opt = SO_BINDANY;
], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SO_BINDANY, 1, [Have SO_BINDANY])
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_SO_BINDANY], [1], [Have SO_BINDANY])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
])
dnl ----------------------
dnl checking for IP_FREEBIND
dnl ----------------------
-AC_MSG_CHECKING(for IP_FREEBIND)
+AC_MSG_CHECKING([for IP_FREEBIND])
AC_TRY_COMPILE([#include <netinet/in.h>], [
int opt = IP_FREEBIND;
], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IP_FREEBIND, 1, [Have IP_FREEBIND])
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_IP_FREEBIND], [1], [Have IP_FREEBIND])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
])
dnl --------------------------------------
@@ -1818,17 +1818,17 @@ AC_CHECK_DECLS([be32enc, be32dec], [], [],
dnl --------------------------------------
dnl checking for clock_time monotonic struct and call
dnl --------------------------------------
-AC_CHECK_DECL(CLOCK_MONOTONIC,
- [AC_CHECK_LIB(rt, clock_gettime, [LIBS="$LIBS -lrt"])
- AC_DEFINE(HAVE_CLOCK_MONOTONIC,, Have monotonic clock)
-], [AC_MSG_RESULT(no)], [FRR_INCLUDES])
+AC_CHECK_DECL([CLOCK_MONOTONIC],
+ [AC_CHECK_LIB([rt], [clock_gettime], [LIBS="$LIBS -lrt"])
+ AC_DEFINE([HAVE_CLOCK_MONOTONIC], [1], [Have monotonic clock])
+], [AC_MSG_RESULT([no])], [FRR_INCLUDES])
dnl --------------------------------------
dnl checking for flex and bison
dnl --------------------------------------
AM_PROG_LEX
-AC_MSG_CHECKING(version of flex)
+AC_MSG_CHECKING([version of flex])
frr_ac_flex_version="$(eval $LEX -V | grep flex | head -n 1)"
frr_ac_flex_version="${frr_ac_flex_version##* }"
AC_MSG_RESULT([$frr_ac_flex_version])
@@ -1845,7 +1845,7 @@ AX_COMPARE_VERSION([$frr_ac_flex_version], [lt], [2.5.20], [
AC_PROG_YACC
dnl thanks GNU bison for this b*llshit...
-AC_MSG_CHECKING(version of bison)
+AC_MSG_CHECKING([version of bison])
frr_ac_bison_version="$(eval $YACC -V | grep bison | head -n 1)"
frr_ac_bison_version="${frr_ac_bison_version##* }"
frr_ac_bison_missing="false"
@@ -1873,9 +1873,9 @@ case "x${frr_ac_bison_version}" in
AC_MSG_RESULT([$frr_ac_bison_version - 3.0 or newer])
;;
esac
-AC_SUBST(BISON_OPENBRACE)
-AC_SUBST(BISON_CLOSEBRACE)
-AC_SUBST(BISON_VERBOSE)
+AC_SUBST([BISON_OPENBRACE])
+AC_SUBST([BISON_CLOSEBRACE])
+AC_SUBST([BISON_VERBOSE])
if $frr_ac_bison_missing; then
YACC="$SHELL $missing_dir/missing bison -y"
@@ -1890,28 +1890,28 @@ dnl -------------------
dnl capabilities checks
dnl -------------------
if test "${enable_capabilities}" != "no"; then
- AC_MSG_CHECKING(whether prctl PR_SET_KEEPCAPS is available)
- AC_TRY_COMPILE([#include <sys/prctl.h>],[prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);],
- [AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_PR_SET_KEEPCAPS,,prctl)
+ AC_MSG_CHECKING([whether prctl PR_SET_KEEPCAPS is available])
+ AC_TRY_COMPILE([#include <sys/prctl.h>], [prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);],
+ [AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_PR_SET_KEEPCAPS], [1], [prctl])
frr_ac_keepcaps="yes"],
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
)
if test x"${frr_ac_keepcaps}" = x"yes"; then
- AC_CHECK_HEADERS(sys/capability.h)
+ AC_CHECK_HEADERS([sys/capability.h])
fi
if test x"${ac_cv_header_sys_capability_h}" = x"yes"; then
- AC_CHECK_LIB(cap, cap_init,
- [AC_DEFINE(HAVE_LCAPS,1,Capabilities)
+ AC_CHECK_LIB([cap], [cap_init],
+ [AC_DEFINE([HAVE_LCAPS], [1], [Capabilities])
LIBCAP="-lcap"
frr_ac_lcaps="yes"]
)
else
- AC_CHECK_HEADERS(priv.h,
- [AC_MSG_CHECKING(Solaris style privileges are available)
- AC_TRY_COMPILE([#include <priv.h>],[getpflags(PRIV_AWARE);],
- [AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SOLARIS_CAPABILITIES,1,getpflags)
+ AC_CHECK_HEADERS([priv.h],
+ [AC_MSG_CHECKING([Solaris style privileges are available])
+ AC_TRY_COMPILE([#include <priv.h>], [getpflags(PRIV_AWARE);],
+ [AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_SOLARIS_CAPABILITIES], [1], [getpflags])
frr_ac_scaps="yes"],
AC_MSG_RESULT(no)
)
@@ -1920,10 +1920,10 @@ if test "${enable_capabilities}" != "no"; then
fi
if test x"${frr_ac_scaps}" = x"yes" \
-o x"${frr_ac_lcaps}" = x"yes"; then
- AC_DEFINE(HAVE_CAPABILITIES,1,capabilities)
+ AC_DEFINE([HAVE_CAPABILITIES], [1], [capabilities])
fi
fi
-AC_SUBST(LIBCAP)
+AC_SUBST([LIBCAP])
dnl ---------------------------
dnl check for glibc 'backtrace'
@@ -1931,13 +1931,13 @@ dnl ---------------------------
if test x"${enable_backtrace}" != x"no" ; then
backtrace_ok=no
PKG_CHECK_MODULES([UNWIND], [libunwind], [
- AC_DEFINE(HAVE_LIBUNWIND, 1, [libunwind])
+ AC_DEFINE([HAVE_LIBUNWIND], [1], [libunwind])
backtrace_ok=yes
], [
case "$host_os" in
sunos* | solaris2*)
AC_CHECK_FUNCS([printstack], [
- AC_DEFINE([HAVE_PRINTSTACK], 1, [Solaris printstack])
+ AC_DEFINE([HAVE_PRINTSTACK], [1], [Solaris printstack])
backtrace_ok=yes
])
;;
@@ -1945,7 +1945,7 @@ if test x"${enable_backtrace}" != x"no" ; then
if test "$backtrace_ok" = no; then
AC_CHECK_HEADER([execinfo.h], [
AC_SEARCH_LIBS([backtrace], [execinfo], [
- AC_DEFINE(HAVE_GLIBC_BACKTRACE, 1, [Glibc backtrace])
+ AC_DEFINE([HAVE_GLIBC_BACKTRACE], [1], [Glibc backtrace])
backtrace_ok=yes
],, [-lm])
])
@@ -1987,10 +1987,10 @@ struct mallinfo ac_x; ac_x = mallinfo ();
])
])
if test "$frr_cv_mallinfo" = yes; then
- AC_DEFINE(HAVE_MALLINFO,,mallinfo)
+ AC_DEFINE([HAVE_MALLINFO], [1], [mallinfo])
fi
-AC_MSG_CHECKING(whether malloc_usable_size is available)
+AC_MSG_CHECKING([whether malloc_usable_size is available])
AC_LINK_IFELSE([AC_LANG_PROGRAM([FRR_INCLUDES [
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -2001,12 +2001,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([FRR_INCLUDES [
]], [[
size_t ac_x; ac_x = malloc_usable_size(NULL);
]])], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_MALLOC_USABLE_SIZE,,malloc_usable_size)
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_MALLOC_USABLE_SIZE], [1], [malloc_usable_size])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
- AC_MSG_CHECKING(whether malloc_size is available)
+ AC_MSG_CHECKING([whether malloc_size is available])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -2017,10 +2017,10 @@ size_t ac_x; ac_x = malloc_usable_size(NULL);
]], [[
size_t ac_x; ac_x = malloc_size(NULL);
]])], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_MALLOC_SIZE,,malloc_size)
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_MALLOC_SIZE], [1], [malloc_size])
], [
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT([no])
])
])
@@ -2028,8 +2028,8 @@ dnl ------
dnl ZeroMQ
dnl ------
if test "x$enable_zeromq" != "xno"; then
- PKG_CHECK_MODULES(ZEROMQ, [libzmq >= 4.0.0], [
- AC_DEFINE(HAVE_ZEROMQ, 1, [Enable ZeroMQ support])
+ PKG_CHECK_MODULES([ZEROMQ], [libzmq >= 4.0.0], [
+ AC_DEFINE([HAVE_ZEROMQ], [1], [Enable ZeroMQ support])
ZEROMQ=true
], [
if test "x$enable_zeromq" = "xyes"; then
@@ -2037,7 +2037,7 @@ if test "x$enable_zeromq" != "xno"; then
fi
])
fi
-AM_CONDITIONAL([ZEROMQ], test "x$ZEROMQ" = "xtrue")
+AM_CONDITIONAL([ZEROMQ], [test "x$ZEROMQ" = "xtrue"])
dnl ----------
dnl configure date
@@ -2049,12 +2049,12 @@ if test "${dev_version}" = ""; then
else
CONFDATE=`date '+%Y%m%d'`
fi
-AC_SUBST(CONFDATE)
+AC_SUBST([CONFDATE])
dnl ------------------------------
dnl set paths for state directory
dnl ------------------------------
-AC_MSG_CHECKING(directory to use for state file)
+AC_MSG_CHECKING([directory to use for state file])
if test "${prefix}" = "NONE"; then
frr_statedir_prefix="";
else
@@ -2076,16 +2076,16 @@ else
frr_statedir=${localstatedir}
fi
if test $frr_statedir = "/dev/null"; then
- AC_MSG_ERROR('STATE DIRECTORY NOT FOUND! FIX OR SPECIFY --localstatedir!')
+ AC_MSG_ERROR([STATE DIRECTORY NOT FOUND! FIX OR SPECIFY --localstatedir!])
fi
-AC_MSG_RESULT(${frr_statedir})
-AC_SUBST(frr_statedir)
+AC_MSG_RESULT([${frr_statedir}])
+AC_SUBST([frr_statedir])
-AC_DEFINE_UNQUOTED(LDPD_SOCKET, "$frr_statedir/ldpd.sock",ldpd control socket)
-AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$frr_statedir/zserv.api",zebra api socket)
-AC_DEFINE_UNQUOTED(BFDD_CONTROL_SOCKET, "$frr_statedir/bfdd.sock", bfdd control socket)
-AC_DEFINE_UNQUOTED(DAEMON_VTY_DIR, "$frr_statedir",daemon vty directory)
-AC_DEFINE_UNQUOTED(DAEMON_DB_DIR, "$frr_statedir",daemon database directory)
+AC_DEFINE_UNQUOTED([LDPD_SOCKET], ["$frr_statedir/ldpd.sock"], [ldpd control socket])
+AC_DEFINE_UNQUOTED([ZEBRA_SERV_PATH], ["$frr_statedir/zserv.api"], [zebra api socket])
+AC_DEFINE_UNQUOTED([BFDD_CONTROL_SOCKET], ["$frr_statedir/bfdd.sock"], [bfdd control socket])
+AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir"], [daemon vty directory])
+AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])
dnl autoconf does this, but it does it too late...
test "x$prefix" = xNONE && prefix=$ac_default_prefix
@@ -2096,8 +2096,8 @@ vtysh_bin="$bindir/vtysh"
for I in 1 2 3 4 5 6 7 8 9 10; do
eval vtysh_bin="\"$vtysh_bin\""
done
-AC_DEFINE_UNQUOTED(VTYSH_BIN_PATH, "$vtysh_bin",path to vtysh binary)
-AC_SUBST(vtysh_bin)
+AC_DEFINE_UNQUOTED([VTYSH_BIN_PATH], ["$vtysh_bin"], [path to vtysh binary])
+AC_SUBST([vtysh_bin])
CFG_SYSCONF="$sysconfdir"
CFG_SBIN="$sbindir"
@@ -2113,27 +2113,27 @@ for I in 1 2 3 4 5 6 7 8 9 10; do
eval CFG_YANGMODELS="\"$CFG_YANGMODELS\""
eval CFG_LIBYANG_PLUGINS="\"$CFG_LIBYANG_PLUGINS\""
done
-AC_SUBST(CFG_SYSCONF)
-AC_SUBST(CFG_SBIN)
-AC_SUBST(CFG_STATE)
-AC_SUBST(CFG_MODULE)
-AC_SUBST(CFG_YANGMODELS)
-AC_SUBST(CFG_LIBYANG_PLUGINS)
-AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules)
-AC_DEFINE_UNQUOTED(YANG_MODELS_PATH, "$CFG_YANGMODELS", path to YANG data models)
-AC_DEFINE_UNQUOTED(LIBYANG_PLUGINS_PATH, "$CFG_LIBYANG_PLUGINS", path to libyang plugins)
+AC_SUBST([CFG_SYSCONF])
+AC_SUBST([CFG_SBIN])
+AC_SUBST([CFG_STATE])
+AC_SUBST([CFG_MODULE])
+AC_SUBST([CFG_YANGMODELS])
+AC_SUBST([CFG_LIBYANG_PLUGINS])
+AC_DEFINE_UNQUOTED([MODULE_PATH], ["$CFG_MODULE"], [path to modules])
+AC_DEFINE_UNQUOTED([YANG_MODELS_PATH], ["$CFG_YANGMODELS"], [path to YANG data models])
+AC_DEFINE_UNQUOTED([LIBYANG_PLUGINS_PATH], ["$CFG_LIBYANG_PLUGINS"], [path to libyang plugins])
dnl ------------------------------------
dnl Enable RPKI and add librtr to libs
dnl ------------------------------------
if test "${enable_rpki}" = "yes"; then
- PKG_CHECK_MODULES(RTRLIB,[rtrlib >= 0.5.0],
+ PKG_CHECK_MODULES([RTRLIB], [rtrlib >= 0.5.0],
[RPKI=true],
[RPKI=false
AC_MSG_ERROR([rtrlib was not found on your system or is too old.])]
)
fi
-AM_CONDITIONAL([RPKI], test "x$RPKI" = "xtrue")
+AM_CONDITIONAL([RPKI], [test "x$RPKI" = "xtrue"])
dnl ------------------------------------------
dnl Check whether rtrlib was build with ssh support
@@ -2141,21 +2141,21 @@ dnl ------------------------------------------
AC_MSG_CHECKING([whether the RTR Library is compiled with SSH])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "rtrlib/rtrlib.h"]],
[[struct tr_ssh_config config;]])],
- [AC_MSG_RESULT(yes)
- AC_DEFINE(FOUND_SSH,,found_ssh)],
- AC_MSG_RESULT(no)
+ [AC_MSG_RESULT([yes])
+ AC_DEFINE([FOUND_SSH], [1], [found_ssh])],
+ AC_MSG_RESULT([no])
)
dnl ---------------------------
dnl Check htonl works correctly
dnl ---------------------------
-AC_MSG_CHECKING(for working htonl)
+AC_MSG_CHECKING([for working htonl])
AC_CACHE_VAL(ac_cv_htonl_works,
[AC_LINK_IFELSE([AC_LANG_PROGRAM([FRR_INCLUDES],[htonl (0);])],
[ac_cv_htonl_works=yes], [ac_cv_htonl_works=no])
]
)
-AC_MSG_RESULT($ac_cv_htonl_works)
+AC_MSG_RESULT([$ac_cv_htonl_works])
AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile])
@@ -2172,8 +2172,8 @@ AC_CONFIG_FILES([
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
pkgsrc/eigrpd.sh])
-AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl])
-AC_CONFIG_FILES([tools/frr],[chmod +x tools/frr])
+AC_CONFIG_FILES([vtysh/extract.pl], [chmod +x vtysh/extract.pl])
+AC_CONFIG_FILES([tools/frr], [chmod +x tools/frr])
AC_CONFIG_COMMANDS([lib/route_types.h], [
dst="${ac_abs_top_builddir}/lib/route_types.h"
@@ -2233,5 +2233,5 @@ directory and to the config files in the config file directory."
if test "${enable_doc}" != "no";then
AS_IF([test "$SPHINXBUILD" = /bin/false],
- AC_MSG_WARN(sphinx-build is missing but required to build documentation))
+ AC_MSG_WARN([sphinx-build is missing but required to build documentation]))
fi
diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst
index 5f9ce705f2..c57573cb9f 100644
--- a/doc/developer/building-frr-for-centos6.rst
+++ b/doc/developer/building-frr-for-centos6.rst
@@ -244,7 +244,7 @@ Load the modifed sysctl's on the system:
Add init.d startup files
^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block::
+.. code-block:: shell
sudo install -p -m 755 redhat/frr.init /etc/init.d/frr
sudo chkconfig --add frr
@@ -252,13 +252,13 @@ Add init.d startup files
Enable FRR daemon at startup
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block::
+.. code-block:: shell
sudo chkconfig frr on
Start FRR manually (or reboot)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block::
+.. code-block:: shell
sudo /etc/init.d/frr start
diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst
index 2d1edc063d..e69ded8f73 100644
--- a/doc/developer/building-frr-for-ubuntu1804.rst
+++ b/doc/developer/building-frr-for-ubuntu1804.rst
@@ -115,7 +115,7 @@ Create empty FRR configuration files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Although not strictly necessary, it's good practice to create empty
-configuration files _before_ starting FRR. This assures that the permissions
+configuration files _before_ starting FRR. This assures that the permissions
are correct. If the files are not already present, FRR will create them.
It's also important to consider _which_ files to create. FRR supports writing
diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst
index 9757ad454e..005b6ba786 100644
--- a/doc/developer/building-libyang.rst
+++ b/doc/developer/building-libyang.rst
@@ -40,23 +40,3 @@ When building libyang on CentOS 6, it's also necessary to pass the
Note: please check the `libyang build requirements
<https://github.com/CESNET/libyang/blob/master/README.md#build-requirements>`_
first.
-
-Libyang uses loadable libraries an YANG modules. It supports
-environment variables to allow overriding the load paths for each of
-these. With FRR, this override currently must be done at the time of
-running FRR's configure command using new options. The new options are:
-
-.. code-block:: shell
-
- --with-yangmodelsdir=DIR
- yang models directory (${datarootdir}/yang)
- --with-libyang-pluginsdir=DIR
- yangmodule plugins directory
- (${libdir}/frr/libyang_plugins)
-
-an example which uses the compile directory is:
-
-.. code-block:: shell
-
- ./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \
- --with-yangmodelsdir="`pwd`/yang"
diff --git a/doc/developer/conf.py b/doc/developer/conf.py
index 61253c4b2f..254c9f6bfc 100644
--- a/doc/developer/conf.py
+++ b/doc/developer/conf.py
@@ -131,7 +131,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ['_build', 'building-libyang.rst']
# The reST default role (used for this markup: `text`) to use for all
# documents.
diff --git a/doc/developer/index.rst b/doc/developer/index.rst
index 42192db637..9838e1098c 100644
--- a/doc/developer/index.rst
+++ b/doc/developer/index.rst
@@ -12,3 +12,4 @@ FRRouting Developer's Guide
bgpd
ospf
zebra
+ vtysh
diff --git a/doc/developer/maintainer-release-build.rst b/doc/developer/maintainer-release-build.rst
index 907bd14ee6..85aaa5365a 100644
--- a/doc/developer/maintainer-release-build.rst
+++ b/doc/developer/maintainer-release-build.rst
@@ -1,5 +1,5 @@
-Release Build Procedure for FRR maintainers
-=========================================================
+Release Build Procedure for FRR Maintainers
+===========================================
1. Rename branch (if needed)
diff --git a/doc/developer/modules.rst b/doc/developer/modules.rst
index bde7682e4e..99c79462ab 100644
--- a/doc/developer/modules.rst
+++ b/doc/developer/modules.rst
@@ -103,9 +103,9 @@ standard entry point for loadable modules.
Command line parameters
-----------------------
-Command line parameters can be passed directly to a module by appending a
-colon to the module name when loading it, e.g. ``-M mymodule:myparameter``.
-The text after the colon will be accessible in the module's code through
+Command line parameters can be passed directly to a module by appending a
+colon to the module name when loading it, e.g. ``-M mymodule:myparameter``.
+The text after the colon will be accessible in the module's code through
``THIS_MODULE->load_args``. For example, see how the format parameter is
configured in the ``zfpm_init()`` function inside ``zebra_fpm.c``.
diff --git a/doc/developer/next-hop-tracking.rst b/doc/developer/next-hop-tracking.rst
index e6484102a8..a9af5e749c 100644
--- a/doc/developer/next-hop-tracking.rst
+++ b/doc/developer/next-hop-tracking.rst
@@ -269,7 +269,7 @@ RNH table::
O O
/ \
O O
-
+
struct rnh
{
uint8_t flags;
diff --git a/doc/developer/packaging-debian.rst b/doc/developer/packaging-debian.rst
index 4ea784c0fc..c812a38212 100644
--- a/doc/developer/packaging-debian.rst
+++ b/doc/developer/packaging-debian.rst
@@ -1,5 +1,5 @@
-Debian
-======
+Packaging Debian
+================
(Tested on Ubuntu 12.04, 14.04, 16.04, 17.10, 18.04, Debian 8 and 9)
diff --git a/doc/developer/packaging.rst b/doc/developer/packaging.rst
index e9bb3a5409..27e6e155fb 100644
--- a/doc/developer/packaging.rst
+++ b/doc/developer/packaging.rst
@@ -5,4 +5,5 @@ Packaging
.. toctree::
:maxdepth: 2
+ maintainer-release-build
packaging-debian
diff --git a/doc/developer/process-architecture.rst b/doc/developer/process-architecture.rst
index 806afa644c..6e0eb68188 100644
--- a/doc/developer/process-architecture.rst
+++ b/doc/developer/process-architecture.rst
@@ -118,7 +118,7 @@ The following diagram illustrates a simplified version of this infrastructure.
.. todo: replace these with SVG
.. figure:: ../figures/threadmaster-single.png
:align: center
-
+
Lifecycle of a program using a single threadmaster.
The series of "task" boxes represents the current ready task queue. The various
@@ -183,7 +183,7 @@ running their own ``threadmaster``-based event loop.
.. todo: replace these with SVG
.. figure:: ../figures/threadmaster-multiple.png
:align: center
-
+
Lifecycle of a program using multiple pthreads, each running their own
``threadmaster``
diff --git a/doc/developer/vtysh.rst b/doc/developer/vtysh.rst
new file mode 100644
index 0000000000..4a52eb0544
--- /dev/null
+++ b/doc/developer/vtysh.rst
@@ -0,0 +1,201 @@
+.. _vtysh:
+
+*****
+VTYSH
+*****
+
+.. seealso:: :ref:`command-line-interface`
+
+.. _vtysh-architecture:
+
+Architecture
+============
+
+VTYSH is a shell for FRR daemons. It amalgamates all the CLI commands defined
+in each of the daemons and presents them to the user in a single shell, which
+saves the user from having to telnet to each of the daemons and use their
+individual shells. The amalgamation is achieved by
+:ref:`extracting <vtysh-command-extraction>` commands from daemons and
+injecting them into VTYSH at build time.
+
+At runtime, VTYSH maintains an instance of a CLI mode tree just like each
+daemon. However, the mode tree in VTYSH contains (almost) all commands from
+every daemon in the same tree, whereas individual daemons have trees that only
+contain commands relevant to themselves. VTYSH also uses the library CLI
+facilities to maintain the user's current position in the tree (the current
+node). Note that this position must be synchronized with all daemons; if a
+daemon receives a command that causes it to change its current node, VTYSH must
+also change its node. Since the extraction script does not understand the
+handler code of commands, but only their definitions, this and other behaviors
+must be manually programmed into VTYSH for every case where the internal state
+of VTYSH must change in response to a command. Details on how this is done are
+discussed in the :ref:`vtysh-special-defuns` section.
+
+VTYSH also handles writing and applying the integrated configuration file,
+:file:`/etc/frr/frr.conf`. Since it has knowledge of the entire command space
+of FRR, it can intelligently distribute configuration commands only to the
+daemons that understand them. Similarly, when writing the configuration file it
+takes care of combining multiple instances of configuration blocks and
+simplifying the output. This is discussed in :ref:`vtysh-configuration`.
+
+.. _vtysh-command-extraction:
+
+Command Extraction
+------------------
+
+When VTYSH is a built, a Perl script named :file:`extract.pl` searches the FRR
+codebase looking for ``DEFUN``'s. It extracts these ``DEFUN``'s, transforms
+them into ``DEFSH``'s and appends them to ``vtysh_cmd.c``. Each ``DEFSH``
+contains the name of the command plus ``_vtysh``, as well as a flag that
+indicates which daemons the command was found in. When the command is executed
+in VTYSH, this flag is inspected to determine which daemons to send the command
+to. This way, commands are only sent to the daemons that know about them,
+avoiding spurious errors from daemons that don't have the command defined.
+
+The extraction script contains lots of hardcoded knowledge about what sources
+to look at and what flags to use for certain commands.
+
+.. _vtysh-special-defuns:
+
+Special DEFUNs
+--------------
+
+In addition to the vanilla ``DEFUN`` macro for defining CLI commands, there are
+several VTYSH-specific ``DEFUN`` variants that each serve different purposes.
+
+``DEFSH``
+ Used almost exclusively by generated VTYSH code. This macro defines a
+ ``cmd_element`` with no handler function; the command, when executed, is
+ simply forwarded to the daemons indicated in the daemon flag.
+
+``DEFUN_NOSH``
+ Used by daemons. Has the same expansion as a ``DEFUN``, but ``extract.pl``
+ will skip these definitions when extracting commands. This is typically used
+ when VTYSH must take some special action upon receiving the command, and the
+ programmer therefore needs to write VTYSH's copy of the command manually
+ instead of using the generated version.
+
+``DEFUNSH``
+ The same as ``DEFUN``, but with an argument that allows specifying the
+ ``->daemon`` field of the generated ``cmd_element``. This is used by VTYSH
+ to determine which daemons to send the command to.
+
+``DEFUNSH_ATTR``
+ A version of ``DEFUNSH`` that allows setting the ``->attr`` field of the
+ generated ``cmd_element``. Not used in practice.
+
+.. _vtysh-configuration:
+
+Configuration Management
+------------------------
+
+When integrated configuration is used, VTYSH manages writing, reading and
+applying the FRR configuration file. VTYSH can be made to read and apply an
+integrated configuration to all running daemons by launching it with ``-f
+<file>``. It sends the appropriate configuration lines to the relevant daemons
+in the same way that commands entered by the user on VTYSH's shell prompt are
+processed.
+
+Configuration writing is more complicated. VTYSH makes a best-effort attempt to
+combine and simplify the configuration as much as possible. A working example
+is best to explain this behavior.
+
+Example
+^^^^^^^
+
+Suppose we have just *staticd* and *zebra* running on the system, and use VTYSH
+to apply the following configuration snippet:
+
+.. code-block:: frr
+
+ !
+ vrf blue
+ ip protocol static route-map ExampleRoutemap
+ ip route 192.168.0.0/24 192.168.0.1
+ exit-vrf
+ !
+
+Note that *staticd* defines static route commands and *zebra* defines ``ip
+protocol`` commands. Therefore if we ask only *zebra* for its configuration, we
+get the following::
+
+ (config)# do sh running-config zebra
+ Building configuration...
+
+ ...
+ !
+ vrf blue
+ ip protocol static route-map ExampleRoutemap
+ exit-vrf
+ !
+ ...
+
+Note that the static route doesn't show up there. Similarly, if we ask
+*staticd* for its configuration, we get::
+
+ (config)# do sh running-config staticd
+
+ ...
+ !
+ vrf blue
+ ip route 192.168.0.0/24 192.168.0.1
+ exit-vrf
+ !
+ ...
+
+But when we display the configuration with VTYSH, we see::
+
+ ubuntu-bionic(config)# do sh running-config
+
+ ...
+ !
+ vrf blue
+ ip protocol static route-map ExampleRoutemap
+ ip route 192.168.0.0/24 192.168.0.1
+ exit-vrf
+ !
+ ...
+
+This is because VTYSH asks each daemon for its currently running configuration,
+and combines equivalent blocks together. In the above example, it combined the
+``vrf blue`` blocks from both *zebra* and *staticd* together into one. This is
+done in :file:`vtysh_config.c`.
+
+Protocol
+========
+
+VTYSH communicates with FRR daemons by way of domain socket. Each daemon
+creates its own socket, typically in :file:`/var/run/frr/<daemon>.vty`. The
+protocol is very simple. In the VTYSH to daemon direction, messages are simply
+NULL-terminated strings, whose content are CLI commands. Here is a typical
+message from VTYSH to a daemon:
+
+::
+
+ Request
+
+ 00000000: 646f 2077 7269 7465 2074 6572 6d69 6e61 do write termina
+ 00000010: 6c0a 00 l..
+
+
+The response format has some more data in it. First is a NULL-terminated string
+containing the plaintext response, which is just the output of the command that
+was sent in the request. This is displayed to the user. The plaintext response
+is followed by 3 null marker bytes, followed by a 1-byte status code that
+indicates whether the command was successful or not.
+
+::
+
+ Response
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Plaintext Response |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Marker (0x00) | Status Code |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+The first ``0x00`` byte in the marker also serves to terminate the plaintext
+response.
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index ee7592fd6a..543dfdd3b9 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -91,17 +91,63 @@ documentation and packaging systems will be updated to reflect the next
possible release name to allow for easy distinguishing.
After one month the development branch will be renamed to
-``stable/MAJOR.MINOR``. This process is not held up unless a crash or security
-issue has been found and needs to be addressed. Issues being fixed will not
-cause a delay.
+``stable/MAJOR.MINOR``. The branch is a stable branch. This process is not
+held up unless a crash or security issue has been found and needs to
+be addressed. Issues being fixed will not cause a delay.
Bugfix releases are made as needed at 1 month intervals until the next
-``MAJOR.MINOR`` relese branch is pulled. Depending on the severity of the bugs,
+``MAJOR.MINOR`` release branch is pulled. Depending on the severity of the bugs,
bugfix releases may occur sooner.
Bugfixes are applied to the two most recent releases. Security fixes are
-backported to all releases less than or equal to one year old. Security fixes
-may also be backported to older releases depending on severity.
+backported to all releases less than or equal to at least one year old. Security
+fixes may also be backported to older releases depending on severity.
+
+Long term support branches ( LTS )
+-----------------------------------------
+
+This kind of branch is not yet officially supported, and need experimentation
+before being effective.
+
+Previous definition of releases prevents long term support of previous releases.
+For instance, bug and security fixes are not applied if the stable branch is too
+old.
+
+Because the FRR users have a need to backport bug and security fixes after the
+stable branch becomes too old, there is a need to provide support on a long term
+basis on that stable branch. If that support is applied on that stable branch,
+then that branch is a long term support branch.
+
+Having a LTS branch requires extra-work and requires one person to be in charge
+of that maintenance branch for a certain amount of time. The amount of time will
+be by default set to 4 months, and can be increased. 4 months stands for the time
+between two releases, this time can be applied to the decision to continue with a
+LTS release or not. In all cases, that time period will be well-defined and
+published. Also, a self nomination from a person that proposes to handle the LTS
+branch is required. The work can be shared by multiple people. In all cases, there
+must be at least one person that is in charge of the maintenance branch. The person
+on people responsible for a maintenance branch must be a FRR maintainer. Note that
+they may choose to abandon support for the maintenance branch at any time. If
+noone takes over the responsibility of the LTS branch, then the support will be
+discontinued.
+
+The LTS branch duties are the following ones:
+
+- organise meetings on a (bi-)weekly or monthly basis, the handling of issues
+ and pull requested relative to that branch. When time permits, this may be done
+ during the regularly scheduled FRR meeting.
+
+- ensure the stability of the branch, by using and eventually adapting the
+ checking the CI tools of FRR ( indeed, maintaining may lead to create
+ maintenance branches for topotests or for CI).
+
+It will not be possible to backport feature requests to LTS branches. Actually, it
+is a false good idea to use LTS for that need. Introducing feature requests may
+break the paradigm where all more recent releases should also include the feature
+request. This would require the LTS maintainer to ensure that all more recent
+releases have support for this feature request. Moreover, introducing features
+requests may result in breaking the stability of the branch. LTS branches are first
+done to bring long term support for stability.
Changelog
---------
diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst
index 1bf31e9624..f771d48235 100644
--- a/doc/developer/zebra.rst
+++ b/doc/developer/zebra.rst
@@ -9,108 +9,335 @@ Zebra
Overview of the Zebra Protocol
==============================
-Zebra Protocol is used by protocol daemons to communicate with the zebra
-daemon.
+The Zebra protocol is used by protocol daemons to communicate with the
+**zebra** daemon.
-Each protocol daemon may request and send information to and from the zebra
+Each protocol daemon may request and send information to and from the **zebra**
daemon such as interface states, routing state, nexthop-validation, and so on.
-Protocol daemons may also install routes with zebra. The zebra daemon manages
-which route is installed into the forwarding table with the kernel.
-
-Zebra Protocol is a streaming protocol, with a common header. Two versions of
-the header are in use. Version 0 is implicitely versioned. Version 1 has an
-explicit version field. Version 0 can be distinguished from all other versions
-by examining the 3rd byte of the header, which contains a marker value for all
-versions bar version 0. The marker byte corresponds to the command field in
-version 0, and the marker value is a reserved command in version 0.
-
-We do not anticipate there will be further versions of the header for the
-foreseeable future, as the command field in version 1 is wide enough to allow
-for future extensions to done compatibly through seperate commands.
-
-Version 0 is used by all versions of GNU Zebra as of this writing, and versions
-of Quagga up to and including Quagga 0.98. Version 2 was created for 0.99.21 of
-Quagga. Version 3 designates VRF compatibility and was released in 1.0.
-Version 4 will be used as of FRR 2.0 to indicate that we are a different
-Routing Suite now and to hopefully prevent accidental Quagga <-> FRR issues.
+Protocol daemons may also install routes with **zebra**. The **zebra** daemon
+manages which routes are installed into the forwarding table with the kernel.
-Zebra Protocol Definition
-=========================
+The Zebra protocol is a streaming protocol, with a common header. Version 0
+lacks a version field and is implicitly versioned. Version 1 and all subsequent
+versions have a version field. Version 0 can be distinguished from all other
+versions by examining the 3rd byte of the header, which contains a marker value
+of 255 (in Quagga) or 254 (in FRR) for all versions except version 0. The
+marker byte corresponds to the command field in version 0, and the marker value
+is a reserved command in version 0.
-Zebra Protocol Header (version 0)
-----------------------------------
+Version History
+---------------
-::
+- Version 0
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-------------------------------+---------------+
- | Length (2) | Command (1) |
- +-------------------------------+---------------+
+ Used by all versions of GNU Zebra and all version of Quagga up to and
+ including Quagga 0.98. This version has no ``version`` field, and so is
+ implicitly versioned as version 0.
+- Version 1
-Zebra Protocol Common Header (version 1)
-----------------------------------------
+ Added ``marker`` and ``version`` fields, increased ``command`` field to 16
+ bits. Used by Quagga versions 0.99.3 through 0.99.20.
-::
+- Version 2
+
+ Used by Quagga versions 0.99.21 through 0.99.23.
+
+- Version 3
+
+ Added ``vrf_id`` field. Used by Quagga versions 0.99.23 until FRR fork.
+
+- Version 4
+
+ Change marker value to 254 to prevent people mixing and matching Quagga and
+ FRR daemon binaries. Used by FRR versions 2.0 through 3.0.3.
+
+- Version 5
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-------------------------------+---------------+-------------+
- | Length (2) | Marker (1) | Version (1) |
- +-------------------------------+---------------+-------------+
- | Command (2) |
- +-------------------------------+
+ Increased VRF identifier field from 16 to 32 bits. Used by FRR versions 4.0
+ through 5.0.1.
+- Version 6
+
+ Removed the following commands:
+
+ * ZEBRA_IPV4_ROUTE_ADD
+ * ZEBRA_IPV4_ROUTE_DELETE
+ * ZEBRA_IPV6_ROUTE_ADD
+ * ZEBRA_IPV6_ROUTE_DELETE
+
+ Used since FRR version 6.0.
+
+
+Zebra Protocol Definition
+=========================
Zebra Protocol Header Field Definitions
---------------------------------------
Length
- Total packet length including this header. The minimum length is 3 bytes for
- version 0 messages and 6 bytes for version 1 messages.
+ Total packet length including this header.
Marker
- Static marker with a value of 255 always. This is to allow version 0 Zserv
- headers (which do not include version explicitly) to be distinguished from
- versioned headers. Not present in version 0 messages.
+ Static marker. The marker value, when it exists, is 255 in all versions of
+ Quagga. It is 254 in all versions of FRR. This is to allow version 0 headers
+ (which do not include version explicitly) to be distinguished from versioned
+ headers.
Version
- Version number of the Zserv message. Clients should not continue processing
- messages past the version field for versions they do not recognise. Not
- present in version 0 messages.
+ Zebra protocol version number. Clients should not continue processing
+ messages past the version field for versions they do not recognise.
Command
- The Zebra Protocol command.
+ The Zebra protocol command.
+
+
+Current Version
+^^^^^^^^^^^^^^^
+
+::
+
+ Version 5, 6
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length | Marker | Version |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | VRF ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Command |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+Past Versions
+^^^^^^^^^^^^^
+
+::
+
+ Version 0
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length | Command |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+::
+
+ Version 1, 2
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length | Marker | Version |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Command |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+::
+
+ Version 3, 4
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length | Marker | Version |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | VRF ID | Command |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Zebra Protocol Commands
-----------------------
-+-----------------------------------+-------+
-| Command | Value |
-+===================================+=======+
-| ZEBRA_INTERFACE_ADD | 1 |
-+-----------------------------------+-------+
-| ZEBRA_INTERFACE_DELETE | 2 |
-+-----------------------------------+-------+
-| ZEBRA_INTERFACE_ADDRESS_ADD | 3 |
-+-----------------------------------+-------+
-| ZEBRA_INTERFACE_ADDRESS_DELETE | 4 |
-+-----------------------------------+-------+
-| ZEBRA_INTERFACE_UP | 5 |
-+-----------------------------------+-------+
-| ZEBRA_INTERFACE_DOWN | 6 |
-+-----------------------------------+-------+
-| ZEBRA_REDISTRIBUTE_ADD | 11 |
-+-----------------------------------+-------+
-| ZEBRA_REDISTRIBUTE_DELETE | 12 |
-+-----------------------------------+-------+
-| ZEBRA_REDISTRIBUTE_DEFAULT_ADD | 13 |
-+-----------------------------------+-------+
-| ZEBRA_REDISTRIBUTE_DEFAULT_DELETE | 14 |
-+-----------------------------------+-------+
-| ZEBRA_IPV4_NEXTHOP_LOOKUP | 15 |
-+-----------------------------------+-------+
-| ZEBRA_IPV6_NEXTHOP_LOOKUP | 16 |
-+-----------------------------------+-------+
++------------------------------------+-------+
+| Command | Value |
++====================================+=======+
+| ZEBRA_INTERFACE_ADD | 0 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_DELETE | 1 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_ADDRESS_ADD | 2 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_ADDRESS_DELETE | 3 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_UP | 4 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_DOWN | 5 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_SET_MASTER | 6 |
++------------------------------------+-------+
+| ZEBRA_ROUTE_ADD | 7 |
++------------------------------------+-------+
+| ZEBRA_ROUTE_DELETE | 8 |
++------------------------------------+-------+
+| ZEBRA_ROUTE_NOTIFY_OWNER | 9 |
++------------------------------------+-------+
+| ZEBRA_REDISTRIBUTE_ADD | 10 |
++------------------------------------+-------+
+| ZEBRA_REDISTRIBUTE_DELETE | 11 |
++------------------------------------+-------+
+| ZEBRA_REDISTRIBUTE_DEFAULT_ADD | 12 |
++------------------------------------+-------+
+| ZEBRA_REDISTRIBUTE_DEFAULT_DELETE | 13 |
++------------------------------------+-------+
+| ZEBRA_ROUTER_ID_ADD | 14 |
++------------------------------------+-------+
+| ZEBRA_ROUTER_ID_DELETE | 15 |
++------------------------------------+-------+
+| ZEBRA_ROUTER_ID_UPDATE | 16 |
++------------------------------------+-------+
+| ZEBRA_HELLO | 17 |
++------------------------------------+-------+
+| ZEBRA_CAPABILITIES | 18 |
++------------------------------------+-------+
+| ZEBRA_NEXTHOP_REGISTER | 19 |
++------------------------------------+-------+
+| ZEBRA_NEXTHOP_UNREGISTER | 20 |
++------------------------------------+-------+
+| ZEBRA_NEXTHOP_UPDATE | 21 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_NBR_ADDRESS_ADD | 22 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_NBR_ADDRESS_DELETE | 23 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_BFD_DEST_UPDATE | 24 |
++------------------------------------+-------+
+| ZEBRA_IMPORT_ROUTE_REGISTER | 25 |
++------------------------------------+-------+
+| ZEBRA_IMPORT_ROUTE_UNREGISTER | 26 |
++------------------------------------+-------+
+| ZEBRA_IMPORT_CHECK_UPDATE | 27 |
++------------------------------------+-------+
+| ZEBRA_BFD_DEST_REGISTER | 28 |
++------------------------------------+-------+
+| ZEBRA_BFD_DEST_DEREGISTER | 29 |
++------------------------------------+-------+
+| ZEBRA_BFD_DEST_UPDATE | 30 |
++------------------------------------+-------+
+| ZEBRA_BFD_DEST_REPLAY | 31 |
++------------------------------------+-------+
+| ZEBRA_REDISTRIBUTE_ROUTE_ADD | 32 |
++------------------------------------+-------+
+| ZEBRA_REDISTRIBUTE_ROUTE_DEL | 33 |
++------------------------------------+-------+
+| ZEBRA_VRF_UNREGISTER | 34 |
++------------------------------------+-------+
+| ZEBRA_VRF_ADD | 35 |
++------------------------------------+-------+
+| ZEBRA_VRF_DELETE | 36 |
++------------------------------------+-------+
+| ZEBRA_VRF_LABEL | 37 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_VRF_UPDATE | 38 |
++------------------------------------+-------+
+| ZEBRA_BFD_CLIENT_REGISTER | 39 |
++------------------------------------+-------+
+| ZEBRA_BFD_CLIENT_DEREGISTER | 40 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_ENABLE_RADV | 41 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_DISABLE_RADV | 42 |
++------------------------------------+-------+
+| ZEBRA_IPV3_NEXTHOP_LOOKUP_MRIB | 44 |
++------------------------------------+-------+
+| ZEBRA_INTERFACE_LINK_PARAMS | 44 |
++------------------------------------+-------+
+| ZEBRA_MPLS_LABELS_ADD | 45 |
++------------------------------------+-------+
+| ZEBRA_MPLS_LABELS_DELETE | 46 |
++------------------------------------+-------+
+| ZEBRA_IPMR_ROUTE_STATS | 47 |
++------------------------------------+-------+
+| ZEBRA_LABEL_MANAGER_CONNECT | 48 |
++------------------------------------+-------+
+| ZEBRA_LABEL_MANAGER_CONNECT_ASYNC | 49 |
++------------------------------------+-------+
+| ZEBRA_GET_LABEL_CHUNK | 50 |
++------------------------------------+-------+
+| ZEBRA_RELEASE_LABEL_CHUNK | 51 |
++------------------------------------+-------+
+| ZEBRA_FEC_REGISTER | 52 |
++------------------------------------+-------+
+| ZEBRA_FEC_UNREGISTER | 53 |
++------------------------------------+-------+
+| ZEBRA_FEC_UPDATE | 54 |
++------------------------------------+-------+
+| ZEBRA_ADVERTISE_DEFAULT_GW | 55 |
++------------------------------------+-------+
+| ZEBRA_ADVERTISE_SUBNET | 56 |
++------------------------------------+-------+
+| ZEBRA_ADVERTISE_ALL_VNI | 57 |
++------------------------------------+-------+
+| ZEBRA_LOCAL_ES_ADD | 58 |
++------------------------------------+-------+
+| ZEBRA_LOCAL_ES_DEL | 59 |
++------------------------------------+-------+
+| ZEBRA_VNI_ADD | 60 |
++------------------------------------+-------+
+| ZEBRA_VNI_DEL | 61 |
++------------------------------------+-------+
+| ZEBRA_L2VNI_ADD | 63 |
++------------------------------------+-------+
+| ZEBRA_L2VNI_DEL | 64 |
++------------------------------------+-------+
+| ZEBRA_REMOTE_VTEP_ADD | 64 |
++------------------------------------+-------+
+| ZEBRA_REMOTE_VTEP_DEL | 65 |
++------------------------------------+-------+
+| ZEBRA_MACIP_ADD | 66 |
++------------------------------------+-------+
+| ZEBRA_MACIP_DEL | 67 |
++------------------------------------+-------+
+| ZEBRA_IP_PREFIX_ROUTE_ADD | 68 |
++------------------------------------+-------+
+| ZEBRA_IP_PREFIX_ROUTE_DEL | 69 |
++------------------------------------+-------+
+| ZEBRA_REMOTE_MACIP_ADD | 70 |
++------------------------------------+-------+
+| ZEBRA_REMOTE_MACIP_DEL | 71 |
++------------------------------------+-------+
+| ZEBRA_PW_ADD | 72 |
++------------------------------------+-------+
+| ZEBRA_PW_DELETE | 73 |
++------------------------------------+-------+
+| ZEBRA_PW_SET | 74 |
++------------------------------------+-------+
+| ZEBRA_PW_UNSET | 75 |
++------------------------------------+-------+
+| ZEBRA_PW_STATUS_UPDATE | 76 |
++------------------------------------+-------+
+| ZEBRA_RULE_ADD | 77 |
++------------------------------------+-------+
+| ZEBRA_RULE_DELETE | 78 |
++------------------------------------+-------+
+| ZEBRA_RULE_NOTIFY_OWNER | 79 |
++------------------------------------+-------+
+| ZEBRA_TABLE_MANAGER_CONNECT | 80 |
++------------------------------------+-------+
+| ZEBRA_GET_TABLE_CHUNK | 81 |
++------------------------------------+-------+
+| ZEBRA_RELEASE_TABLE_CHUNK | 82 |
++------------------------------------+-------+
+| ZEBRA_IPSET_CREATE | 83 |
++------------------------------------+-------+
+| ZEBRA_IPSET_DESTROY | 84 |
++------------------------------------+-------+
+| ZEBRA_IPSET_ENTRY_ADD | 85 |
++------------------------------------+-------+
+| ZEBRA_IPSET_ENTRY_DELETE | 86 |
++------------------------------------+-------+
+| ZEBRA_IPSET_NOTIFY_OWNER | 87 |
++------------------------------------+-------+
+| ZEBRA_IPSET_ENTRY_NOTIFY_OWNER | 88 |
++------------------------------------+-------+
+| ZEBRA_IPTABLE_ADD | 89 |
++------------------------------------+-------+
+| ZEBRA_IPTABLE_DELETE | 90 |
++------------------------------------+-------+
+| ZEBRA_IPTABLE_NOTIFY_OWNER | 91 |
++------------------------------------+-------+
+| ZEBRA_VXLAN_FLOOD_CONTROL | 92 |
++------------------------------------+-------+
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index b7f0712a1b..9654cc2eb8 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -255,6 +255,24 @@ options to the configuration script.
Configure zebra to use `dir` for local state files, such as pid files and
unix sockets.
+.. option:: --with-yangmodelsdir <dir>
+
+ Look for YANG modules in `dir` [`prefix`/share/yang]. Note that the FRR
+ YANG modules will be installed here.
+
+.. option:: --with-libyang-pluginsdir <dir>
+
+ Look for libyang plugins in `dir` [`prefix`/lib/frr/libyang_plugins].
+ Note that the FRR libyang plugins will be installed here.
+
+When it's desired to run FRR without installing it in the system, it's possible
+to configure it as follows to look for YANG modules and libyang plugins in the
+compile directory:
+.. code-block:: shell
+
+ ./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \
+ --with-yangmodelsdir="`pwd`/yang"
+
.. _least-privilege-support:
Least-Privilege Support
@@ -367,7 +385,7 @@ Additional kernel modules are also needed to support MPLS forwarding.
appropriate value.
:makevar:`VRF forwarding`
- General information on Linux VRF support can be found in
+ General information on Linux VRF support can be found in
https://www.kernel.org/doc/Documentation/networking/vrf.txt. Kernel
support for VRFs was introduced in 4.3 and improved upon through
4.13, which is the version most used in FRR testing (as of June
@@ -403,7 +421,7 @@ Additional kernel modules are also needed to support MPLS forwarding.
included in future kernel versions so upgrading your kernel may also
address this issue.
-
+
Building
^^^^^^^^
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index ee681858d1..f7607a54f7 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -30,14 +30,11 @@ configuration file :file:`isisd.conf`.
ISIS router
===========
-To start ISIS process you have to specify the ISIS router. As of this
+To start the ISIS process you have to specify the ISIS router. As of this
writing, *isisd* does not support multiple ISIS processes.
-.. index:: router isis WORD
-.. clicmd:: router isis WORD
-
-.. index:: no router isis WORD
-.. clicmd:: no router isis WORD
+.. index:: [no] router isis WORD
+.. clicmd:: [no] router isis WORD
Enable or disable the ISIS process by specifying the ISIS domain with
'WORD'. *isisd* does not yet support multiple ISIS processes but you must
@@ -197,17 +194,15 @@ ISIS region
ISIS interface
==============
-.. index:: ip router isis WORD
-.. clicmd:: ip router isis WORD
-
-.. index:: no ip router isis WORD
-.. clicmd:: no ip router isis WORD
-
.. _ip-router-isis-word:
- Activate ISIS adjacency on this interface. Note that the name
- of ISIS instance must be the same as the one used to configure the ISIS process
- (see command :clicmd:`router isis WORD`).
+.. index:: [no] <ip|ipv6> router isis WORD
+.. clicmd:: [no] <ip|ipv6> router isis WORD
+
+ Activate ISIS adjacency on this interface. Note that the name of ISIS
+ instance must be the same as the one used to configure the ISIS process (see
+ command :clicmd:`router isis WORD`). To enable IPv4, issue ``ip router isis
+ WORD``; to enable IPv6, issue ``ipv6 router isis WORD``.
.. index:: isis circuit-type [level-1 | level-1-2 | level-2]
.. clicmd:: isis circuit-type [level-1 | level-1-2 | level-2]
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index e843136396..b6a7cd5de0 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -979,14 +979,17 @@ Traffic Engineering
Router Information
==================
-.. index:: router-info [as | area <A.B.C.D>]
-.. clicmd:: router-info [as | area <A.B.C.D>]
+.. index:: router-info [as | area]
+.. clicmd:: router-info [as | area]
.. index:: no router-info
.. clicmd:: no router-info
Enable Router Information (:rfc:`4970`) LSA advertisement with AS scope
- (default) or Area scope flooding when area is specified.
+ (default) or Area scope flooding when area is specified. Old syntax
+ `router-info area <A.B.C.D>` is always supported but mark as deprecated
+ as the area ID is no more necessary. Indeed, router information support
+ multi-area and detect automatically the areas.
.. index:: pce address <A.B.C.D>
.. clicmd:: pce address <A.B.C.D>
diff --git a/doc/user/static.rst b/doc/user/static.rst
index 6755c809eb..1705b6379e 100644
--- a/doc/user/static.rst
+++ b/doc/user/static.rst
@@ -9,7 +9,7 @@ of static routes.
.. _starting-static:
-Starting STATIC
+Starting STATIC
===============
Default configuration file for *staticd* is :file:`staticd.conf`. The typical
@@ -45,11 +45,11 @@ a static prefix and gateway.
initial form of the command. GATEWAY is gateway for the prefix it currently
must match the v4 or v6 route type specified at the start of the command.
GATEWAY can also be treated as an interface name. If the interface name
- is ``null0`` then zebra installs a blackhole route. TABLENO
+ is ``null0`` then zebra installs a blackhole route. TABLENO
is an optional parameter for namespaces that allows you to create the
route in a specified table associated with the vrf namespace. table will
be rejected if you are not using namespace based vrfs. ``nexthop-vrf``
- allows you to create a leaked route with a nexthop in the specified VRFNAME
+ allows you to create a leaked route with a nexthop in the specified VRFNAME
vrf VRFNAME allows you to create the route in a specified vrf.
``nexthop-vrf`` cannot be currently used with namespace based vrfs
currently as well.
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 1cfb7953d4..c509eb8583 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -140,16 +140,6 @@ Standard Commands
behind the other end of the link (or even on the link in Point-to-Multipoint
setups), though generally /32s are used.
-.. index:: ip address ADDRESS/PREFIX secondary
-
-.. clicmd:: ip address ADDRESS/PREFIX secondary
-.. index:: no ip address ADDRESS/PREFIX secondary
-
-.. clicmd:: no ip address ADDRESS/PREFIX secondary
-
- Set the secondary flag for this address. This causes ospfd to not treat the
- address as a distinct subnet.
-
.. index:: description DESCRIPTION ...
.. clicmd:: description DESCRIPTION ...
@@ -186,7 +176,7 @@ Standard Commands
Enable/disable link-detect on platforms which support this. Currently only
Linux and Solaris, and only where network interface drivers support
reporting link-state via the ``IFF_RUNNING`` flag.
-
+
In FRR, link-detect is on by default.
.. _link-parameters-commands:
@@ -393,7 +383,7 @@ alternate name for default VRF. Then, the default VRF naming will automatically
be updated with the new name. To illustrate, if you want to recompile with
`global` value, use the following command:
-.. code-block:: linux
+.. code-block:: shell
./configure --with-defaultvrfname=global
diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index 3a3d6aae12..29bd23b514 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -116,7 +116,7 @@ void eigrp_zebra_init(void)
{
struct zclient_options opt = {.receive_notify = false};
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
zclient->zebra_connected = eigrp_zebra_connected;
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index bb090f42ed..38239d5919 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -406,8 +406,12 @@ static void lsp_seqno_update(struct isis_lsp *lsp0)
for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) {
if (lsp->tlvs)
lsp_inc_seqno(lsp, 0);
- else
+ else if (lsp->hdr.rem_lifetime) {
+ /* Purge should only be applied when the fragment has
+ * non-zero remaining lifetime.
+ */
lsp_purge(lsp, lsp0->level, NULL);
+ }
}
return;
@@ -578,29 +582,17 @@ void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb)
void lsp_build_list_nonzero_ht(uint8_t *start_id, uint8_t *stop_id,
struct list *list, dict_t *lspdb)
{
- dnode_t *first, *last, *curr;
-
- first = dict_lower_bound(lspdb, start_id);
- if (!first)
- return;
-
- last = dict_upper_bound(lspdb, stop_id);
+ for (dnode_t *curr = dict_lower_bound(lspdb, start_id);
+ curr; curr = dict_next(lspdb, curr)) {
+ struct isis_lsp *lsp = curr->dict_data;
- curr = first;
-
- if (((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime)
- listnode_add(list, first->dict_data);
-
- while (curr) {
- curr = dict_next(lspdb, curr);
- if (curr
- && ((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime)
- listnode_add(list, curr->dict_data);
- if (curr == last)
+ if (memcmp(lsp->hdr.lsp_id, stop_id,
+ ISIS_SYS_ID_LEN + 2) > 0)
break;
- }
- return;
+ if (lsp->hdr.rem_lifetime)
+ listnode_add(list, lsp);
+ }
}
static void lsp_set_time(struct isis_lsp *lsp)
@@ -1306,6 +1298,13 @@ static int lsp_regenerate(struct isis_area *area, int level)
lsp->last_generated = time(NULL);
lsp_flood(lsp, NULL);
for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
+ if (!frag->tlvs) {
+ /* Updating and flooding should only affect fragments
+ * carrying data
+ */
+ continue;
+ }
+
frag->hdr.lsp_bits = lsp_bits_generate(
level, area->overload_bit, area->attached_bit);
/* Set the lifetime values of all the fragments to the same
@@ -1361,7 +1360,7 @@ static int lsp_refresh(struct thread *thread)
if ((area->is_type & level) == 0)
return ISIS_ERROR;
- if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 50000L) {
+ if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 100000L) {
sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh",
area->area_tag, level);
_lsp_regenerate_schedule(area, level, 0, false,
@@ -1999,13 +1998,13 @@ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set)
void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit)
{
- if (!fabricd) {
+ if (!fabricd)
lsp_set_all_srmflags(lsp, true);
- if (circuit)
- isis_tx_queue_del(circuit->tx_queue, lsp);
- } else {
+ else
fabricd_lsp_flood(lsp);
- }
+
+ if (circuit)
+ isis_tx_queue_del(circuit->tx_queue, lsp);
}
static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 33d8a0f771..101bd57cc9 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -87,12 +87,6 @@ static int isis_zebra_if_add(int command, struct zclient *zclient,
ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
- if (isis->debugs & DEBUG_ZEBRA)
- zlog_debug(
- "Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
- ifp->mtu);
-
if (if_is_operative(ifp))
isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
ifp);
@@ -116,12 +110,6 @@ static int isis_zebra_if_del(int command, struct zclient *zclient,
zlog_warn("Zebra: got delete of %s, but interface is still up",
ifp->name);
- if (isis->debugs & DEBUG_ZEBRA)
- zlog_debug(
- "Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
- ifp->mtu);
-
isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
/* Cannot call if_delete because we should retain the pseudo interface
@@ -425,7 +413,7 @@ static void isis_zebra_connected(struct zclient *zclient)
void isis_zebra_init(struct thread_master *master)
{
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
zclient->zebra_connected = isis_zebra_connected;
zclient->router_id_update = isis_router_id_update_zebra;
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 54bdbf3eb3..ce45ba65ec 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -720,24 +720,11 @@ void print_debug(struct vty *vty, int flags, int onoff)
vty_out(vty,
"IS-IS Adjacency related packets debugging is %s\n",
onoffs);
- if (flags & DEBUG_CHECKSUM_ERRORS)
- vty_out(vty, "IS-IS checksum errors debugging is %s\n", onoffs);
- if (flags & DEBUG_LOCAL_UPDATES)
- vty_out(vty, "IS-IS local updates debugging is %s\n", onoffs);
- if (flags & DEBUG_PROTOCOL_ERRORS)
- vty_out(vty, "IS-IS protocol errors debugging is %s\n", onoffs);
if (flags & DEBUG_SNP_PACKETS)
vty_out(vty, "IS-IS CSNP/PSNP packets debugging is %s\n",
onoffs);
if (flags & DEBUG_SPF_EVENTS)
vty_out(vty, "IS-IS SPF events debugging is %s\n", onoffs);
- if (flags & DEBUG_SPF_STATS)
- vty_out(vty,
- "IS-IS SPF Timing and Statistics Data debugging is %s\n",
- onoffs);
- if (flags & DEBUG_SPF_TRIGGERS)
- vty_out(vty, "IS-IS SPF triggering events debugging is %s\n",
- onoffs);
if (flags & DEBUG_UPDATE_PACKETS)
vty_out(vty, "IS-IS Update related packet debugging is %s\n",
onoffs);
@@ -784,18 +771,6 @@ static int config_write_debug(struct vty *vty)
vty_out(vty, "debug " PROTO_NAME " adj-packets\n");
write++;
}
- if (flags & DEBUG_CHECKSUM_ERRORS) {
- vty_out(vty, "debug " PROTO_NAME " checksum-errors\n");
- write++;
- }
- if (flags & DEBUG_LOCAL_UPDATES) {
- vty_out(vty, "debug " PROTO_NAME " local-updates\n");
- write++;
- }
- if (flags & DEBUG_PROTOCOL_ERRORS) {
- vty_out(vty, "debug " PROTO_NAME " protocol-errors\n");
- write++;
- }
if (flags & DEBUG_SNP_PACKETS) {
vty_out(vty, "debug " PROTO_NAME " snp-packets\n");
write++;
@@ -804,14 +779,6 @@ static int config_write_debug(struct vty *vty)
vty_out(vty, "debug " PROTO_NAME " spf-events\n");
write++;
}
- if (flags & DEBUG_SPF_STATS) {
- vty_out(vty, "debug " PROTO_NAME " spf-statistics\n");
- write++;
- }
- if (flags & DEBUG_SPF_TRIGGERS) {
- vty_out(vty, "debug " PROTO_NAME " spf-triggers\n");
- write++;
- }
if (flags & DEBUG_UPDATE_PACKETS) {
vty_out(vty, "debug " PROTO_NAME " update-packets\n");
write++;
@@ -876,87 +843,6 @@ DEFUN (no_debug_isis_adj,
return CMD_SUCCESS;
}
-DEFUN (debug_isis_csum,
- debug_isis_csum_cmd,
- "debug " PROTO_NAME " checksum-errors",
- DEBUG_STR
- PROTO_HELP
- "IS-IS LSP checksum errors\n")
-{
- isis->debugs |= DEBUG_CHECKSUM_ERRORS;
- print_debug(vty, DEBUG_CHECKSUM_ERRORS, 1);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_isis_csum,
- no_debug_isis_csum_cmd,
- "no debug " PROTO_NAME " checksum-errors",
- NO_STR
- UNDEBUG_STR
- PROTO_HELP
- "IS-IS LSP checksum errors\n")
-{
- isis->debugs &= ~DEBUG_CHECKSUM_ERRORS;
- print_debug(vty, DEBUG_CHECKSUM_ERRORS, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (debug_isis_lupd,
- debug_isis_lupd_cmd,
- "debug " PROTO_NAME " local-updates",
- DEBUG_STR
- PROTO_HELP
- "IS-IS local update packets\n")
-{
- isis->debugs |= DEBUG_LOCAL_UPDATES;
- print_debug(vty, DEBUG_LOCAL_UPDATES, 1);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_isis_lupd,
- no_debug_isis_lupd_cmd,
- "no debug " PROTO_NAME " local-updates",
- NO_STR
- UNDEBUG_STR
- PROTO_HELP
- "IS-IS local update packets\n")
-{
- isis->debugs &= ~DEBUG_LOCAL_UPDATES;
- print_debug(vty, DEBUG_LOCAL_UPDATES, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (debug_isis_err,
- debug_isis_err_cmd,
- "debug " PROTO_NAME " protocol-errors",
- DEBUG_STR
- PROTO_HELP
- "IS-IS LSP protocol errors\n")
-{
- isis->debugs |= DEBUG_PROTOCOL_ERRORS;
- print_debug(vty, DEBUG_PROTOCOL_ERRORS, 1);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_isis_err,
- no_debug_isis_err_cmd,
- "no debug " PROTO_NAME " protocol-errors",
- NO_STR
- UNDEBUG_STR
- PROTO_HELP
- "IS-IS LSP protocol errors\n")
-{
- isis->debugs &= ~DEBUG_PROTOCOL_ERRORS;
- print_debug(vty, DEBUG_PROTOCOL_ERRORS, 0);
-
- return CMD_SUCCESS;
-}
-
DEFUN (debug_isis_snp,
debug_isis_snp_cmd,
"debug " PROTO_NAME " snp-packets",
@@ -1038,60 +924,6 @@ DEFUN (no_debug_isis_spfevents,
return CMD_SUCCESS;
}
-DEFUN (debug_isis_spfstats,
- debug_isis_spfstats_cmd,
- "debug " PROTO_NAME " spf-statistics ",
- DEBUG_STR
- PROTO_HELP
- "IS-IS SPF Timing and Statistic Data\n")
-{
- isis->debugs |= DEBUG_SPF_STATS;
- print_debug(vty, DEBUG_SPF_STATS, 1);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_isis_spfstats,
- no_debug_isis_spfstats_cmd,
- "no debug " PROTO_NAME " spf-statistics",
- NO_STR
- UNDEBUG_STR
- PROTO_HELP
- "IS-IS SPF Timing and Statistic Data\n")
-{
- isis->debugs &= ~DEBUG_SPF_STATS;
- print_debug(vty, DEBUG_SPF_STATS, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (debug_isis_spftrigg,
- debug_isis_spftrigg_cmd,
- "debug " PROTO_NAME " spf-triggers",
- DEBUG_STR
- PROTO_HELP
- "IS-IS SPF triggering events\n")
-{
- isis->debugs |= DEBUG_SPF_TRIGGERS;
- print_debug(vty, DEBUG_SPF_TRIGGERS, 1);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_isis_spftrigg,
- no_debug_isis_spftrigg_cmd,
- "no debug " PROTO_NAME " spf-triggers",
- NO_STR
- UNDEBUG_STR
- PROTO_HELP
- "IS-IS SPF triggering events\n")
-{
- isis->debugs &= ~DEBUG_SPF_TRIGGERS;
- print_debug(vty, DEBUG_SPF_TRIGGERS, 0);
-
- return CMD_SUCCESS;
-}
-
DEFUN (debug_isis_rtevents,
debug_isis_rtevents_cmd,
"debug " PROTO_NAME " route-events",
@@ -2229,22 +2061,12 @@ void isis_init()
install_element(ENABLE_NODE, &debug_isis_adj_cmd);
install_element(ENABLE_NODE, &no_debug_isis_adj_cmd);
- install_element(ENABLE_NODE, &debug_isis_csum_cmd);
- install_element(ENABLE_NODE, &no_debug_isis_csum_cmd);
- install_element(ENABLE_NODE, &debug_isis_lupd_cmd);
- install_element(ENABLE_NODE, &no_debug_isis_lupd_cmd);
- install_element(ENABLE_NODE, &debug_isis_err_cmd);
- install_element(ENABLE_NODE, &no_debug_isis_err_cmd);
install_element(ENABLE_NODE, &debug_isis_snp_cmd);
install_element(ENABLE_NODE, &no_debug_isis_snp_cmd);
install_element(ENABLE_NODE, &debug_isis_upd_cmd);
install_element(ENABLE_NODE, &no_debug_isis_upd_cmd);
install_element(ENABLE_NODE, &debug_isis_spfevents_cmd);
install_element(ENABLE_NODE, &no_debug_isis_spfevents_cmd);
- install_element(ENABLE_NODE, &debug_isis_spfstats_cmd);
- install_element(ENABLE_NODE, &no_debug_isis_spfstats_cmd);
- install_element(ENABLE_NODE, &debug_isis_spftrigg_cmd);
- install_element(ENABLE_NODE, &no_debug_isis_spftrigg_cmd);
install_element(ENABLE_NODE, &debug_isis_rtevents_cmd);
install_element(ENABLE_NODE, &no_debug_isis_rtevents_cmd);
install_element(ENABLE_NODE, &debug_isis_events_cmd);
@@ -2260,22 +2082,12 @@ void isis_init()
install_element(CONFIG_NODE, &debug_isis_adj_cmd);
install_element(CONFIG_NODE, &no_debug_isis_adj_cmd);
- install_element(CONFIG_NODE, &debug_isis_csum_cmd);
- install_element(CONFIG_NODE, &no_debug_isis_csum_cmd);
- install_element(CONFIG_NODE, &debug_isis_lupd_cmd);
- install_element(CONFIG_NODE, &no_debug_isis_lupd_cmd);
- install_element(CONFIG_NODE, &debug_isis_err_cmd);
- install_element(CONFIG_NODE, &no_debug_isis_err_cmd);
install_element(CONFIG_NODE, &debug_isis_snp_cmd);
install_element(CONFIG_NODE, &no_debug_isis_snp_cmd);
install_element(CONFIG_NODE, &debug_isis_upd_cmd);
install_element(CONFIG_NODE, &no_debug_isis_upd_cmd);
install_element(CONFIG_NODE, &debug_isis_spfevents_cmd);
install_element(CONFIG_NODE, &no_debug_isis_spfevents_cmd);
- install_element(CONFIG_NODE, &debug_isis_spfstats_cmd);
- install_element(CONFIG_NODE, &no_debug_isis_spfstats_cmd);
- install_element(CONFIG_NODE, &debug_isis_spftrigg_cmd);
- install_element(CONFIG_NODE, &no_debug_isis_spftrigg_cmd);
install_element(CONFIG_NODE, &debug_isis_rtevents_cmd);
install_element(CONFIG_NODE, &no_debug_isis_rtevents_cmd);
install_element(CONFIG_NODE, &debug_isis_events_cmd);
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 51b359aad4..fe9abff93c 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -204,22 +204,16 @@ int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level,
extern struct thread_master *master;
#define DEBUG_ADJ_PACKETS (1<<0)
-#define DEBUG_CHECKSUM_ERRORS (1<<1)
-#define DEBUG_LOCAL_UPDATES (1<<2)
-#define DEBUG_PROTOCOL_ERRORS (1<<3)
-#define DEBUG_SNP_PACKETS (1<<4)
-#define DEBUG_UPDATE_PACKETS (1<<5)
-#define DEBUG_SPF_EVENTS (1<<6)
-#define DEBUG_SPF_STATS (1<<7)
-#define DEBUG_SPF_TRIGGERS (1<<8)
-#define DEBUG_RTE_EVENTS (1<<9)
-#define DEBUG_EVENTS (1<<10)
-#define DEBUG_ZEBRA (1<<11)
-#define DEBUG_PACKET_DUMP (1<<12)
-#define DEBUG_LSP_GEN (1<<13)
-#define DEBUG_LSP_SCHED (1<<14)
-#define DEBUG_FABRICD_FLOODING (1<<15)
-#define DEBUG_BFD (1<<16)
+#define DEBUG_SNP_PACKETS (1<<1)
+#define DEBUG_UPDATE_PACKETS (1<<2)
+#define DEBUG_SPF_EVENTS (1<<3)
+#define DEBUG_RTE_EVENTS (1<<4)
+#define DEBUG_EVENTS (1<<5)
+#define DEBUG_PACKET_DUMP (1<<6)
+#define DEBUG_LSP_GEN (1<<7)
+#define DEBUG_LSP_SCHED (1<<8)
+#define DEBUG_FABRICD_FLOODING (1<<9)
+#define DEBUG_BFD (1<<10)
#define lsp_debug(...) \
do { \
@@ -233,7 +227,7 @@ extern struct thread_master *master;
zlog_debug(__VA_ARGS__); \
} while (0)
-#define DEBUG_TE (1<<13)
+#define DEBUG_TE DEBUG_LSP_GEN
#define IS_DEBUG_ISIS(x) (isis->debugs & x)
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 4f74d93044..2aa96546ec 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -1627,7 +1627,7 @@ lde_address_list_free(struct lde_nbr *ln)
static void zclient_sync_init(unsigned short instance)
{
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new_notify(master, &zclient_options_default);
+ zclient_sync = zclient_new(master, &zclient_options_default);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
zclient_sync->instance = instance;
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index c8b775cb8e..9dc5677358 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -533,7 +533,7 @@ void
ldp_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs);
/* set callbacks */
diff --git a/lib/agentx.c b/lib/agentx.c
index 55bb9e99ec..40cac722ae 100644
--- a/lib/agentx.c
+++ b/lib/agentx.c
@@ -188,9 +188,8 @@ DEFUN (agentx_enable,
events = list_new();
agentx_events_update();
agentx_enabled = 1;
- return CMD_SUCCESS;
}
- vty_out(vty, "SNMP AgentX already enabled\n");
+
return CMD_SUCCESS;
}
diff --git a/lib/id_alloc.c b/lib/id_alloc.c
new file mode 100644
index 0000000000..222ba651b4
--- /dev/null
+++ b/lib/id_alloc.c
@@ -0,0 +1,406 @@
+/*
+ * FRR ID Number Allocator
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "id_alloc.h"
+
+#include "log.h"
+#include "lib_errors.h"
+#include "memory.h"
+
+#include <inttypes.h>
+
+DEFINE_MTYPE_STATIC(LIB, IDALLOC_ALLOCATOR, "ID Number Allocator")
+DEFINE_MTYPE_STATIC(LIB, IDALLOC_ALLOCATOR_NAME, "ID Number Allocator Name")
+DEFINE_MTYPE_STATIC(LIB, IDALLOC_DIRECTORY, "ID Number Allocator Directory")
+DEFINE_MTYPE_STATIC(LIB, IDALLOC_SUBDIRECTORY,
+ "ID Number Allocator Subdirectory")
+DEFINE_MTYPE_STATIC(LIB, IDALLOC_PAGE, "ID Number Allocator Page")
+DEFINE_MTYPE_STATIC(LIB, IDALLOC_POOL, "ID Number temporary holding pool entry")
+
+#if UINT_MAX >= UINT32_MAX
+#define FFS32(x) ffs(x)
+#else
+/* ints less than 32 bits? Yikes. */
+#define FFS32(x) ffsl(x)
+#endif
+
+#define DIR_MASK ((1<<IDALLOC_DIR_BITS)-1)
+#define SUBDIR_MASK ((1<<IDALLOC_SUBDIR_BITS)-1)
+#define FRR_ID_PAGE_MASK ((1<<IDALLOC_PAGE_BITS)-1)
+#define WORD_MASK ((1<<IDALLOC_WORD_BITS)-1)
+#define OFFSET_MASK ((1<<IDALLOC_OFFSET_BITS)-1)
+
+#define DIR_SHIFT (IDALLOC_OFFSET_BITS + IDALLOC_WORD_BITS + \
+ IDALLOC_PAGE_BITS + IDALLOC_SUBDIR_BITS)
+#define SUBDIR_SHIFT (IDALLOC_OFFSET_BITS + IDALLOC_WORD_BITS + \
+ IDALLOC_PAGE_BITS)
+#define FRR_ID_PAGE_SHIFT (IDALLOC_OFFSET_BITS + IDALLOC_WORD_BITS)
+#define WORD_SHIFT (IDALLOC_OFFSET_BITS)
+#define OFFSET_SHIFT (0)
+
+#define ID_DIR(id) ((id >> DIR_SHIFT) & DIR_MASK)
+#define ID_SUBDIR(id) ((id >> SUBDIR_SHIFT) & SUBDIR_MASK)
+#define ID_PAGE(id) ((id >> FRR_ID_PAGE_SHIFT) & FRR_ID_PAGE_MASK)
+#define ID_WORD(id) ((id >> WORD_SHIFT) & WORD_MASK)
+#define ID_OFFSET(id) ((id >> OFFSET_SHIFT) & OFFSET_MASK)
+
+/*
+ * Find the page that an ID number belongs to in an allocator.
+ * Optionally create the page if it doesn't exist.
+ */
+static struct id_alloc_page *find_or_create_page(struct id_alloc *alloc,
+ uint32_t id, int create)
+{
+ struct id_alloc_dir *dir = NULL;
+ struct id_alloc_subdir *subdir = NULL;
+ struct id_alloc_page *page = NULL;
+
+ dir = alloc->sublevels[ID_DIR(id)];
+ if (dir == NULL) {
+ if (create) {
+ dir = XCALLOC(MTYPE_IDALLOC_DIRECTORY, sizeof(*dir));
+ alloc->sublevels[ID_DIR(id)] = dir;
+ } else {
+ return NULL;
+ }
+ }
+
+ subdir = dir->sublevels[ID_SUBDIR(id)];
+ if (subdir == NULL) {
+ if (create) {
+ subdir = XCALLOC(MTYPE_IDALLOC_SUBDIRECTORY,
+ sizeof(*subdir));
+ dir->sublevels[ID_SUBDIR(id)] = subdir;
+ } else {
+ return NULL;
+ }
+ }
+
+ page = subdir->sublevels[ID_PAGE(id)];
+ if (page == NULL && create) {
+ page = XCALLOC(MTYPE_IDALLOC_PAGE, sizeof(*page));
+ page->base_value = id;
+ subdir->sublevels[ID_PAGE(id)] = page;
+
+ alloc->capacity += 1 << FRR_ID_PAGE_SHIFT;
+ page->next_has_free = alloc->has_free;
+ alloc->has_free = page;
+ } else if (page != NULL && create) {
+ flog_err(
+ EC_LIB_ID_CONSISTENCY,
+ "ID Allocator %s attempt to re-create page at %" PRIu32,
+ alloc->name, id);
+ }
+
+ return page;
+}
+
+/*
+ * Return an ID number back to the allocator.
+ * While this ID can be re-assigned through idalloc_allocate, the underlying
+ * memory will not be freed. If this is the first free ID in the page, the page
+ * will be added to the allocator's list of pages with free IDs.
+ */
+void idalloc_free(struct id_alloc *alloc, uint32_t id)
+{
+ struct id_alloc_page *page = NULL;
+
+ int word, offset;
+ uint32_t old_word, old_word_mask;
+
+ page = find_or_create_page(alloc, id, 0);
+ if (!page) {
+ flog_err(EC_LIB_ID_CONSISTENCY,
+ "ID Allocator %s cannot free #%" PRIu32
+ ". ID Block does not exist.",
+ alloc->name, id);
+ return;
+ }
+
+ word = ID_WORD(id);
+ offset = ID_OFFSET(id);
+
+ if ((page->allocated_mask[word] & (1 << offset)) == 0) {
+ flog_err(EC_LIB_ID_CONSISTENCY,
+ "ID Allocator %s cannot free #%" PRIu32
+ ". ID was not allocated at the time of free.",
+ alloc->name, id);
+ return;
+ }
+
+ old_word = page->allocated_mask[word];
+ page->allocated_mask[word] &= ~(((uint32_t)1) << offset);
+ alloc->allocated -= 1;
+
+ if (old_word == UINT32_MAX) {
+ /* first bit in this block of 32 to be freed.*/
+
+ old_word_mask = page->full_word_mask;
+ page->full_word_mask &= ~(((uint32_t)1) << word);
+
+ if (old_word_mask == UINT32_MAX) {
+ /* first bit in page freed, add this to the allocator's
+ * list of pages with free space
+ */
+ page->next_has_free = alloc->has_free;
+ alloc->has_free = page;
+ }
+ }
+}
+
+/*
+ * Add a allocation page to the end of the allocator's current range.
+ * Returns null if the allocator has had all possible pages allocated already.
+ */
+static struct id_alloc_page *create_next_page(struct id_alloc *alloc)
+{
+ if (alloc->capacity == 0 && alloc->sublevels[0])
+ return NULL; /* All IDs allocated and the capacity looped. */
+
+ return find_or_create_page(alloc, alloc->capacity, 1);
+}
+
+/*
+ * Marks an ID within an allocator page as in use.
+ * If the ID was the last free ID in the page, the page is removed from the
+ * allocator's list of free IDs. In the typical allocation case, this page is
+ * the first page in the list, and removing the page is fast. If instead an ID
+ * is being reserved by number, this may end up scanning the whole single linked
+ * list of pages in order to remove it.
+ */
+static void reserve_bit(struct id_alloc *alloc, struct id_alloc_page *page,
+ int word, int offset)
+{
+ struct id_alloc_page *itr;
+
+ page->allocated_mask[word] |= ((uint32_t)1) << offset;
+ alloc->allocated += 1;
+
+ if (page->allocated_mask[word] == UINT32_MAX) {
+ page->full_word_mask |= ((uint32_t)1) << word;
+ if (page->full_word_mask == UINT32_MAX) {
+ if (alloc->has_free == page) {
+ /* allocate always pulls from alloc->has_free */
+ alloc->has_free = page->next_has_free;
+ } else {
+ /* reserve could pull from any page with free
+ * bits
+ */
+ itr = alloc->has_free;
+ while (itr) {
+ if (itr->next_has_free == page) {
+ itr->next_has_free =
+ page->next_has_free;
+ return;
+ }
+
+ itr = itr->next_has_free;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Reserve an ID number from the allocator. Returns IDALLOC_INVALID (0) if the
+ * allocator has no more IDs available.
+ */
+uint32_t idalloc_allocate(struct id_alloc *alloc)
+{
+ struct id_alloc_page *page;
+ int word, offset;
+ uint32_t return_value;
+
+ if (alloc->has_free == NULL)
+ create_next_page(alloc);
+
+ if (alloc->has_free == NULL) {
+ flog_err(EC_LIB_ID_EXHAUST,
+ "ID Allocator %s has run out of IDs.", alloc->name);
+ return IDALLOC_INVALID;
+ }
+
+ page = alloc->has_free;
+ word = FFS32(~(page->full_word_mask)) - 1;
+
+ if (word < 0 || word >= 32) {
+ flog_err(EC_LIB_ID_CONSISTENCY,
+ "ID Allocator %s internal error. Page starting at %d is inconsistent.",
+ alloc->name, page->base_value);
+ return IDALLOC_INVALID;
+ }
+
+ offset = FFS32(~(page->allocated_mask[word])) - 1;
+ if (offset < 0 || offset >= 32) {
+ flog_err(EC_LIB_ID_CONSISTENCY,
+ "ID Allocator %s internal error. Page starting at %d is inconsistent on word %d",
+ alloc->name, page->base_value, word);
+ return IDALLOC_INVALID;
+ }
+ return_value = page->base_value + word * 32 + offset;
+
+ reserve_bit(alloc, page, word, offset);
+
+ return return_value;
+}
+
+/*
+ * Tries to allocate a specific ID from the allocator. Returns IDALLOC_INVALID
+ * when the ID being "reserved" has allready been assigned/reserved. This should
+ * only be done with low numbered IDs, as the allocator needs to reserve bit-map
+ * pages in order
+ */
+uint32_t idalloc_reserve(struct id_alloc *alloc, uint32_t id)
+{
+ struct id_alloc_page *page;
+ int word, offset;
+
+ while (alloc->capacity <= id)
+ create_next_page(alloc);
+
+ word = ID_WORD(id);
+ offset = ID_OFFSET(id);
+ page = find_or_create_page(alloc, id, 0);
+ /* page can't be null because the loop above ensured it was created. */
+
+ if (page->allocated_mask[word] & (((uint32_t)1) << offset)) {
+ flog_err(EC_LIB_ID_CONSISTENCY,
+ "ID Allocator %s could not reserve %" PRIu32
+ " because it is already allocated.",
+ alloc->name, id);
+ return IDALLOC_INVALID;
+ }
+
+ reserve_bit(alloc, page, word, offset);
+ return id;
+}
+
+/*
+ * Set up an empty ID allocator, with IDALLOC_INVALID pre-reserved.
+ */
+struct id_alloc *idalloc_new(const char *name)
+{
+ struct id_alloc *ret;
+
+ ret = XCALLOC(MTYPE_IDALLOC_ALLOCATOR, sizeof(*ret));
+ ret->name = XSTRDUP(MTYPE_IDALLOC_ALLOCATOR_NAME, name);
+
+ idalloc_reserve(ret, IDALLOC_INVALID);
+
+ return ret;
+}
+
+/*
+ * Free a subdir, and all pages below it.
+ */
+static void idalloc_destroy_subdir(struct id_alloc_subdir *subdir)
+{
+ int i;
+
+ for (i = 0; i < IDALLOC_PAGE_COUNT; i++) {
+ if (subdir->sublevels[i])
+ XFREE(MTYPE_IDALLOC_PAGE, subdir->sublevels[i]);
+ else
+ break;
+ }
+ XFREE(MTYPE_IDALLOC_SUBDIRECTORY, subdir);
+}
+
+/*
+ * Free a dir, and all subdirs/pages below it.
+ */
+static void idalloc_destroy_dir(struct id_alloc_dir *dir)
+{
+ int i;
+
+ for (i = 0; i < IDALLOC_SUBDIR_COUNT; i++) {
+ if (dir->sublevels[i])
+ idalloc_destroy_subdir(dir->sublevels[i]);
+ else
+ break;
+ }
+ XFREE(MTYPE_IDALLOC_DIRECTORY, dir);
+}
+
+/*
+ * Free all memory associated with an ID allocator.
+ */
+void idalloc_destroy(struct id_alloc *alloc)
+{
+ int i;
+
+ for (i = 0; i < IDALLOC_DIR_COUNT; i++) {
+ if (alloc->sublevels[i])
+ idalloc_destroy_dir(alloc->sublevels[i]);
+ else
+ break;
+ }
+
+ XFREE(MTYPE_IDALLOC_ALLOCATOR_NAME, alloc->name);
+ XFREE(MTYPE_IDALLOC_ALLOCATOR, alloc);
+}
+
+/*
+ * Give an ID number to temporary holding pool.
+ */
+void idalloc_free_to_pool(struct id_alloc_pool **pool_ptr, uint32_t id)
+{
+ struct id_alloc_pool *new_pool;
+
+ new_pool = XMALLOC(MTYPE_IDALLOC_POOL, sizeof(*new_pool));
+ new_pool->id = id;
+ new_pool->next = *pool_ptr;
+ *pool_ptr = new_pool;
+}
+
+/*
+ * Free all ID numbers held in a holding pool back to the main allocator.
+ */
+void idalloc_drain_pool(struct id_alloc *alloc, struct id_alloc_pool **pool_ptr)
+{
+ struct id_alloc_pool *current, *next;
+
+ while (*pool_ptr) {
+ current = *pool_ptr;
+ next = current->next;
+ idalloc_free(alloc, current->id);
+ XFREE(MTYPE_IDALLOC_POOL, current);
+ *pool_ptr = next;
+ }
+}
+
+/*
+ * Allocate an ID from either a holding pool, or the main allocator. IDs will
+ * only be pulled form the main allocator when the pool is empty.
+ */
+uint32_t idalloc_allocate_prefer_pool(struct id_alloc *alloc,
+ struct id_alloc_pool **pool_ptr)
+{
+ uint32_t ret;
+ struct id_alloc_pool *pool_head = *pool_ptr;
+
+ if (pool_head) {
+ ret = pool_head->id;
+ *pool_ptr = pool_head->next;
+ XFREE(MTYPE_IDALLOC_POOL, pool_head);
+ return ret;
+ } else {
+ return idalloc_allocate(alloc);
+ }
+}
diff --git a/lib/id_alloc.h b/lib/id_alloc.h
new file mode 100644
index 0000000000..efe355658a
--- /dev/null
+++ b/lib/id_alloc.h
@@ -0,0 +1,90 @@
+/*
+ * FRR ID Number Allocator
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _ZEBRA_ID_ALLOC_H
+#define _ZEBRA_ID_ALLOC_H
+
+#include <strings.h>
+#include <limits.h>
+#include <stdint.h>
+
+#define IDALLOC_INVALID 0
+
+#define IDALLOC_DIR_BITS 8
+#define IDALLOC_SUBDIR_BITS 7
+#define IDALLOC_PAGE_BITS 7
+#define IDALLOC_WORD_BITS 5
+#define IDALLOC_OFFSET_BITS 5
+
+#define IDALLOC_DIR_COUNT (1 << IDALLOC_DIR_BITS)
+#define IDALLOC_SUBDIR_COUNT (1 << IDALLOC_SUBDIR_BITS)
+#define IDALLOC_PAGE_COUNT (1 << IDALLOC_PAGE_BITS)
+#define IDALLOC_WORD_COUNT (1 << IDALLOC_WORD_BITS)
+
+struct id_alloc_page {
+ /* Bitmask of allocations. 1s indicates the ID is already allocated. */
+ uint32_t allocated_mask[IDALLOC_WORD_COUNT];
+
+ /* Bitmask for free space in allocated_mask. 1s indicate whole 32 bit
+ * section is full.
+ */
+ uint32_t full_word_mask;
+
+ /* The ID that bit 0 in allocated_mask corresponds to. */
+ uint32_t base_value;
+
+ struct id_alloc_page
+ *next_has_free; /* Next page with at least one bit open */
+};
+
+struct id_alloc_subdir {
+ struct id_alloc_page *sublevels[IDALLOC_PAGE_COUNT];
+};
+
+struct id_alloc_dir {
+ struct id_alloc_subdir *sublevels[IDALLOC_SUBDIR_COUNT];
+};
+
+struct id_alloc {
+ struct id_alloc_dir *sublevels[IDALLOC_DIR_COUNT];
+
+ struct id_alloc_page *has_free;
+
+ char *name;
+
+ uint32_t allocated, capacity;
+};
+
+struct id_alloc_pool {
+ struct id_alloc_pool *next;
+ uint32_t id;
+};
+
+void idalloc_free(struct id_alloc *alloc, uint32_t id);
+void idalloc_free_to_pool(struct id_alloc_pool **pool_ptr, uint32_t id);
+void idalloc_drain_pool(struct id_alloc *alloc,
+ struct id_alloc_pool **pool_ptr);
+uint32_t idalloc_allocate(struct id_alloc *alloc);
+uint32_t idalloc_allocate_prefer_pool(struct id_alloc *alloc,
+ struct id_alloc_pool **pool_ptr);
+uint32_t idalloc_reserve(struct id_alloc *alloc, uint32_t id);
+struct id_alloc *idalloc_new(const char *name);
+void idalloc_destroy(struct id_alloc *alloc);
+
+#endif
diff --git a/lib/lib_errors.h b/lib/lib_errors.h
index 3831116dd3..38c75f913e 100644
--- a/lib/lib_errors.h
+++ b/lib/lib_errors.h
@@ -72,6 +72,8 @@ enum lib_log_refs {
EC_LIB_SYSREPO_INIT,
EC_LIB_SYSREPO_DATA_CONVERT,
EC_LIB_LIBSYSREPO,
+ EC_LIB_ID_CONSISTENCY,
+ EC_LIB_ID_EXHAUST,
};
extern void lib_error_init(void);
diff --git a/lib/subdir.am b/lib/subdir.am
index 356796fbb1..c144c2c2e1 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -29,6 +29,7 @@ lib_libfrr_la_SOURCES = \
lib/graph.c \
lib/hash.c \
lib/hook.c \
+ lib/id_alloc.c \
lib/if.c \
lib/if_rmap.c \
lib/imsg-buffer.c \
@@ -147,6 +148,7 @@ pkginclude_HEADERS += \
lib/graph.h \
lib/hash.h \
lib/hook.h \
+ lib/id_alloc.h \
lib/if.h \
lib/if_rmap.h \
lib/imsg.h \
diff --git a/lib/vrf.c b/lib/vrf.c
index 498aef4580..046e468f20 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -1022,3 +1022,10 @@ int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
}
return ret;
}
+
+vrf_id_t vrf_generate_id(void)
+{
+ static int vrf_id_local;
+
+ return ++vrf_id_local;
+}
diff --git a/lib/vrf.h b/lib/vrf.h
index 04a8f70f5f..3bc88e610a 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -293,5 +293,6 @@ extern int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
extern void vrf_disable(struct vrf *vrf);
extern int vrf_enable(struct vrf *vrf);
extern void vrf_delete(struct vrf *vrf);
+extern vrf_id_t vrf_generate_id(void);
#endif /*_ZEBRA_VRF_H*/
diff --git a/lib/zclient.c b/lib/zclient.c
index 45a9f7be9e..b879326d71 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -58,8 +58,8 @@ int zclient_debug = 0;
struct zclient_options zclient_options_default = {.receive_notify = false};
/* Allocate zclient structure. */
-struct zclient *zclient_new_notify(struct thread_master *master,
- struct zclient_options *opt)
+struct zclient *zclient_new(struct thread_master *master,
+ struct zclient_options *opt)
{
struct zclient *zclient;
zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient));
@@ -199,7 +199,7 @@ void zclient_reset(struct zclient *zclient)
* @param zclient a pointer to zclient structure
* @return socket fd just to make sure that connection established
* @see zclient_init
- * @see zclient_new_notify
+ * @see zclient_new
*/
int zclient_socket_connect(struct zclient *zclient)
{
diff --git a/lib/zclient.h b/lib/zclient.h
index 97ebb0811c..07fe512a3c 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -422,23 +422,10 @@ struct zclient_options {
bool receive_notify;
};
-/* Prototypes of zebra client service functions. */
-extern struct zclient *zclient_new(struct thread_master *);
-
-/* clang-format off */
-#if CONFDATE > 20181101
-CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
-#endif
-/* clang-format on */
-
extern struct zclient_options zclient_options_default;
-extern struct zclient *zclient_new_notify(struct thread_master *m,
- struct zclient_options *opt);
-
-#define zclient_new(A) \
- zclient_new_notify((A), &zclient_options_default); \
- CPP_WARN("Please transition to using zclient_new_notify");
+extern struct zclient *zclient_new(struct thread_master *m,
+ struct zclient_options *opt);
extern void zclient_init(struct zclient *, int, unsigned short,
struct zebra_privs_t *privs);
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index e7b187f3b6..dae00bbcea 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -344,7 +344,7 @@ void nhrp_zebra_init(void)
zebra_rib[AFI_IP] = route_table_init();
zebra_rib[AFI_IP6] = route_table_init();
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient->zebra_connected = nhrp_zebra_connected;
zclient->interface_add = nhrp_interface_add;
zclient->interface_delete = nhrp_interface_delete;
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index bc52864313..30f0e9e774 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -567,9 +567,10 @@ void ospf6_area_config_write(struct vty *vty)
DEFUN (area_filter_list,
area_filter_list_cmd,
- "area A.B.C.D filter-list prefix WORD <in|out>",
+ "area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Filter networks between OSPF6 areas\n"
"Filter prefixes between OSPF6 areas\n"
"Name of an IPv6 prefix-list\n"
@@ -605,10 +606,11 @@ DEFUN (area_filter_list,
DEFUN (no_area_filter_list,
no_area_filter_list_cmd,
- "no area A.B.C.D filter-list prefix WORD <in|out>",
+ "no area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Filter networks between OSPF6 areas\n"
"Filter prefixes between OSPF6 areas\n"
"Name of an IPv6 prefix-list\n"
@@ -662,9 +664,10 @@ void ospf6_area_plist_update(struct prefix_list *plist, int add)
DEFUN (area_import_list,
area_import_list_cmd,
- "area A.B.C.D import-list NAME",
+ "area <A.B.C.D|(0-4294967295)> import-list NAME",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Set the filter for networks from other areas announced to the specified one\n"
"Name of the acess-list\n")
{
@@ -690,10 +693,11 @@ DEFUN (area_import_list,
DEFUN (no_area_import_list,
no_area_import_list_cmd,
- "no area A.B.C.D import-list NAME",
+ "no area <A.B.C.D|(0-4294967295)> import-list NAME",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Unset the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
@@ -715,9 +719,10 @@ DEFUN (no_area_import_list,
DEFUN (area_export_list,
area_export_list_cmd,
- "area A.B.C.D export-list NAME",
+ "area <A.B.C.D|(0-4294967295)> export-list NAME",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Set the filter for networks announced to other areas\n"
"Name of the acess-list\n")
{
@@ -743,10 +748,11 @@ DEFUN (area_export_list,
DEFUN (no_area_export_list,
no_area_export_list_cmd,
- "no area A.B.C.D export-list NAME",
+ "no area <A.B.C.D|(0-4294967295)> export-list NAME",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Unset the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index c968b35d90..5db9b529ef 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -586,7 +586,7 @@ static void ospf6_zebra_connected(struct zclient *zclient)
void ospf6_zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);
zclient->zebra_connected = ospf6_zebra_connected;
zclient->router_id_update = ospf6_router_id_update_zebra;
diff --git a/ospfd/ospf_memory.c b/ospfd/ospf_memory.c
index 1332104b0a..c4dc0136ed 100644
--- a/ospfd/ospf_memory.c
+++ b/ospfd/ospf_memory.c
@@ -52,6 +52,7 @@ DEFINE_MTYPE(OSPFD, OSPF_IF_INFO, "OSPF if info")
DEFINE_MTYPE(OSPFD, OSPF_IF_PARAMS, "OSPF if params")
DEFINE_MTYPE(OSPFD, OSPF_MESSAGE, "OSPF message")
DEFINE_MTYPE(OSPFD, OSPF_MPLS_TE, "OSPF MPLS parameters")
+DEFINE_MTYPE(OSPFD, OSPF_ROUTER_INFO, "OSPF Router Info parameters")
DEFINE_MTYPE(OSPFD, OSPF_PCE_PARAMS, "OSPF PCE parameters")
DEFINE_MTYPE(OSPFD, OSPF_EXT_PARAMS, "OSPF Extended parameters")
DEFINE_MTYPE(OSPFD, OSPF_SR_PARAMS, "OSPF Segment Routing parameters")
diff --git a/ospfd/ospf_memory.h b/ospfd/ospf_memory.h
index 50c6f33ecf..861de64c25 100644
--- a/ospfd/ospf_memory.h
+++ b/ospfd/ospf_memory.h
@@ -51,6 +51,7 @@ DECLARE_MTYPE(OSPF_IF_INFO)
DECLARE_MTYPE(OSPF_IF_PARAMS)
DECLARE_MTYPE(OSPF_MESSAGE)
DECLARE_MTYPE(OSPF_MPLS_TE)
+DECLARE_MTYPE(OSPF_ROUTER_INFO)
DECLARE_MTYPE(OSPF_PCE_PARAMS)
DECLARE_MTYPE(OSPF_SR_PARAMS)
DECLARE_MTYPE(OSPF_EXT_PARAMS)
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index bef16761f2..72f6dbe08e 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -59,60 +59,6 @@
#include "ospfd/ospf_ri.h"
#include "ospfd/ospf_errors.h"
-/* Store Router Information PCE TLV and SubTLV in network byte order. */
-struct ospf_pce_info {
- bool enabled;
- struct ri_tlv_pce pce_header;
- struct ri_pce_subtlv_address pce_address;
- struct ri_pce_subtlv_path_scope pce_scope;
- struct list *pce_domain;
- struct list *pce_neighbor;
- struct ri_pce_subtlv_cap_flag pce_cap_flag;
-};
-
-/*
- * Store Router Information Segment Routing TLV and SubTLV
- * in network byte order
- */
-struct ospf_ri_sr_info {
- bool enabled;
- /* Algorithms supported by the node */
- struct ri_sr_tlv_sr_algorithm algo;
- /*
- * Segment Routing Global Block i.e. label range
- * Only one range supported in this code
- */
- struct ri_sr_tlv_sid_label_range range;
- /* Maximum SID Depth supported by the node */
- struct ri_sr_tlv_node_msd msd;
-};
-
-/* Following structure are internal use only. */
-struct ospf_router_info {
- bool enabled;
-
- uint8_t registered;
- uint8_t scope;
-
-/* Flags to manage this router information. */
-#define RIFLG_LSA_ENGAGED 0x1
-#define RIFLG_LSA_FORCED_REFRESH 0x2
- uint32_t flags;
-
- /* area pointer if flooding is Type 10 Null if flooding is AS scope */
- struct ospf_area *area;
- struct in_addr area_id;
-
- /* Store Router Information Capabilities LSA */
- struct ri_tlv_router_cap router_cap;
-
- /* Store PCE capability LSA */
- struct ospf_pce_info pce_info;
-
- /* Store SR capability LSA */
- struct ospf_ri_sr_info sr_info;
-};
-
/*
* Global variable to manage Opaque-LSA/Router Information on this node.
* Note that all parameter values are stored in network byte order.
@@ -126,28 +72,29 @@ static struct ospf_router_info OspfRI;
static void ospf_router_info_ism_change(struct ospf_interface *oi,
int old_status);
-static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
- int old_status);
static void ospf_router_info_config_write_router(struct vty *vty);
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa);
static int ospf_router_info_lsa_originate(void *arg);
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
-static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode);
+static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
+ enum lsa_opcode opcode);
static void ospf_router_info_register_vty(void);
static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
+static void del_area_info(void *val);
static void del_pce_info(void *val);
int ospf_router_info_init(void)
{
- zlog_info("RI -> Initialize Router Information");
+ zlog_info("RI (%s): Initialize Router Information", __func__);
memset(&OspfRI, 0, sizeof(struct ospf_router_info));
OspfRI.enabled = false;
OspfRI.registered = 0;
OspfRI.scope = OSPF_OPAQUE_AS_LSA;
- OspfRI.area_id.s_addr = 0;
- OspfRI.flags = 0;
+ OspfRI.as_flags = RIFLG_LSA_INACTIVE;
+ OspfRI.area_info = list_new();
+ OspfRI.area_info->del = del_area_info;
/* Initialize pce domain and neighbor list */
OspfRI.pce_info.enabled = false;
@@ -171,13 +118,15 @@ static int ospf_router_info_register(uint8_t scope)
if (OspfRI.registered)
return rc;
- zlog_info("RI -> Register Router Information with scope %s(%d)",
+ zlog_info("RI (%s): Register Router Information with scope %s(%d)",
+ __func__,
scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
rc = ospf_register_opaque_functab(
scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
NULL, /* new interface */
NULL, /* del interface */
- ospf_router_info_ism_change, ospf_router_info_nsm_change,
+ ospf_router_info_ism_change,
+ NULL, /* NSM change */
ospf_router_info_config_write_router,
NULL, /* Config. write interface */
NULL, /* Config. write debug */
@@ -188,7 +137,7 @@ static int ospf_router_info_register(uint8_t scope)
if (rc != 0) {
flog_warn(
EC_OSPF_OPAQUE_REGISTRATION,
- "ospf_router_info_init: Failed to register functions");
+ "RI (%s): Failed to register functions", __func__);
return rc;
}
@@ -235,10 +184,14 @@ void ospf_router_info_finish(void)
OspfRI.enabled = false;
}
+static void del_area_info(void *val)
+{
+ XFREE(MTYPE_OSPF_ROUTER_INFO, val);
+}
+
static void del_pce_info(void *val)
{
XFREE(MTYPE_OSPF_PCE_PARAMS, val);
- return;
}
/* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
@@ -248,14 +201,26 @@ struct scope_info ospf_router_info_get_flooding_scope(void)
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
- flooding_scope.area_id.s_addr = 0;
+ flooding_scope.areas = NULL;
return flooding_scope;
}
flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
- flooding_scope.area_id.s_addr = OspfRI.area_id.s_addr;
+ flooding_scope.areas = OspfRI.area_info;
return flooding_scope;
}
+static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area)
+{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
+ if (ai->area == area)
+ return ai;
+
+ return NULL;
+}
+
/*------------------------------------------------------------------------*
* Followings are control functions for ROUTER INFORMATION parameters
*management.
@@ -525,6 +490,9 @@ static void initialize_params(struct ospf_router_info *ori)
{
uint32_t cap = 0;
struct ospf *top;
+ struct listnode *node, *nnode;
+ struct ospf_area *area;
+ struct ospf_ri_area_info *new;
/*
* Initialize default Router Information Capabilities.
@@ -536,14 +504,22 @@ static void initialize_params(struct ospf_router_info *ori)
/* If Area address is not null and exist, retrieve corresponding
* structure */
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- zlog_info("RI-> Initialize Router Info for %s scope within area %s",
- OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS",
- inet_ntoa(OspfRI.area_id));
+ zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
+ OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
- /* Try to get the Area context at this step. Do it latter if not
- * available */
- if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
- OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id);
+ /* Try to get available Area's context from ospf at this step.
+ * Do it latter if not available */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
+ zlog_debug("RI (%s): Add area %s to Router Information",
+ __func__, inet_ntoa(area->area_id));
+ new = XCALLOC(MTYPE_OSPF_ROUTER_INFO,
+ sizeof(struct ospf_ri_area_info));
+ new->area = area;
+ new->flags = RIFLG_LSA_INACTIVE;
+ listnode_add(OspfRI.area_info, new);
+ }
+ }
/*
* Initialize default PCE Information values
@@ -597,16 +573,31 @@ static int is_mandated_params_set(struct ospf_router_info ori)
*/
void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ /* First, check if Router Information is registered or not */
+ if (!OspfRI.registered)
+ ospf_router_info_register(OSPF_OPAQUE_AREA_LSA);
+
+ /* Verify that scope is AREA */
+ if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) {
+ zlog_err(
+ "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
+ __func__,
+ OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
+ return;
+ }
- /* First activate and initialize Router Information is necessary */
+ /* Then, activate and initialize Router Information if necessary */
if (!OspfRI.enabled) {
OspfRI.enabled = true;
initialize_params(&OspfRI);
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug("RI-> %s Routing Information for Segment Routing",
- enable ? "Enable" : "Disable");
+ zlog_debug("RI (%s): %s Routing Information for Segment Routing",
+ __func__, enable ? "Enable" : "Disable");
/* Unset or Set SR parameters */
if (!enable) {
@@ -626,10 +617,14 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
}
/* Refresh if already engaged or originate RI LSA */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
- else
- ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
+ else
+ ospf_router_info_lsa_schedule(ai,
+ REORIGINATE_THIS_LSA);
+
+ }
}
/*------------------------------------------------------------------------*
@@ -638,14 +633,22 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
static void ospf_router_info_ism_change(struct ospf_interface *oi,
int old_state)
{
- /* So far, nothing to do here. */
- return;
-}
-static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
- int old_state)
-{
- /* So far, nothing to do here. */
+ struct ospf_ri_area_info *ai;
+
+ /* Collect area information */
+ ai = lookup_by_area(oi->area);
+
+ /* Check if area is not yet registered */
+ if (ai != NULL)
+ return;
+
+ /* Add this new area to the list */
+ ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info));
+ ai->area = oi->area;
+ ai->flags = RIFLG_LSA_INACTIVE;
+ listnode_add(OspfRI.area_info, ai);
+
return;
}
@@ -723,7 +726,7 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
}
/* Create new opaque-LSA. */
-static struct ospf_lsa *ospf_router_info_lsa_new()
+static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
{
struct ospf *top;
struct stream *s;
@@ -768,8 +771,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
/* Now, create an OSPF LSA instance. */
new = ospf_lsa_new_and_data(length);
- new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
- scope, fulfill otherwise */
+ new->area = area;
if (new->area && new->area->ospf)
new->vrf_id = new->area->ospf->vrf_id;
@@ -783,36 +785,31 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
return new;
}
-static int ospf_router_info_lsa_originate1(void *arg)
+static int ospf_router_info_lsa_originate_as(void *arg)
{
struct ospf_lsa *new;
struct ospf *top;
- struct ospf_area *area;
int rc = -1;
vrf_id_t vrf_id = VRF_DEFAULT;
- /* First check if the area is known if flooding scope is Area */
+ /* Sanity Check */
if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
- area = (struct ospf_area *)arg;
- if (area->area_id.s_addr != OspfRI.area_id.s_addr) {
- zlog_debug(
- "RI -> This is not the Router Information Area. Stop processing");
- return rc;
- }
- OspfRI.area = area;
- if (area->ospf)
- vrf_id = area->ospf->vrf_id;
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): wrong flooding scope AREA instead of AS ?",
+ __func__);
+ return rc;
}
/* Create new Opaque-LSA/ROUTER INFORMATION instance. */
- new = ospf_router_info_lsa_new();
- new->vrf_id = vrf_id;
+ new = ospf_router_info_lsa_new(NULL);
+ new->vrf_id = VRF_DEFAULT;
+ top = (struct ospf *)arg;
- /* Get ospf info */
- top = ospf_lookup_by_vrf_id(vrf_id);
+ /* Check ospf info */
if (top == NULL) {
- zlog_debug("%s: ospf instance not found for vrf id %u",
- __PRETTY_FUNCTION__, vrf_id);
+ zlog_debug("RI (%s): ospf instance not found for vrf id %u",
+ __func__, vrf_id);
ospf_lsa_unlock(&new);
return rc;
}
@@ -821,22 +818,86 @@ static int ospf_router_info_lsa_originate1(void *arg)
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
flog_warn(
EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return rc;
+ }
+
+ /* Update new LSA origination count. */
+ top->lsa_originate_count++;
+
+ /* Flood new LSA through AREA or AS. */
+ SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
+ ospf_flood_through_as(top, NULL /*nbr */, new);
+
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
+ zlog_debug(
+ "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
+ new->data->type, inet_ntoa(new->data->id));
+ ospf_lsa_header_dump(new->data);
+ }
+
+ rc = 0;
+ return rc;
+}
+
+static int ospf_router_info_lsa_originate_area(void *arg)
+{
+ struct ospf_lsa *new;
+ struct ospf *top;
+ struct ospf_ri_area_info *ai = NULL;
+ int rc = -1;
+ vrf_id_t vrf_id = VRF_DEFAULT;
+
+ /* Sanity Check */
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): wrong flooding scope AS instead of AREA ?",
+ __func__);
+ return rc;
+ }
+
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ ai = lookup_by_area((struct ospf_area *)arg);
+ if (ai == NULL) {
+ zlog_debug(
+ "RI (%s): There is no context for this Router Information. Stop processing",
+ __func__);
+ return rc;
+ }
+ if (ai->area->ospf) {
+ vrf_id = ai->area->ospf->vrf_id;
+ top = ai->area->ospf;
+ } else {
+ top = ospf_lookup_by_vrf_id(vrf_id);
+ }
+ new = ospf_router_info_lsa_new(ai->area);
+ new->vrf_id = vrf_id;
+
+ /* Check ospf info */
+ if (top == NULL) {
+ zlog_debug("RI (%s): ospf instance not found for vrf id %u",
+ __func__, vrf_id);
ospf_lsa_unlock(&new);
return rc;
}
- /* Now this Router Info parameter entry has associated LSA. */
- SET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
+ /* Install this LSA into LSDB. */
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return rc;
+ }
/* Update new LSA origination count. */
top->lsa_originate_count++;
- /* Flood new LSA through AS. */
- if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
- ospf_flood_through_as(top, NULL /*nbr */, new);
- else
- ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new);
+ /* Flood new LSA through AREA or AS. */
+ SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ ospf_flood_through_area(ai->area, NULL /*nbr */, new);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug(
@@ -852,38 +913,62 @@ static int ospf_router_info_lsa_originate1(void *arg)
static int ospf_router_info_lsa_originate(void *arg)
{
+ struct ospf_ri_area_info *ai;
int rc = -1;
if (!OspfRI.enabled) {
- zlog_info(
- "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
+ zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
+ __func__);
rc = 0; /* This is not an error case. */
return rc;
}
/* Check if Router Information LSA is already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH)) {
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH);
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
+ && (CHECK_FLAG(OspfRI.as_flags,
+ RIFLG_LSA_FORCED_REFRESH))) {
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
+ ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
+ rc = 0;
+ return rc;
}
} else {
- if (!is_mandated_params_set(OspfRI))
+ ai = lookup_by_area((struct ospf_area *)arg);
+ if (ai == NULL) {
flog_warn(
EC_OSPF_LSA,
- "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
-
- /* Ok, let's try to originate an LSA */
- if (ospf_router_info_lsa_originate1(arg) != 0)
+ "RI (%s): Missing area information", __func__);
return rc;
+ }
+ if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
+ UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
+ ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
+ rc = 0;
+ return rc;
+ }
}
- rc = 0;
+ /* Router Information is not yet Engaged, check parameters */
+ if (!is_mandated_params_set(OspfRI))
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): lacks mandated ROUTER INFORMATION parameters",
+ __func__);
+
+ /* Ok, let's try to originate an LSA */
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
+ rc = ospf_router_info_lsa_originate_as(arg);
+ else
+ rc = ospf_router_info_lsa_originate_area(arg);
+
return rc;
}
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
{
+ struct ospf_ri_area_info *ai = NULL;
struct ospf_lsa *new = NULL;
struct ospf *top;
@@ -893,8 +978,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
* status change.
* It seems a slip among routers in the routing domain.
*/
- zlog_info(
- "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
+ zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
+ __func__);
lsa->data->ls_age =
htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
}
@@ -903,37 +988,66 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
flog_warn(
EC_OSPF_LSA,
- "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
+ "RI (%s): Unsupported Router Information ID",
+ __func__);
return NULL;
}
- /* If the lsa's age reached to MaxAge, start flushing procedure. */
- if (IS_LSA_MAXAGE(lsa)) {
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
- ospf_opaque_lsa_flush_schedule(lsa);
- return NULL;
- }
-
- /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
- new = ospf_router_info_lsa_new();
- new->data->ls_seqnum = lsa_seqnum_increment(lsa);
- new->vrf_id = lsa->vrf_id;
-
- /* Install this LSA into LSDB. */
- /* Given "lsa" will be freed in the next function. */
- top = ospf_lookup_by_vrf_id(lsa->vrf_id);
- if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
- flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
- ospf_lsa_unlock(&new);
- return new;
- }
-
- /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
- if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
+ /* Process LSA depending of the flooding scope */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ /* Get context AREA context */
+ ai = lookup_by_area(lsa->area);
+ if (ai == NULL) {
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): No associated Area", __func__);
+ return NULL;
+ }
+ /* Flush LSA, if the lsa's age reached to MaxAge. */
+ if (IS_LSA_MAXAGE(lsa)) {
+ UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ ospf_opaque_lsa_flush_schedule(lsa);
+ return NULL;
+ }
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ new = ospf_router_info_lsa_new(ai->area);
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->vrf_id = lsa->vrf_id;
+ /* Install this LSA into LSDB. */
+ /* Given "lsa" will be freed in the next function. */
+ top = ospf_lookup_by_vrf_id(lsa->vrf_id);
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return new;
+ }
+ /* Flood updated LSA through AREA */
+ ospf_flood_through_area(ai->area, NULL /*nbr */, new);
+
+ } else { /* AS Flooding scope */
+ /* Flush LSA, if the lsa's age reached to MaxAge. */
+ if (IS_LSA_MAXAGE(lsa)) {
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
+ ospf_opaque_lsa_flush_schedule(lsa);
+ return NULL;
+ }
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ new = ospf_router_info_lsa_new(NULL);
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->vrf_id = lsa->vrf_id;
+ /* Install this LSA into LSDB. */
+ /* Given "lsa" will be freed in the next function. */
+ top = ospf_lookup_by_vrf_id(lsa->vrf_id);
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return new;
+ }
+ /* Flood updated LSA through AS */
ospf_flood_through_as(top, NULL /*nbr */, new);
- else
- ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new);
+ }
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
@@ -946,7 +1060,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
return new;
}
-static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
+static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
+ enum lsa_opcode opcode)
{
struct ospf_lsa lsa;
struct lsa_header lsah;
@@ -956,28 +1071,44 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
memset(&lsa, 0, sizeof(lsa));
memset(&lsah, 0, sizeof(lsah));
- zlog_debug("RI-> LSA schedule %s%s%s",
+ zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
opcode == FLUSH_THIS_LSA ? "Flush" : "");
- /* Check LSA flags state coherence */
- if (!CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)
- && (opcode != REORIGINATE_THIS_LSA))
- return;
+ /* Check LSA flags state coherence and collect area information */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ if ((ai == NULL) || (ai->area == NULL)) {
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): Router Info is Area scope flooding but area is not set",
+ __func__);
+ return;
+ }
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)
- && (opcode == REORIGINATE_THIS_LSA))
- opcode = REFRESH_THIS_LSA;
+ if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
+ && (opcode != REORIGINATE_THIS_LSA))
+ return;
- top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
- OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id);
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
+ && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
+ lsa.area = ai->area;
+ top = ai->area->ospf;
+ } else {
+ if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
+ && (opcode != REORIGINATE_THIS_LSA))
+ return;
+
+ if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
+ && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
+ top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
+ lsa.area = NULL;
}
- lsa.area = OspfRI.area;
+
lsa.data = &lsah;
lsah.type = OspfRI.scope;
@@ -989,7 +1120,7 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
case REORIGINATE_THIS_LSA:
if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
ospf_opaque_lsa_reoriginate_schedule(
- (void *)OspfRI.area, OSPF_OPAQUE_AREA_LSA,
+ (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
else
ospf_opaque_lsa_reoriginate_schedule(
@@ -1000,7 +1131,10 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
ospf_opaque_lsa_refresh_schedule(&lsa);
break;
case FLUSH_THIS_LSA:
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
+ UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ else
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(&lsa);
break;
}
@@ -1014,7 +1148,7 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
/* Sanity Check */
if (lsa == NULL) {
- flog_warn(EC_OSPF_LSA, "OSPF-RI (%s): Abort! LSA is NULL",
+ flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
__func__);
return -1;
}
@@ -1356,8 +1490,7 @@ static void ospf_router_info_config_write_router(struct vty *vty)
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
vty_out(vty, " router-info as\n");
else
- vty_out(vty, " router-info area %s\n",
- inet_ntoa(OspfRI.area_id));
+ vty_out(vty, " router-info area\n");
if (OspfRI.pce_info.enabled) {
@@ -1405,43 +1538,53 @@ static void ospf_router_info_config_write_router(struct vty *vty)
/*------------------------------------------------------------------------*
* Followings are vty command functions.
*------------------------------------------------------------------------*/
+/* Simple wrapper schedule RI LSA action in function of the scope */
+static void ospf_router_info_schedule(enum lsa_opcode opcode)
+{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(NULL, opcode);
+ else if (opcode == REORIGINATE_THIS_LSA)
+ ospf_router_info_lsa_schedule(NULL, opcode);
+ } else {
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(ai, opcode);
+ }
+ }
+}
DEFUN (router_info,
router_info_area_cmd,
- "router-info <as|area A.B.C.D>",
+ "router-info <as|area [A.B.C.D]>",
OSPF_RI_STR
"Enable the Router Information functionality with AS flooding scope\n"
"Enable the Router Information functionality with Area flooding scope\n"
- "OSPF area ID in IP format\n")
+ "OSPF area ID in IP format (deprecated)\n")
{
- int idx_ipv4 = 2;
- char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL;
-
+ int idx_mode = 1;
uint8_t scope;
if (OspfRI.enabled)
return CMD_SUCCESS;
/* Check and get Area value if present */
- if (area) {
- if (!inet_aton(area, &OspfRI.area_id)) {
- vty_out(vty, "%% specified Area ID %s is invalid\n",
- area);
- return CMD_WARNING_CONFIG_FAILED;
- }
- scope = OSPF_OPAQUE_AREA_LSA;
- } else {
- OspfRI.area_id.s_addr = 0;
+ if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
scope = OSPF_OPAQUE_AS_LSA;
- }
+ else
+ scope = OSPF_OPAQUE_AREA_LSA;
/* First start to register Router Information callbacks */
- if ((ospf_router_info_register(scope)) != 0) {
+ if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
vty_out(vty,
"%% Unable to register Router Information callbacks.");
flog_err(
EC_OSPF_INIT_FAIL,
- "Unable to register Router Information callbacks. Abort!");
+ "RI (%s): Unable to register Router Information callbacks. Abort!",
+ __func__);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -1463,14 +1606,8 @@ DEFUN (router_info,
initialize_params(&OspfRI);
- /* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
- zlog_debug("RI-> Refresh LSA following configuration");
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
- } else {
- zlog_debug("RI-> Initial origination following configuration");
- ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
- }
+ /* Originate or Refresh RI LSA if already engaged */
+ ospf_router_info_schedule(REORIGINATE_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1488,8 +1625,7 @@ DEFUN (no_router_info,
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("RI-> Router Information: ON -> OFF");
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(FLUSH_THIS_LSA);
+ ospf_router_info_schedule(FLUSH_THIS_LSA);
OspfRI.enabled = false;
@@ -1533,8 +1669,7 @@ DEFUN (pce_address,
set_pce_address(value, pi);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
@@ -1552,8 +1687,7 @@ DEFUN (no_pce_address,
unset_param(&OspfRI.pce_info.pce_address);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1583,8 +1717,7 @@ DEFUN (pce_path_scope,
set_pce_path_scope(scope, pi);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
@@ -1602,8 +1735,7 @@ DEFUN (no_pce_path_scope,
unset_param(&OspfRI.pce_info.pce_address);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1641,8 +1773,7 @@ DEFUN (pce_domain,
set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1671,8 +1802,7 @@ DEFUN (no_pce_domain,
unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1711,8 +1841,7 @@ DEFUN (pce_neigbhor,
set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1741,8 +1870,7 @@ DEFUN (no_pce_neighbor,
unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1773,8 +1901,7 @@ DEFUN (pce_cap_flag,
set_pce_cap_flag(cap, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
@@ -1791,8 +1918,7 @@ DEFUN (no_pce_cap_flag,
unset_param(&OspfRI.pce_info.pce_cap_flag);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h
index 26bcc1b62a..84511ac5e7 100644
--- a/ospfd/ospf_ri.h
+++ b/ospfd/ospf_ri.h
@@ -170,7 +170,71 @@ struct ri_pce_subtlv_cap_flag {
/* Structure to share flooding scope info for Segment Routing */
struct scope_info {
uint8_t scope;
- struct in_addr area_id;
+ struct list *areas;
+};
+
+/* Flags to manage the Router Information LSA. */
+#define RIFLG_LSA_INACTIVE 0x0
+#define RIFLG_LSA_ENGAGED 0x1
+#define RIFLG_LSA_FORCED_REFRESH 0x2
+
+/* Store Router Information PCE TLV and SubTLV in network byte order. */
+struct ospf_pce_info {
+ bool enabled;
+ struct ri_tlv_pce pce_header;
+ struct ri_pce_subtlv_address pce_address;
+ struct ri_pce_subtlv_path_scope pce_scope;
+ struct list *pce_domain;
+ struct list *pce_neighbor;
+ struct ri_pce_subtlv_cap_flag pce_cap_flag;
+};
+
+/*
+ * Store Router Information Segment Routing TLV and SubTLV
+ * in network byte order
+ */
+struct ospf_ri_sr_info {
+ bool enabled;
+ /* Algorithms supported by the node */
+ struct ri_sr_tlv_sr_algorithm algo;
+ /*
+ * Segment Routing Global Block i.e. label range
+ * Only one range supported in this code
+ */
+ struct ri_sr_tlv_sid_label_range range;
+ /* Maximum SID Depth supported by the node */
+ struct ri_sr_tlv_node_msd msd;
+};
+
+/* Store area information to flood LSA per area */
+struct ospf_ri_area_info {
+
+ uint32_t flags;
+
+ /* area pointer if flooding is Type 10 Null if flooding is AS scope */
+ struct ospf_area *area;
+};
+
+/* Following structure are internal use only. */
+struct ospf_router_info {
+ bool enabled;
+
+ uint8_t registered;
+ uint8_t scope;
+ /* LSA flags are only used when scope is AS flooding */
+ uint32_t as_flags;
+
+ /* List of area info to flood RI LSA */
+ struct list *area_info;
+
+ /* Store Router Information Capabilities LSA */
+ struct ri_tlv_router_cap router_cap;
+
+ /* Store PCE capability LSA */
+ struct ospf_pce_info pce_info;
+
+ /* Store SR capability LSA */
+ struct ospf_ri_sr_info sr_info;
};
/* Prototypes. */
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 02698d770a..16347f1c5b 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -2398,16 +2398,16 @@ DEFUN (no_ospf_mpls_te_inter_as,
zlog_debug("MPLS-TE: Inter-AS support OFF");
if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
- OspfMplsTE.inter_as = Off;
/* Flush all Inter-AS LSA */
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
if (IS_INTER_AS(lp->type)
&& CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
- }
- /* Deregister the Callbacks for Inter-AS support */
- ospf_mpls_te_unregister();
+ /* Deregister the Callbacks for Inter-AS support */
+ ospf_mpls_te_unregister();
+ OspfMplsTE.inter_as = Off;
+ }
return CMD_SUCCESS;
}
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 52652821d6..67f5c7e890 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -245,8 +245,11 @@ DEFUN_NOSH (router_ospf,
return ret;
}
}
- ospf_interface_area_set(ospf, ifp);
- ospf->if_ospf_cli_count++;
+ if (!ospf_interface_area_is_already_set(ospf,
+ ifp)) {
+ ospf_interface_area_set(ospf, ifp);
+ ospf->if_ospf_cli_count++;
+ }
}
}
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index ed19ae4f31..c7bde55cd9 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1577,7 +1577,7 @@ static void ospf_zebra_connected(struct zclient *zclient)
void ospf_zebra_init(struct thread_master *master, unsigned short instance)
{
/* Allocate zebra structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);
zclient->zebra_connected = ospf_zebra_connected;
zclient->router_id_update = ospf_router_id_update_zebra;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index d5d1a7a605..a18e2de725 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1149,6 +1149,32 @@ void ospf_interface_area_unset(struct ospf *ospf, struct interface *ifp)
update_redistributed(ospf, 0); /* interfaces possibly removed */
}
+bool ospf_interface_area_is_already_set(struct ospf *ospf,
+ struct interface *ifp)
+{
+ struct route_node *rn_oi;
+
+ if (!ospf)
+ return false; /* Ospf not ready yet */
+
+ /* Find interfaces that may need to be removed. */
+ for (rn_oi = route_top(IF_OIFS(ifp)); rn_oi;
+ rn_oi = route_next(rn_oi)) {
+ struct ospf_interface *oi = rn_oi->info;
+
+ if (oi == NULL)
+ continue;
+
+ if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+ continue;
+ /* at least one route covered by interface
+ * that implies already done
+ */
+ return true;
+ }
+ return false;
+}
+
/* Check whether interface matches given network
* returns: 1, true. 0, false
*/
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index bc9c68d570..cbea033b73 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -561,6 +561,8 @@ extern void ospf_area_del_if(struct ospf_area *, struct ospf_interface *);
extern void ospf_interface_area_set(struct ospf *, struct interface *);
extern void ospf_interface_area_unset(struct ospf *, struct interface *);
+extern bool ospf_interface_area_is_already_set(struct ospf *ospf,
+ struct interface *ifp);
extern void ospf_route_map_init(void);
diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c
index b7391a171a..9db3edacb9 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -391,7 +391,7 @@ void pbr_zebra_init(void)
{
struct zclient_options opt = { .receive_notify = true };
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_PBR, 0, &pbr_privs);
zclient->zebra_connected = zebra_connected;
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 23001031e3..3dfc36a0c2 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -746,7 +746,7 @@ static void pim_zebra_connected(struct zclient *zclient)
void pim_zebra_init(void)
{
/* Socket for receiving updates from Zebra daemon */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient->zebra_connected = pim_zebra_connected;
zclient->router_id_update = pim_router_id_update_zebra;
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 0e74866117..6b45313081 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -120,7 +120,7 @@ void zclient_lookup_free(void)
void zclient_lookup_new(void)
{
- zlookup = zclient_new_notify(master, &zclient_options_default);
+ zlookup = zclient_new(master, &zclient_options_default);
if (!zlookup) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",
__PRETTY_FUNCTION__);
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index 2a56cd7b1b..20f543a258 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -211,7 +211,7 @@ static void rip_zebra_connected(struct zclient *zclient)
void rip_zclient_init(struct thread_master *master)
{
/* Set default value to the zebra client structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);
zclient->zebra_connected = rip_zebra_connected;
zclient->interface_add = rip_interface_add;
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index a8cc9ee128..f2b69c85a7 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -414,7 +414,7 @@ static void ripng_zebra_connected(struct zclient *zclient)
void zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
zclient->zebra_connected = ripng_zebra_connected;
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 286f320874..12bab73c5e 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -281,7 +281,7 @@ void sharp_zebra_init(void)
{
struct zclient_options opt = {.receive_notify = true};
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
zclient->zebra_connected = zebra_connected;
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index cd0330ed82..a5f0f74b00 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -497,6 +497,66 @@ void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
}
}
+/*
+ * This function enables static routes when an interface it relies
+ * on in a different vrf is coming up.
+ *
+ * stable -> The stable we are looking at.
+ * ifp -> interface coming up
+ * afi -> the afi in question
+ * safi -> the safi in question
+ */
+static void static_fixup_intf_nh(struct route_table *stable,
+ struct interface *ifp,
+ afi_t afi, safi_t safi)
+{
+ struct route_node *rn;
+ struct static_route *si;
+
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ for (si = rn->info; si; si = si->next) {
+ if (si->nh_vrf_id != ifp->vrf_id)
+ continue;
+
+ if (si->ifindex != ifp->ifindex)
+ continue;
+
+ static_install_route(rn, si, safi);
+ }
+ }
+}
+
+/*
+ * This function enables static routes that rely on an interface in
+ * a different vrf when that interface comes up.
+ */
+void static_install_intf_nh(struct interface *ifp)
+{
+ struct route_table *stable;
+ struct vrf *vrf;
+ afi_t afi;
+ safi_t safi;
+
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
+ struct static_vrf *svrf = vrf->info;
+
+ /* Not needed if same vrf since happens naturally */
+ if (vrf->vrf_id == ifp->vrf_id)
+ continue;
+
+ /* Install any static routes configured for this interface. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ stable = svrf->stable[afi][safi];
+ if (!stable)
+ continue;
+
+ static_fixup_intf_nh(stable, ifp, afi, safi);
+ }
+ }
+ }
+}
+
/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
void static_ifindex_update(struct interface *ifp, bool up)
{
diff --git a/staticd/static_routes.h b/staticd/static_routes.h
index 916ddcd7eb..6036bfe396 100644
--- a/staticd/static_routes.h
+++ b/staticd/static_routes.h
@@ -113,5 +113,7 @@ extern int static_delete_route(afi_t afi, safi_t safi, uint8_t type,
extern void static_cleanup_vrf_ids(struct static_vrf *disable_svrf);
+extern void static_install_intf_nh(struct interface *ifp);
+
extern void static_ifindex_update(struct interface *ifp, bool up);
#endif
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 4e168e142c..1e23f597b0 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -122,11 +122,17 @@ static int interface_state_up(int command, struct zclient *zclient,
ifp = zebra_interface_if_lookup(zclient->ibuf);
- if (ifp && if_is_vrf(ifp)) {
- struct static_vrf *svrf = static_vrf_lookup_by_id(vrf_id);
+ if (ifp) {
+ if (if_is_vrf(ifp)) {
+ struct static_vrf *svrf =
+ static_vrf_lookup_by_id(vrf_id);
- static_fixup_vrf_ids(svrf);
- static_config_install_delayed_routes(svrf);
+ static_fixup_vrf_ids(svrf);
+ static_config_install_delayed_routes(svrf);
+ }
+
+ /* Install any static reliant on this interface coming up */
+ static_install_intf_nh(ifp);
}
return 0;
@@ -465,7 +471,7 @@ void static_zebra_init(void)
{
struct zclient_options opt = { .receive_notify = true };
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
zclient->zebra_capabilities = static_zebra_capabilities;
diff --git a/tests/.gitignore b/tests/.gitignore
index 37cd245de0..a6202786be 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -12,6 +12,7 @@
/bgpd/test_peer_attr
/isisd/test_fuzz_isis_tlv
/isisd/test_fuzz_isis_tlv_tests.h
+/isisd/test_isis_lspdb
/isisd/test_isis_vertex_queue
/lib/cli/test_cli
/lib/cli/test_cli_clippy.c
@@ -19,23 +20,24 @@
/lib/cli/test_commands_defun.c
/lib/test_buffer
/lib/test_checksum
+/lib/test_graph
/lib/test_heavy
/lib/test_heavy_thread
/lib/test_heavy_wq
+/lib/test_idalloc
/lib/test_memory
/lib/test_nexthop_iter
/lib/test_privs
/lib/test_ringbuf
-/lib/test_srcdest_table
/lib/test_segv
/lib/test_sig
+/lib/test_srcdest_table
/lib/test_stream
/lib/test_table
/lib/test_timer_correctness
/lib/test_timer_performance
/lib/test_ttable
-/lib/test_zmq
/lib/test_zlog
-/lib/test_graph
+/lib/test_zmq
/ospf6d/test_lsdb
/ospf6d/test_lsdb_clippy.c
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
index 171b1aa22f..73243dcacf 100644
--- a/tests/bgpd/test_bgp_table.c
+++ b/tests/bgpd/test_bgp_table.c
@@ -28,6 +28,8 @@
#include "bgpd/bgp_table.h"
#include "linklist.h"
+/* Satisfy link requirements from including bgpd.h */
+struct zebra_privs_t bgpd_privs = {0};
/*
* test_node_t
*
diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c
index f0797827ce..04fbda42eb 100644
--- a/tests/bgpd/test_mpath.c
+++ b/tests/bgpd/test_mpath.c
@@ -379,7 +379,7 @@ static int global_test_init(void)
{
qobj_init();
master = thread_master_create(NULL);
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
bgp_master_init(master);
vrf_init(NULL, NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 2f464d7217..2fbc686e1e 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -254,6 +254,8 @@ TEST_STR_ATTR_HANDLER_DECL(password, password, "FRR-Peer", "FRR-Group");
TEST_ATTR_HANDLER_DECL(local_as, change_local_as, 1, 2);
TEST_ATTR_HANDLER_DECL(timers_1, keepalive, 10, 20);
TEST_ATTR_HANDLER_DECL(timers_2, holdtime, 30, 60);
+TEST_ATTR_HANDLER_DECL(addpath_types, addpath_type[pa->afi][pa->safi],
+ BGP_ADDPATH_ALL, BGP_ADDPATH_BEST_PER_AS);
TEST_SU_ATTR_HANDLER_DECL(update_source_su, update_source, "255.255.255.1",
"255.255.255.2");
TEST_STR_ATTR_HANDLER_DECL(update_source_if, update_if, "IF-PEER", "IF-GROUP");
@@ -414,12 +416,11 @@ static struct test_peer_attr test_peer_attrs[] = {
/* Address Family Attributes */
{
- .cmd = "addpath-tx-all-paths",
- .u.flag = PEER_FLAG_ADDPATH_TX_ALL_PATHS,
- },
- {
- .cmd = "addpath-tx-bestpath-per-AS",
- .u.flag = PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS,
+ .cmd = "addpath",
+ .peer_cmd = "addpath-tx-all-paths",
+ .group_cmd = "addpath-tx-bestpath-per-AS",
+ .type = PEER_AT_AF_CUSTOM,
+ .handlers[0] = TEST_HANDLER(addpath_types),
},
{
.cmd = "allowas-in",
diff --git a/tests/bgpd/test_peer_attr.py b/tests/bgpd/test_peer_attr.py
index 7a4dd2b04a..bafd131b78 100644
--- a/tests/bgpd/test_peer_attr.py
+++ b/tests/bgpd/test_peer_attr.py
@@ -26,14 +26,10 @@ TestFlag.okfail('peer\\timers')
TestFlag.okfail('peer\\timers connect')
TestFlag.okfail('peer\\update-source')
TestFlag.okfail('peer\\update-source')
-TestFlag.okfail('peer\\ipv4-unicast\\addpath-tx-all-paths')
-TestFlag.okfail('peer\\ipv4-multicast\\addpath-tx-all-paths')
-TestFlag.okfail('peer\\ipv6-unicast\\addpath-tx-all-paths')
-TestFlag.okfail('peer\\ipv6-multicast\\addpath-tx-all-paths')
-TestFlag.okfail('peer\\ipv4-unicast\\addpath-tx-bestpath-per-AS')
-TestFlag.okfail('peer\\ipv4-multicast\\addpath-tx-bestpath-per-AS')
-TestFlag.okfail('peer\\ipv6-unicast\\addpath-tx-bestpath-per-AS')
-TestFlag.okfail('peer\\ipv6-multicast\\addpath-tx-bestpath-per-AS')
+TestFlag.okfail('peer\\ipv4-unicast\\addpath')
+TestFlag.okfail('peer\\ipv4-multicast\\addpath')
+TestFlag.okfail('peer\\ipv6-unicast\\addpath')
+TestFlag.okfail('peer\\ipv6-multicast\\addpath')
TestFlag.okfail('peer\\ipv4-unicast\\allowas-in')
TestFlag.okfail('peer\\ipv4-multicast\\allowas-in')
TestFlag.okfail('peer\\ipv6-unicast\\allowas-in')
diff --git a/tests/isisd/test_isis_lspdb.c b/tests/isisd/test_isis_lspdb.c
new file mode 100644
index 0000000000..b9c6f2bbb2
--- /dev/null
+++ b/tests/isisd/test_isis_lspdb.c
@@ -0,0 +1,87 @@
+#include <zebra.h>
+
+#include "isisd/isis_lsp.c"
+
+struct thread_master *master;
+
+int isis_sock_init(struct isis_circuit *circuit);
+int isis_sock_init(struct isis_circuit *circuit)
+{
+ return 0;
+}
+
+struct zebra_privs_t isisd_privs;
+
+static void test_lsp_build_list_nonzero_ht(void)
+{
+ uint8_t lsp_id1[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
+ };
+ uint8_t lsp_id_end[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00
+ };
+ uint8_t lsp_id2[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
+ };
+
+ struct isis_area *area = calloc(sizeof(*area), 1);
+
+ area->lsp_mtu = 1500;
+
+ dict_t *lspdb = lsp_db_init();
+
+ struct isis_lsp *lsp1 = lsp_new(area, lsp_id1, 6000, 0, 0, 0, NULL,
+ ISIS_LEVEL2);
+
+ lsp_insert(lsp1, lspdb);
+
+ struct isis_lsp *lsp2 = lsp_new(area, lsp_id2, 6000, 0, 0, 0, NULL,
+ ISIS_LEVEL2);
+
+ lsp_insert(lsp2, lspdb);
+
+ struct list *list = list_new();
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 1);
+ assert(listgetdata(listhead(list)) == lsp1);
+ list_delete_all_node(list);
+
+ lsp_id_end[5] = 0x03;
+ lsp_id_end[6] = 0x00;
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 2);
+ assert(listgetdata(listhead(list)) == lsp1);
+ assert(listgetdata(listtail(list)) == lsp2);
+ list_delete_all_node(list);
+
+ memcpy(lsp_id1, lsp_id2, sizeof(lsp_id1));
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 1);
+ assert(listgetdata(listhead(list)) == lsp2);
+ list_delete_all_node(list);
+
+ lsp_id1[5] = 0x03;
+ lsp_id_end[5] = 0x04;
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 0);
+ list_delete_all_node(list);
+
+ lsp_id1[5] = 0x00;
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 2);
+ assert(listgetdata(listhead(list)) == lsp1);
+ assert(listgetdata(listtail(list)) == lsp2);
+ list_delete_all_node(list);
+}
+
+int main(int argc, char **argv)
+{
+ isis = calloc(sizeof(*isis), 1);
+ test_lsp_build_list_nonzero_ht();
+ return 0;
+}
diff --git a/tests/isisd/test_isis_lspdb.py b/tests/isisd/test_isis_lspdb.py
new file mode 100644
index 0000000000..cd0b5345c7
--- /dev/null
+++ b/tests/isisd/test_isis_lspdb.py
@@ -0,0 +1,6 @@
+import frrtest
+
+class TestIsisLSPDB(frrtest.TestMultiOut):
+ program = './test_isis_lspdb'
+
+TestIsisLSPDB.exit_cleanly()
diff --git a/tests/lib/test_idalloc.c b/tests/lib/test_idalloc.c
new file mode 100644
index 0000000000..3053c1c074
--- /dev/null
+++ b/tests/lib/test_idalloc.c
@@ -0,0 +1,193 @@
+#include "id_alloc.h"
+
+#include <inttypes.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+#define IDS_PER_PAGE (1<<(IDALLOC_OFFSET_BITS + IDALLOC_WORD_BITS))
+char allocated_markers[IDS_PER_PAGE*3];
+
+int main(int argc, char **argv)
+{
+ int i, val;
+ uint32_t pg;
+ struct id_alloc *a;
+
+ /* 1. Rattle test, shake it a little and make sure it doesn't make any
+ * noise :)
+ */
+ a = idalloc_new("Rattle test");
+ for (i = 0; i < 1000000; i++)
+ assert(idalloc_allocate(a) != 0);
+
+ idalloc_destroy(a);
+
+ /* 2. Reserve a few low IDs, make sure they are skipped by normal
+ * allocation.
+ */
+ a = idalloc_new("Low Reservations");
+ assert(idalloc_reserve(a, 1) == 1);
+ assert(idalloc_reserve(a, 3) == 3);
+ assert(idalloc_reserve(a, 5) == 5);
+ for (i = 0; i < 100; i++) {
+ val = idalloc_allocate(a);
+ assert(val != 1 && val != 3 && val != 5);
+ }
+ idalloc_destroy(a);
+
+ /* 3. Single page testing. Check that IDs are kept unique, and all IDs
+ * in the existing page are allocated before a new page is added.
+ */
+ memset(allocated_markers, 0, sizeof(allocated_markers));
+ allocated_markers[IDALLOC_INVALID] = 1;
+
+ a = idalloc_new("Single Page");
+
+ /* reserve the rest of the first page */
+ for (i = 0; i < IDS_PER_PAGE - 1; i++) {
+ val = idalloc_allocate(a);
+ assert(val < IDS_PER_PAGE);
+ assert(allocated_markers[val] == 0);
+ assert(a->capacity == IDS_PER_PAGE);
+ allocated_markers[val] = 1;
+ }
+ /* Check that the count is right */
+ assert(a->allocated == IDS_PER_PAGE);
+
+ /* Free some IDs out of the middle. */
+ idalloc_free(a, 300);
+ allocated_markers[300] = 0;
+ idalloc_free(a, 400);
+ allocated_markers[400] = 0;
+ idalloc_free(a, 500);
+ allocated_markers[500] = 0;
+
+ assert(a->allocated == IDS_PER_PAGE-3);
+
+ /* Allocate the three IDs back and make sure they are pulled from the
+ * set just freed
+ */
+ for (i = 0; i < 3; i++) {
+ val = idalloc_allocate(a);
+ assert(val < IDS_PER_PAGE);
+ assert(allocated_markers[val] == 0);
+ assert(a->capacity == IDS_PER_PAGE);
+ allocated_markers[val] = 1;
+ }
+ idalloc_destroy(a);
+
+ /* 4. Multi-page testing. */
+ memset(allocated_markers, 0, sizeof(allocated_markers));
+ allocated_markers[IDALLOC_INVALID] = 1;
+
+ a = idalloc_new("Multi-page");
+
+ /* reserve the rest of the first page and all of the second and third */
+ for (i = 0; i < 3 * IDS_PER_PAGE - 1; i++) {
+ val = idalloc_allocate(a);
+ assert(val < 3*IDS_PER_PAGE);
+ assert(allocated_markers[val] == 0);
+ allocated_markers[val] = 1;
+ }
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE);
+
+ /* Free two IDs from each page. */
+ for (i = 0; i < 3; i++) {
+ idalloc_free(a, 7 + i*IDS_PER_PAGE);
+ allocated_markers[7 + i*IDS_PER_PAGE] = 0;
+
+ idalloc_free(a, 4 + i*IDS_PER_PAGE);
+ allocated_markers[4 + i*IDS_PER_PAGE] = 0;
+ }
+
+ assert(a->allocated == 3*IDS_PER_PAGE - 6);
+
+ /* Allocate the six IDs back and make sure they are pulled from the set
+ * just freed.
+ */
+ for (i = 0; i < 6; i++) {
+ val = idalloc_allocate(a);
+ assert(val < 3*IDS_PER_PAGE);
+ assert(allocated_markers[val] == 0);
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ allocated_markers[val] = 1;
+ }
+
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE);
+
+ /* Walk each allocated ID. Free it, then re-allocate it back. */
+ for (i = 1; i < 3 * IDS_PER_PAGE - 1; i++) {
+ idalloc_free(a, i);
+ val = idalloc_allocate(a);
+ assert(val == i);
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE);
+ }
+ idalloc_destroy(a);
+
+ /* 5. Weird Reservations
+ * idalloc_reserve exists primarily to black out low numbered IDs that
+ * are reserved for special cases. However, we will test it for more
+ * complex use cases to avoid unpleasant surprises.
+ */
+
+ memset(allocated_markers, 0, sizeof(allocated_markers));
+ allocated_markers[IDALLOC_INVALID] = 1;
+
+ a = idalloc_new("Weird Reservations");
+
+ /* Start with 3 pages fully allocated. */
+ for (i = 0; i < 3 * IDS_PER_PAGE - 1; i++) {
+ val = idalloc_allocate(a);
+ assert(val < 3*IDS_PER_PAGE);
+ assert(allocated_markers[val] == 0);
+ allocated_markers[val] = 1;
+ }
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE);
+
+ /* Free a bit out of each of the three pages. Then reserve one of the
+ * three freed IDs. Finally, allocate the other two freed IDs. Do this
+ * each of three ways. (Reserve out of the first, seconds then third
+ * page.)
+ * The intent here is to exercise the rare cases on reserve_bit's
+ * linked-list removal in the case that it is not removing the first
+ * page with a free bit in its list of pages with free bits.
+ */
+
+ for (pg = 0; pg < 3; pg++) {
+ /* free a bit out of each of the three pages */
+ for (i = 0; i < 3; i++) {
+ idalloc_free(a, i*IDS_PER_PAGE + 17);
+ allocated_markers[i*IDS_PER_PAGE + 17] = 0;
+ }
+
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE-3);
+
+ /* Reserve one of the freed IDs */
+ assert(idalloc_reserve(a, pg*IDS_PER_PAGE + 17) ==
+ pg*IDS_PER_PAGE + 17);
+ allocated_markers[pg*IDS_PER_PAGE + 17] = 1;
+
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE-2);
+
+ /* Allocate the other two back */
+ for (i = 0; i < 2; i++) {
+ val = idalloc_allocate(a);
+ assert(val < 3*IDS_PER_PAGE);
+ assert(allocated_markers[val] == 0);
+ allocated_markers[val] = 1;
+ }
+ assert(a->capacity == 3*IDS_PER_PAGE);
+ assert(a->allocated == 3*IDS_PER_PAGE);
+ }
+ idalloc_destroy(a);
+
+ puts("ID Allocator test successful.\n");
+ return 0;
+}
diff --git a/tests/lib/test_idalloc.py b/tests/lib/test_idalloc.py
new file mode 100644
index 0000000000..22de082be4
--- /dev/null
+++ b/tests/lib/test_idalloc.py
@@ -0,0 +1,6 @@
+import frrtest
+
+class TestIDAlloc(frrtest.TestMultiOut):
+ program = './test_idalloc'
+
+TestIDAlloc.onesimple('ID Allocator test successful.')
diff --git a/tests/subdir.am b/tests/subdir.am
index a4a754b088..6b52c90bc0 100644
--- a/tests/subdir.am
+++ b/tests/subdir.am
@@ -24,6 +24,7 @@ TESTS_ISISD =
else
TESTS_ISISD = \
tests/isisd/test_fuzz_isis_tlv \
+ tests/isisd/test_isis_lspdb \
tests/isisd/test_isis_vertex_queue \
# end
endif
@@ -50,6 +51,7 @@ check_PROGRAMS = \
tests/lib/test_heavy_thread \
tests/lib/test_heavy_wq \
tests/lib/test_heavy \
+ tests/lib/test_idalloc \
tests/lib/test_memory \
tests/lib/test_nexthop_iter \
tests/lib/test_privs \
@@ -155,6 +157,10 @@ tests_isisd_test_fuzz_isis_tlv_CPPFLAGS = $(TESTS_CPPFLAGS) -I$(top_builddir)/te
tests_isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv.c
nodist_tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv_tests.h
+tests_isisd_test_isis_lspdb_CFLAGS = $(TESTS_CFLAGS)
+tests_isisd_test_isis_lspdb_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_isisd_test_isis_lspdb_LDADD = $(ISISD_TEST_LDADD)
+tests_isisd_test_isis_lspdb_SOURCES = tests/isisd/test_isis_lspdb.c
tests_isisd_test_isis_vertex_queue_CFLAGS = $(TESTS_CFLAGS)
tests_isisd_test_isis_vertex_queue_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
@@ -193,6 +199,9 @@ tests_lib_test_heavy_wq_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_heavy_wq_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_heavy_wq_LDADD = $(ALL_TESTS_LDADD) -lm
tests_lib_test_heavy_wq_SOURCES = tests/lib/test_heavy_wq.c tests/helpers/c/main.c
+tests_lib_test_idalloc_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_idalloc_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_idalloc_SOURCES = tests/lib/test_idalloc.c
tests_lib_test_memory_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_memory_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_memory_LDADD = $(ALL_TESTS_LDADD)
@@ -267,6 +276,7 @@ EXTRA_DIST += \
tests/helpers/python/frrtest.py \
tests/isisd/test_fuzz_isis_tlv.py \
tests/isisd/test_fuzz_isis_tlv_tests.h.gz \
+ tests/isisd/test_isis_lspdb.py \
tests/isisd/test_isis_vertex_queue.py \
tests/lib/cli/test_commands.in \
tests/lib/cli/test_commands.py \
diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c
index 9d1c05436c..e71e680fad 100644
--- a/tests/test_lblmgr.c
+++ b/tests/test_lblmgr.c
@@ -119,7 +119,7 @@ void init_zclient(struct thread_master *master, char *lm_zserv_path)
{
frr_zclient_addr(&zclient_addr, &zclient_addr_len, lm_zserv_path);
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
/* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */
zclient->sock = -1;
zclient->redist_default = ZEBRA_ROUTE_LDP;
diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf
index bd0e370d1e..94221301eb 100644
--- a/tools/etc/frr/daemons.conf
+++ b/tools/etc/frr/daemons.conf
@@ -24,7 +24,8 @@ fabricd_options=" --daemon -A 127.0.0.1"
# The list of daemons to watch is automatically generated by the init script.
watchfrr_enable=yes
-watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB)
+
+watchfrr_options=(-d -r /usr/lib/frr/frrbBrestartbB%s -s /usr/lib/frr/frrbBstartbB%s -k /usr/lib/frr/frrbBstopbB%s -b bB)
# If valgrind_enable is 'yes' the frr daemons will be started via valgrind.
# The use case for doing so is tracking down memory leaks, etc in frr.
diff --git a/tools/frr.in b/tools/frr.in
index ee8dc883dc..ec383bc5a0 100755
--- a/tools/frr.in
+++ b/tools/frr.in
@@ -127,6 +127,7 @@ start()
echo -n " $1"
fi
+
${SSD} \
--start \
--pidfile=`pidfile $1` \
@@ -148,7 +149,6 @@ start()
-- \
`eval echo "$""$1""_options"` -n "$2"
else
- echo -n " $1"
if ! check_daemon $1; then
echo -n " (binary does not exist)"
return;
@@ -210,7 +210,6 @@ stop()
# Now we have to wait until $DAEMON has _really_ stopped.
#
if test -n "$PID" && kill -0 $PID 2>/dev/null; then
- echo -n " (waiting) ."
cnt=0
while kill -0 $PID 2>/dev/null; do
cnt=`expr $cnt + 1`
@@ -220,10 +219,8 @@ stop()
break
fi
sleep 2
- echo -n "."
done
fi
- echo -n " $inst"
rm -f `pidfile $inst`
rm -f `vtyfile $inst`
@@ -305,7 +302,6 @@ start_watchfrr()
# Start if at least one daemon is activated.
if [ $found_one -eq 1 ]; then
- echo -n "Starting Frr monitor daemon:"
start watchfrr
echo "."
fi
@@ -408,8 +404,6 @@ start_prio()
wanted_prio=$1
daemon_list=${daemon:-$DAEMONS}
- echo -n "Starting Frr daemons (prio:$wanted_prio):"
-
for prio_i in `seq 1 $wanted_prio`; do
for daemon_name in $daemon_list; do
eval daemon_prio=\$${daemon_name}
@@ -447,7 +441,6 @@ start_prio()
eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
for pidfile in $file_list_suffix.pid; do
${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
- echo -n "."
rm -rf "$pidfile"
done
for vtyfile in $file_list_suffix.vty; do
@@ -459,7 +452,6 @@ start_prio()
fi
done
done
- echo "."
}
check_status()
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 8e459160c6..f4bd193569 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -243,7 +243,8 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt)
}
}
-static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
+static void netlink_determine_zebra_iftype(const char *kind,
+ zebra_iftype_t *zif_type)
{
*zif_type = ZEBRA_IF_OTHER;
@@ -262,6 +263,10 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
*zif_type = ZEBRA_IF_MACVLAN;
else if (strcmp(kind, "veth") == 0)
*zif_type = ZEBRA_IF_VETH;
+ else if (strcmp(kind, "bond") == 0)
+ *zif_type = ZEBRA_IF_BOND;
+ else if (strcmp(kind, "bond_slave") == 0)
+ *zif_type = ZEBRA_IF_BOND_SLAVE;
}
#define parse_rtattr_nested(tb, max, rta) \
@@ -585,6 +590,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
+ ifindex_t bond_ifindex = IFINDEX_INTERNAL;
struct zebra_if *zif;
zns = zebra_ns_lookup(ns_id);
@@ -635,7 +641,10 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (linkinfo[IFLA_INFO_SLAVE_KIND])
slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
- netlink_determine_zebra_iftype(kind, &zif_type);
+ if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0)
+ netlink_determine_zebra_iftype("bond_slave", &zif_type);
+ else
+ netlink_determine_zebra_iftype(kind, &zif_type);
}
/* If VRF, create the VRF structure itself. */
@@ -653,6 +662,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
+ zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+ bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
@@ -700,6 +712,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
return 0;
}
@@ -1081,6 +1095,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zebra_iftype_t zif_type = ZEBRA_IF_OTHER;
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
+ ifindex_t bond_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
@@ -1180,6 +1195,11 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ } else if (slave_kind
+ && (strcmp(slave_kind, "bond") == 0)) {
+ zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+ bond_ifindex =
+ *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
@@ -1239,6 +1259,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
} else if (ifp->vrf_id != vrf_id) {
/* VRF change for an interface. */
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1250,7 +1272,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if_handle_vrf_change(ifp, vrf_id);
} else {
- int was_bridge_slave;
+ bool was_bridge_slave, was_bond_slave;
/* Interface update. */
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1273,6 +1295,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* Update interface type - NOTE: Only slave_type can
* change. */
was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
+ was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
netlink_interface_update_hw_addr(tb, ifp);
@@ -1312,6 +1335,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
}
} else {
/* Delete interface notification from kernel */
diff --git a/zebra/interface.c b/zebra/interface.c
index afb08f7012..ac765e7846 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -806,19 +806,6 @@ static void ipv6_ll_address_to_mac(struct in6_addr *address, uint8_t *mac)
mac[5] = address->s6_addr[15];
}
-static bool mac_is_same(char *mac1, char *mac2)
-{
- if (mac1[0] == mac2[0] &&
- mac1[1] == mac2[1] &&
- mac1[2] == mac2[2] &&
- mac1[3] == mac2[3] &&
- mac1[4] == mac2[4] &&
- mac1[5] == mac2[5])
- return true;
- else
- return false;
-}
-
void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
char mac[6],
struct in6_addr *address,
@@ -835,19 +822,23 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
ns_id = zvrf->zns->ns_id;
/*
- * Remove existed arp record for the interface as netlink
- * protocol does not have update message types
- *
- * supported message types are RTM_NEWNEIGH and RTM_DELNEIGH
+ * Remove and re-add any existing neighbor entry for this address,
+ * since Netlink doesn't currently offer update message types.
*/
- if (!mac_is_same(zif->neigh_mac, mac)) {
- kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr,
- mac, 6, ns_id);
+ kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
- /* Add arp record */
- kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr,
- mac, 6, ns_id);
- }
+ /* Add new neighbor entry.
+ *
+ * We force installation even if current neighbor entry is the same.
+ * Since this function is used to refresh our MAC entries after an
+ * interface flap, if we don't force in our custom entries with their
+ * state set to PERMANENT or REACHABLE then the kernel will attempt to
+ * resolve our leftover entries, fail, mark them unreachable and then
+ * they'll be useless to us.
+ */
+ if (add)
+ kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6,
+ ns_id);
memcpy(&zif->neigh_mac[0], &mac[0], 6);
@@ -1150,6 +1141,15 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
return "VETH";
break;
+ case ZEBRA_IF_BOND:
+ return "bond";
+
+ case ZEBRA_IF_BOND_SLAVE:
+ return "bond_slave";
+
+ case ZEBRA_IF_MACVLAN:
+ return "macvlan";
+
default:
return "Unknown";
break;
@@ -1279,6 +1279,15 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
br_slave->bridge_ifindex);
}
+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
+ struct zebra_l2info_bondslave *bond_slave;
+
+ bond_slave = &zebra_if->bondslave_info;
+ if (bond_slave->bond_ifindex != IFINDEX_INTERNAL)
+ vty_out(vty, " Master (bond) ifindex %u\n",
+ bond_slave->bond_ifindex);
+ }
+
if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
vty_out(vty, " Link ifindex %u", zebra_if->link_ifindex);
if (zebra_if->link)
@@ -2749,7 +2758,7 @@ DEFUN (no_ip_address_label,
static int ipv6_address_install(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
- const char *label, int secondary)
+ const char *label)
{
struct zebra_if *if_data;
struct prefix_ipv6 cp;
@@ -2780,10 +2789,6 @@ static int ipv6_address_install(struct vty *vty, struct interface *ifp,
*p = cp;
ifc->address = (struct prefix *)p;
- /* Secondary. */
- if (secondary)
- SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
-
/* Label. */
if (label)
ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
@@ -2839,7 +2844,7 @@ int ipv6_address_configured(struct interface *ifp)
static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
- const char *label, int secondry)
+ const char *label)
{
struct prefix_ipv6 cp;
struct connected *ifc;
@@ -2897,7 +2902,7 @@ DEFUN (ipv6_address,
int idx_ipv6_prefixlen = 2;
VTY_DECLVAR_CONTEXT(interface, ifp);
return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
- NULL, NULL, 0);
+ NULL, NULL);
}
DEFUN (no_ipv6_address,
@@ -2911,7 +2916,7 @@ DEFUN (no_ipv6_address,
int idx_ipv6_prefixlen = 3;
VTY_DECLVAR_CONTEXT(interface, ifp);
return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
- NULL, NULL, 0);
+ NULL, NULL);
}
static int link_params_config_write(struct vty *vty, struct interface *ifp)
diff --git a/zebra/interface.h b/zebra/interface.h
index e4c05e8dc4..01dd697772 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -1,3 +1,4 @@
+
/* Interface function header.
* Copyright (C) 1999 Kunihiro Ishiguro
*
@@ -192,6 +193,8 @@ typedef enum {
ZEBRA_IF_VLAN, /* VLAN sub-interface */
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
ZEBRA_IF_VETH, /* VETH interface*/
+ ZEBRA_IF_BOND, /* Bond */
+ ZEBRA_IF_BOND_SLAVE, /* Bond */
} zebra_iftype_t;
/* Zebra "slave" interface type */
@@ -199,6 +202,7 @@ typedef enum {
ZEBRA_IF_SLAVE_NONE, /* Not a slave */
ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */
ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */
+ ZEBRA_IF_SLAVE_BOND, /* Bond member */
ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */
} zebra_slave_iftype_t;
@@ -268,6 +272,8 @@ struct zebra_if {
*/
struct zebra_l2info_brslave brslave_info;
+ struct zebra_l2info_bondslave bondslave_info;
+
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
@@ -324,6 +330,10 @@ static inline void zebra_if_set_ziftype(struct interface *ifp,
#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF)
+#define IS_ZEBRA_IF_BOND_SLAVE(ifp) \
+ (((struct zebra_if *)(ifp->info))->zif_slave_type \
+ == ZEBRA_IF_SLAVE_BOND)
+
extern void zebra_if_init(void);
extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t);
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index 8afb1a0b79..bfad8ea643 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -318,7 +318,7 @@ static void lm_zclient_init(char *lm_zserv_path)
lm_zserv_path);
/* Set default values. */
- zclient = zclient_new_notify(zebrad.master, &zclient_options_default);
+ zclient = zclient_new(zebrad.master, &zclient_options_default);
zclient->privs = &zserv_privs;
zclient->sock = -1;
zclient->t_connect = NULL;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index a65d477f03..da74a757bf 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1711,6 +1711,8 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
setsrc = 1;
}
}
+
+ continue;
}
if ((cmd == RTM_NEWROUTE
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 99a7ca5d55..19d41a402e 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -410,7 +410,7 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
goto done;
}
- frr_elevate_privs(ZPRIVS_RAISE) {
+ frr_elevate_privs(&zserv_privs) {
if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE)
kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 83b4ffa832..b93911bee7 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -248,7 +248,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
* RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
* an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
* received)
- * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
+ * - for the vty commands "ip address A.B.C.D/M [<label LINE>]"
* and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
* - when an RTM_NEWADDR message is received from the kernel,
*
@@ -269,7 +269,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
* |
* vty commands:
* "no ip address A.B.C.D/M [label LINE]"
- * "no ip address A.B.C.D/M secondary"
+ * "no ip address A.B.C.D/M"
* ["no ipv6 address X:X::X:X/M"]
*
*/
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 529fc48edf..f4b2fe4794 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -99,6 +99,23 @@ void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave)
br_slave->br_if = NULL;
}
+void zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave)
+{
+ struct interface *bond_if;
+
+ /* TODO: Handle change of master */
+ bond_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ bond_slave->bond_ifindex);
+ if (bond_if)
+ bond_slave->bond_if = bond_if;
+}
+
+void zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave)
+{
+ if (bond_slave != NULL)
+ bond_slave->bond_if = NULL;
+}
+
/*
* Handle Bridge interface add or update. Update relevant info,
* map slaves (if any) to the bridge.
@@ -238,3 +255,24 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
zebra_l2_unmap_slave_from_bridge(&zif->brslave_info);
}
}
+
+void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex)
+{
+ struct zebra_if *zif;
+ ifindex_t old_bond_ifindex;
+
+ zif = ifp->info;
+ assert(zif);
+
+ old_bond_ifindex = zif->bondslave_info.bond_ifindex;
+ if (old_bond_ifindex == bond_ifindex)
+ return;
+
+ zif->bondslave_info.bond_ifindex = bond_ifindex;
+
+ /* Set up or remove link with master */
+ if (bond_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_map_slave_to_bond(&zif->bondslave_info);
+ else if (old_bond_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_unmap_slave_from_bond(&zif->bondslave_info);
+}
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index db6cb0e53a..68c9d4a7a1 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -52,6 +52,11 @@ struct zebra_l2info_vxlan {
vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */
};
+struct zebra_l2info_bondslave {
+ ifindex_t bond_ifindex; /* Bridge Master */
+ struct interface *bond_if; /* Pointer to master */
+};
+
union zebra_l2if_info {
struct zebra_l2info_bridge br;
struct zebra_l2info_vlan vl;
@@ -70,6 +75,10 @@ union zebra_l2if_info {
extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave);
extern void
zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave);
+extern void
+zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave);
+extern void
+zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave);
extern void zebra_l2_bridge_add_update(struct interface *ifp,
struct zebra_l2info_bridge *bridge_info,
int add);
@@ -85,4 +94,6 @@ extern void zebra_l2_vxlanif_del(struct interface *ifp);
extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex);
+extern void zebra_l2if_update_bond_slave(struct interface *ifp,
+ ifindex_t bond_ifindex);
#endif /* _ZEBRA_L2_H */
diff --git a/zebra/zebra_l2_null.c b/zebra/zebra_l2_null.c
deleted file mode 100644
index c063f77bd4..0000000000
--- a/zebra/zebra_l2_null.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Zebra Layer-2 interface Data structures and definitions
- * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
- *
- * This file is part of FRR.
- *
- * FRR is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * FRR is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with FRR; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <zebra.h>
-
-#include "if.h"
-#include "zebra/debug.h"
-#include "zebra/zserv.h"
-#include "zebra/rib.h"
-#include "zebra/zebra_vrf.h"
-#include "zebra/zebra_l2.h"
-
-void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave)
-{
-}
-
-void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave)
-{
-}
-
-void zebra_l2_bridge_add_update(struct interface *ifp,
- struct zebra_l2info_bridge *bridge_info,
- int add)
-{
-}
-
-void zebra_l2_bridge_del(struct interface *ifp)
-{
-}
-
-void zebra_l2_vlanif_update(struct interface *ifp,
- struct zebra_l2info_vlan *vlan_info)
-{
-}
-
-void zebra_l2_vxlanif_add_update(struct interface *ifp,
- struct zebra_l2info_vxlan *vxlan_info, int add)
-{
-}
-
-void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
- vlanid_t access_vlan)
-{
-}
-
-void zebra_l2_vxlanif_del(struct interface *ifp)
-{
-}
-
-void zebra_l2if_update_bridge_slave(struct interface *ifp,
- ifindex_t bridge_ifindex)
-{
-}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index d55467c727..8285392527 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -358,8 +358,6 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
if (newhop->ifindex) {
resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
resolved_hop->ifindex = newhop->ifindex;
- if (newhop->flags & NEXTHOP_FLAG_ONLINK)
- resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
}
break;
case NEXTHOP_TYPE_IPV6:
@@ -398,6 +396,9 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
break;
}
+ if (newhop->flags & NEXTHOP_FLAG_ONLINK)
+ resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
+
/* Copy labels of the resolved route */
if (newhop->nh_label)
nexthop_add_labels(resolved_hop, newhop->nh_label_type,
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index bacef49836..c9918a7887 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -1116,15 +1116,15 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
/* Match function should return 1 if match is success else return
zero. */
-static route_map_result_t route_match_ip_address(void *rule,
- const struct prefix *prefix,
- route_map_object_t type,
- void *object)
+static route_map_result_t route_match_address(afi_t afi, void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
{
struct access_list *alist;
if (type == RMAP_ZEBRA) {
- alist = access_list_lookup(AFI_IP, (char *)rule);
+ alist = access_list_lookup(afi, (char *)rule);
if (alist == NULL)
return RMAP_NOMATCH;
@@ -1135,23 +1135,45 @@ static route_map_result_t route_match_ip_address(void *rule,
return RMAP_NOMATCH;
}
+static route_map_result_t route_match_ip_address(void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
+{
+ return route_match_address(AFI_IP, rule, prefix, type, object);
+}
+
+static route_map_result_t route_match_ipv6_address(void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
+
+{
+ return route_match_address(AFI_IP6, rule, prefix, type, object);
+}
+
/* Route map `ip address' match statement. `arg' should be
access-list name. */
-static void *route_match_ip_address_compile(const char *arg)
+static void *route_match_address_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}
/* Free route map's compiled `ip address' value. */
-static void route_match_ip_address_free(void *rule)
+static void route_match_address_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
/* Route map commands for ip address matching. */
static struct route_map_rule_cmd route_match_ip_address_cmd = {
- "ip address", route_match_ip_address, route_match_ip_address_compile,
- route_match_ip_address_free};
+ "ip address", route_match_ip_address, route_match_address_compile,
+ route_match_address_free};
+
+/* Route map commands for ipv6 address matching. */
+static struct route_map_rule_cmd route_match_ipv6_address_cmd = {
+ "ipv6 address", route_match_ipv6_address, route_match_address_compile,
+ route_match_address_free};
/* `match ip address prefix-list PREFIX_LIST' */
@@ -1869,6 +1891,7 @@ void zebra_route_map_init()
route_map_install_match(&route_match_ip_next_hop_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_cmd);
+ route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_prefix_len_cmd);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 99d96fd67f..afe3c708a0 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -96,6 +96,7 @@ struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
zrt = XCALLOC(MTYPE_ZEBRA_NS, sizeof(*zrt));
zrt->tableid = tableid;
zrt->afi = afi;
+ zrt->safi = safi;
zrt->ns_id = zvrf->zns->ns_id;
zrt->table =
(afi == AFI_IP6) ? srcdest_table_init() : route_table_init();
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index e98a533609..38b8b43d73 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -380,6 +380,7 @@ static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
table->cleanup = zebra_rtable_node_cleanup;
zvrf->table[afi][safi] = table;
+ XFREE(MTYPE_RIB_TABLE_INFO, table->info);
info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
info->zvrf = zvrf;
info->afi = afi;