-I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib
AM_LDFLAGS = \
-export-dynamic \
+ $(AC_LDFLAGS) \
$(SAN_FLAGS) \
# end
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
aclocal.m4 \
README.md \
m4/README.txt \
+ m4/libtool-whole-archive.patch \
\
python/clidef.py \
python/clippy/__init__.py \
.description = "The BGP flowspec subsystem has detected that there was a failure for installation/removal/modification of Flowspec from the dataplane",
.suggestion = "Gather log files from the router and open an issue, Restart FRR"
},
+ {
+ .code = EC_BGP_DOPPELGANGER_CONFIG,
+ .title = "BGP has detected a configuration overwrite during peer collision resolution",
+ .description = "As part of BGP startup, the peer and ourselves can start connections to each other at the same time. During this process BGP received additional configuration, but it was only applied to one of the two nascent connections. Depending on the result of collision detection and resolution this configuration might be lost. To remedy this, after performing collision detection and resolution the peer session has been reset in order to apply the new configuration.",
+ .suggestion = "Gather data and open a Issue so that this developmental escape can be fixed, the peer should have been reset",
+ },
{
.code = END_FERR,
}
EC_BGP_CAPABILITY_VENDOR,
EC_BGP_CAPABILITY_UNKNOWN,
EC_BGP_INVALID_NEXTHOP_LENGTH,
+ EC_BGP_DOPPELGANGER_CONFIG,
};
extern void bgp_error_init(void);
}
hash_release(bgp_def->vrf_import_rt_hash, irt);
- list_delete_and_null(&irt->vrfs);
+ list_delete(&irt->vrfs);
XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
}
static void import_rt_free(struct bgp *bgp, struct irt_node *irt)
{
hash_release(bgp->import_rt_hash, irt);
- list_delete_and_null(&irt->vnis);
+ list_delete(&irt->vnis);
XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt);
}
bgpevpn_unlink_from_l3vni(vpn);
bgp_table_unlock(vpn->route_table);
bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
- list_delete_and_null(&vpn->import_rtl);
- list_delete_and_null(&vpn->export_rtl);
+ list_delete(&vpn->import_rtl);
+ list_delete(&vpn->export_rtl);
bf_release_index(bm->rd_idspace, vpn->rd_id);
hash_release(bgp->vnihash, vpn);
QOBJ_UNREG(vpn);
*/
void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es)
{
- list_delete_and_null(&es->vtep_list);
+ list_delete(&es->vtep_list);
bgp_table_unlock(es->route_table);
bf_release_index(bm->rd_idspace, es->rd_id);
hash_release(bgp->esihash, es);
hash_free(bgp->esihash);
bgp->esihash = NULL;
- list_delete_and_null(&bgp->vrf_import_rtl);
- list_delete_and_null(&bgp->vrf_export_rtl);
- list_delete_and_null(&bgp->l2vnis);
+ list_delete(&bgp->vrf_import_rtl);
+ list_delete(&bgp->vrf_export_rtl);
+ list_delete(&bgp->l2vnis);
}
/*
for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
write_vni_config(vty, data);
- list_delete_and_null(&vnilist);
+ list_delete(&vnilist);
}
if (bgp->advertise_all_vni)
if (list_began)
vty_out(vty, ")");
vty_out(vty, "\n");
- list_delete_and_null(&list_bpm);
+ list_delete(&list_bpm);
} else
vty_out(vty, "\tnot installed in PBR\n");
}
if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
return from_peer;
+ /*
+ * Let's check that we are not going to loose known configuration
+ * state based upon doppelganger rules.
+ */
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (from_peer->afc[afi][safi] != peer->afc[afi][safi]) {
+ flog_err(
+ EC_BGP_DOPPELGANGER_CONFIG,
+ "from_peer->afc[%d][%d] is not the same as what we are overwriting",
+ afi, safi);
+ return NULL;
+ }
+ }
+
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
from_peer->host, from_peer, from_peer->fd, peer,
skiplist_free(lp->inuse);
lp->inuse = NULL;
- list_delete_and_null(&lp->chunks);
+ list_delete(&lp->chunks);
while ((lf = LABEL_FIFO_HEAD(lp->requests))) {
bgp_zebra_destroy();
bf_free(bm->rd_idspace);
- list_delete_and_null(&bm->bgp);
+ list_delete(&bm->bgp);
memset(bm, 0, sizeof(*bm));
frr_fini();
{
struct bgp_addr *addr = data;
- list_delete_and_null(&addr->ifp_name_list);
+ list_delete(&addr->ifp_name_list);
XFREE(MTYPE_BGP_ADDR, addr);
}
if (addr->ifp_name_list->count == 0) {
hash_release(bgp->address_hash, addr);
- list_delete_and_null(&addr->ifp_name_list);
+ list_delete(&addr->ifp_name_list);
XFREE(MTYPE_BGP_ADDR, addr);
}
}
bgp_unlock(e->bgp_orig);
if ((*extra)->bgp_fs_pbr)
- list_delete_and_null(&((*extra)->bgp_fs_pbr));
+ list_delete(&((*extra)->bgp_fs_pbr));
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
*extra = NULL;
{
struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote;
union gw_addr *info_gw_ip, *info_gw_ip_remote;
- char temp[16];
+ union {
+ struct eth_segment_id esi;
+ union gw_addr ip;
+ } temp;
if (afi != AFI_L2VPN)
return true;
if (!info->attr) {
- memset(&temp, 0, 16);
- info_eth_s_id = (struct eth_segment_id *)&temp;
- info_gw_ip = (union gw_addr *)&temp;
+ memset(&temp, 0, sizeof(temp));
+ info_eth_s_id = &temp.esi;
+ info_gw_ip = &temp.ip;
+
if (eth_s_id == NULL && gw_ip == NULL)
return true;
} else {
info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id);
info_gw_ip = &(info->attr->evpn_overlay.gw_ip);
}
- if (gw_ip == NULL)
- info_gw_ip_remote = (union gw_addr *)&temp;
- else
+
+ if (gw_ip == NULL) {
+ memset(&temp, 0, sizeof(temp));
+ info_gw_ip_remote = &temp.ip;
+ } else
info_gw_ip_remote = gw_ip;
- if (eth_s_id == NULL)
- info_eth_s_id_remote = (struct eth_segment_id *)&temp;
- else
+
+ if (eth_s_id == NULL) {
+ memset(&temp, 0, sizeof(temp));
+ info_eth_s_id_remote = &temp.esi;
+ } else
info_eth_s_id_remote = eth_s_id;
+
if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr)))
return false;
+
return !memcmp(info_eth_s_id, info_eth_s_id_remote,
sizeof(struct eth_segment_id));
}
route_match_ip_next_hop_prefix_list_compile,
route_match_ip_next_hop_prefix_list_free};
+/* `match ip next-hop type <blackhole>' */
+
+static route_map_result_t
+route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct bgp_info *bgp_info;
+
+ if (type == RMAP_BGP && prefix->family == AF_INET) {
+ bgp_info = (struct bgp_info *)object;
+ if (!bgp_info || !bgp_info->attr)
+ return RMAP_DENYMATCH;
+
+ /* If nexthop interface's index can't be resolved and nexthop is
+ set to any address then mark it as type `blackhole`.
+ This logic works for matching kernel/static routes like:
+ `ip route add blackhole 10.0.0.1`. */
+ if (bgp_info->attr->nexthop.s_addr == INADDR_ANY
+ && !bgp_info->attr->nh_ifindex)
+ return RMAP_MATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ip_next_hop_type_compile(const char *arg)
+{
+ return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ip_next_hop_type_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
+ "ip next-hop type", route_match_ip_next_hop_type,
+ route_match_ip_next_hop_type_compile,
+ route_match_ip_next_hop_type_free};
+
/* `match ip route-source prefix-list PREFIX_LIST' */
static route_map_result_t
route_match_ipv6_address_prefix_list_compile,
route_match_ipv6_address_prefix_list_free};
+/* `match ipv6 next-hop type <TYPE>' */
+
+static route_map_result_t
+route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct bgp_info *bgp_info;
+ struct in6_addr *addr = rule;
+
+ if (type == RMAP_BGP && prefix->family == AF_INET6) {
+ bgp_info = (struct bgp_info *)object;
+ if (!bgp_info || !bgp_info->attr)
+ return RMAP_DENYMATCH;
+
+ if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr)
+ && !bgp_info->attr->nh_ifindex)
+ return RMAP_MATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_type_compile(const char *arg)
+{
+ struct in6_addr *address;
+ int ret;
+
+ address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
+
+ ret = inet_pton(AF_INET6, "::0", address);
+ if (!ret) {
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
+ return NULL;
+ }
+
+ return address;
+}
+
+static void route_match_ipv6_next_hop_type_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
+ "ipv6 next-hop type", route_match_ipv6_next_hop_type,
+ route_match_ipv6_next_hop_type_compile,
+ route_match_ipv6_next_hop_type_free};
+
/* `set ipv6 nexthop global IP_ADDRESS' */
/* Set nexthop to object. ojbect must be pointer to struct attr. */
route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
+ route_map_match_ip_next_hop_type_hook(generic_match_add);
+ route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
+
route_map_match_ipv6_address_hook(generic_match_add);
route_map_no_match_ipv6_address_hook(generic_match_delete);
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
+ route_map_match_ipv6_next_hop_type_hook(generic_match_add);
+ route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
+
route_map_match_metric_hook(generic_match_add);
route_map_no_match_metric_hook(generic_match_delete);
route_map_install_match(&route_match_ip_route_source_cmd);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
+ route_map_install_match(&route_match_ip_next_hop_type_cmd);
route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
route_map_install_match(&route_match_aspath_cmd);
route_map_install_match(&route_match_community_cmd);
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_next_hop_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
+ route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
revalidate_bgp_node(bgp_node, afi,
safi);
- list_delete_and_null(&matches);
+ list_delete(&matches);
}
}
}
static int bgp_rpki_fini(void)
{
stop();
- list_delete_and_null(&cache_list);
+ list_delete(&cache_list);
close(rpki_sync_socket_rtr);
close(rpki_sync_socket_bgpd);
listnode_delete(bgp->redist[afi][type], red);
XFREE(MTYPE_BGP_REDIST, red);
if (!bgp->redist[afi][type]->count)
- list_delete_and_null(&bgp->redist[afi][type]);
+ list_delete(&bgp->redist[afi][type]);
}
}
static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
{
int active;
+ struct peer *other;
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
+ /*
+ * If we are turning on a AFI/SAFI locally and we've
+ * started bringing a peer up, we need to tell
+ * the other peer to restart because we might loose
+ * configuration here because when the doppelganger
+ * gets to a established state due to how
+ * we resolve we could just overwrite the afi/safi
+ * activation.
+ */
+ other = peer->doppelganger;
+ if (other
+ && (other->status == OpenSent
+ || other->status == OpenConfirm)) {
+ other->last_reset = PEER_DOWN_AF_ACTIVATE;
+ bgp_notify_send(other, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ }
}
return 0;
peer_delete(other);
}
}
- list_delete_and_null(&group->peer);
+ list_delete(&group->peer);
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
prefix)) {
prefix_free(prefix);
}
- list_delete_and_null(&group->listen_range[afi]);
+ list_delete(&group->listen_range[afi]);
}
XFREE(MTYPE_PEER_GROUP_HOST, group->name);
QOBJ_UNREG(bgp);
- list_delete_and_null(&bgp->group);
- list_delete_and_null(&bgp->peer);
+ list_delete(&bgp->group);
+ list_delete(&bgp->peer);
if (bgp->peerhash) {
hash_free(bgp->peerhash);
vpn_policy_direction_t dir;
if (bgp->vpn_policy[afi].import_vrf)
- list_delete_and_null(&bgp->vpn_policy[afi].import_vrf);
+ list_delete(&bgp->vpn_policy[afi].import_vrf);
if (bgp->vpn_policy[afi].export_vrf)
- list_delete_and_null(&bgp->vpn_policy[afi].export_vrf);
+ list_delete(&bgp->vpn_policy[afi].export_vrf);
dir = BGP_VPN_POLICY_DIR_FROMVPN;
if (bgp->vpn_policy[afi].rtlist[dir])
bgp_close();
if (bm->listen_sockets)
- list_delete_and_null(&bm->listen_sockets);
+ list_delete(&bm->listen_sockets);
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
listnode_delete(rfg->nves, rfd);
listnode_add(orphaned_nves, rfd);
}
- list_delete_and_null(&rfg->nves);
+ list_delete(&rfg->nves);
}
/* delete it */
if (vty)
vty_out(vty, "\n");
}
- list_delete_and_null(&orphaned_nves);
+ list_delete(&orphaned_nves);
}
}
if (rfg->rt_export_list)
ecommunity_free(&rfg->rt_export_list);
if (rfg->labels)
- list_delete_and_null(&rfg->labels);
+ list_delete(&rfg->labels);
if (rfg->rfp_cfg)
XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg);
listnode_delete(bgp->rfapi_cfg->l2_groups, rfg);
bgp_rfapi_delete_named_nve_group(NULL, bgp, NULL, RFAPI_GROUP_CFG_MAX);
bgp_rfapi_delete_named_l2_group(NULL, bgp, NULL);
if (h->l2_groups != NULL)
- list_delete_and_null(&h->l2_groups);
- list_delete_and_null(&h->nve_groups_sequential);
- list_delete_and_null(&h->rfg_export_direct_bgp_l);
- list_delete_and_null(&h->rfg_export_zebra_l);
+ list_delete(&h->l2_groups);
+ list_delete(&h->nve_groups_sequential);
+ list_delete(&h->rfg_export_direct_bgp_l);
+ list_delete(&h->rfg_export_zebra_l);
if (h->default_rt_export_list)
ecommunity_free(&h->default_rt_export_list);
if (h->default_rt_import_list)
* Delete local_nexthops list
*/
if (bi->extra && bi->extra->vnc.export.local_nexthops) {
- list_delete_and_null(
+ list_delete(
&bi->extra->vnc.export.local_nexthops);
}
*/
if (pn->info) {
if (pn->info != (void *)1) {
- list_delete_and_null(
+ list_delete(
(struct list *
*)(&pn->info));
}
}
delete_list->del = (void (*)(void *))rfapi_info_free;
- list_delete_and_null(&delete_list);
+ list_delete(&delete_list);
}
RFAPI_RIB_CHECK_COUNTS(0, 0);
agg_unlock_node(pn);
}
if (lPendCost) {
- list_delete_and_null(&lPendCost);
+ list_delete(&lPendCost);
pn->info = NULL;
agg_unlock_node(pn);
}
*/
if (pn->info) {
if (pn->info != (void *)1) {
- list_delete_and_null((struct list **)(&pn->info));
+ list_delete((struct list **)(&pn->info));
}
pn->info = NULL;
agg_unlock_node(pn); /* linklist or 1 deleted */
}
list_delete_all_node(adb_delete_list);
}
- list_delete_and_null(&adb_delete_list);
+ list_delete(&adb_delete_list);
}
if (nve_list) {
vnc_direct_bgp_unexport_table(
afi, it->imported_vpn[afi], nve_list);
- list_delete_and_null(&nve_list);
+ list_delete(&nve_list);
}
}
}
skiplist_delete(it->monitor_exterior_orphans,
an_bi_exterior, NULL);
}
- list_delete_and_null(&list_adopted);
+ list_delete(&list_adopted);
}
}
nve_list_to_nh_array(rn->p.family, nves, &nexthop_count,
&nh_ary, &nhp_ary);
- list_delete_and_null(&nves);
+ list_delete(&nves);
if (nexthop_count)
vnc_zebra_route_msg(&rn->p, nexthop_count, nhp_ary,
vnc_zlog_debug_verbose("%s: family: %d, nve count: %d",
__func__, family, nexthop_count);
- list_delete_and_null(&nves);
+ list_delete(&nves);
if (nexthop_count) {
/*
dnl -------
dnl libtool
dnl -------
+AC_ARG_ENABLE(static-bin,
+ AS_HELP_STRING([--enable-static-bin], [link binaries statically]))
LT_INIT
+_LT_CONFIG_LIBTOOL([
+ patch -N -i "${srcdir}/m4/libtool-whole-archive.patch" libtool >&AS_MESSAGE_LOG_FD || \
+ AC_MSG_WARN([Could not patch libtool for static linking support. Loading modules into a statically linked daemon will fail.])
+])
+if test "$enable_static_bin" = "yes"; then
+ AC_LDFLAGS="-static"
+fi
+AC_SUBST(AC_LDFLAGS)
+AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"])
dnl ----------------------
dnl Packages configuration
fi
AM_CONDITIONAL([GIT_VERSION], [test "x$with_pkg_git_version" = "xyes"])
+AC_CHECK_TOOL([OBJCOPY], [objcopy], [:])
+AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [
+ frr_cv_interp=""
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [
+ if $OBJCOPY -j.interp -Obinary conftest conftest.interp; then
+ frr_cv_interp="`xargs -0 echo < conftest.interp`"
+ fi
+ test -f conftest.interp && rm conftest.interp
+ ])
+])
+if test -n "$frr_cv_interp"; then
+ AC_DEFINE_UNQUOTED(INTERP, ["$frr_cv_interp"], [.interp value])
+fi
+
dnl ------------------------------------
dnl Check C keywords and standard types
dnl ------------------------------------
with the sources (``frr_*.orig.tar.gz``, ``frr_*.debian.tar.xz`` and
``frr_*.dsc``)
+The build procedure can also be executed automatically using the ``tools/build-debian-package.sh``
+script. For example:
+
+.. code-block:: shell
+
+ EXTRA_VERSION="-myversion" WANT_SNMP=1 WANT_CUMULUS_MODE=1 tools/build-debian-package.sh
+
.. _deb-backports:
Debian Backports
common capabilities, FRR sends Unsupported Capability error and then resets the
connection.
-.. _bgp-concepts-vrfs:
-
-VRFs: Virtual Routing and Forwarding
-------------------------------------
-
-*bgpd* supports :abbr:`L3VPN (Layer 3 Virtual Private Networks)` :abbr:`VRFs
-(Virtual Routing and Forwarding tables)` for IPv4 :rfc:`4364` and IPv6
-:rfc:`4659`. L3VPN routes, and their associated VRF MPLS labels, can be
-distributed to VPN SAFI neighbors in the *default*, i.e., non VRF, BGP
-instance. VRF MPLS labels are reached using *core* MPLS labels which are
-distributed using LDP or BGP labeled unicast. *bgpd* also supports inter-VRF
-route leaking. General information on FRR's VRF support can be found in
-:ref:`zebra-vrf`.
-
.. _bgp-router-configuration:
BGP Router Configuration
not enabled *bgpd* can't get interface information so `router-id` is set to
0.0.0.0. So please set router-id by hand.
+
+.. _bgp-multiple-autonomous-systems:
+
+Multiple Autonomous Systems
+---------------------------
+
+FRR's BGP implementation is capable of running multiple autonomous systems at
+once. Each configured AS corresponds to a :ref:`zebra-vrf`. In the past, to get
+the same functionality the network administrator had to run a new *bgpd*
+process; using VRFs allows multiple autonomous systems to be handled in a
+single process.
+
+When using multiple autonomous systems, all router config blocks after the
+first one must specify a VRF to be the target of BGP's route selection. This
+VRF must be unique within respect to all other VRFs being used for the same
+purpose, i.e. two different autonomous systems cannot use the same VRF.
+However, the same AS can be used with different VRFs.
+
+.. note::
+
+ The separated nature of VRFs makes it possible to peer a single *bgpd*
+ process to itself, on one machine. Note that this can be done fully within
+ BGP without a corresponding VRF in the kernel or Zebra, which enables some
+ practical use cases such as :ref:`route reflectors <bgp-route-reflector>`
+ and route servers.
+
+Configuration of additional autonomous systems, or of a router that targets a
+specific VRF, is accomplished with the following command:
+
+.. index:: router bgp ASN vrf VRFNAME
+.. clicmd:: router bgp ASN vrf VRFNAME
+
+ ``VRFNAME`` is matched against VRFs configured in the kernel. When ``vrf
+ VRFNAME`` is not specified, the BGP protocol process belongs to the default
+ VRF.
+
+An example configuration with multiple autonomous systems might look like this:
+
+.. code-block:: frr
+
+ router bgp 1
+ neighbor 10.0.0.1 remote-as 20
+ neighbor 10.0.0.2 remote-as 30
+ !
+ router bgp 2 vrf blue
+ neighbor 10.0.0.3 remote-as 40
+ neighbor 10.0.0.4 remote-as 50
+ !
+ router bgp 3 vrf red
+ neighbor 10.0.0.5 remote-as 60
+ neighbor 10.0.0.6 remote-as 70
+ ...
+
+In the past this feature done differently and the following commands were
+required to enable the functionality. They are now deprecated.
+
+.. deprecated:: 5.0
+ This command is deprecated and may be safely removed from the config.
+
+.. index:: bgp multiple-instance
+.. clicmd:: bgp multiple-instance
+
+ Enable BGP multiple instance feature. Because this is now the default
+ configuration this command will not be displayed in the running
+ configuration.
+
+.. deprecated:: 5.0
+ This command is deprecated and may be safely removed from the config.
+
+.. index:: no bgp multiple-instance
+.. clicmd:: no bgp multiple-instance
+
+ In previous versions of FRR, this command disabled the BGP multiple instance
+ feature. This functionality is automatically turned on when BGP multiple
+ instances or views exist so this command no longer does anything.
+
+.. seealso:: :ref:`bgp-vrf-route-leaking`
+.. seealso:: :ref:`zebra-vrf`
+
+
+.. _bgp-views:
+
+Views
+-----
+
+In addition to supporting multiple autonomous systems, FRR's BGP implementation
+also supports *views*.
+
+BGP views are almost the same as normal BGP processes, except that routes
+selected by BGP are not installed into the kernel routing table. Each BGP view
+provides an independent set of routing information which is only distributed
+via BGP. Multiple views can be supported, and BGP view information is always
+independent from other routing protocols and Zebra/kernel routes. BGP views use
+the core instance (i.e., default VRF) for communication with peers.
+
+.. index:: router bgp AS-NUMBER view NAME
+.. clicmd:: router bgp AS-NUMBER view NAME
+
+ Make a new BGP view. You can use an arbitrary word for the ``NAME``. Routes
+ selected by the view are not installed into the kernel routing table.
+
+ With this command, you can setup Route Server like below.
+
+ .. code-block:: frr
+
+ !
+ router bgp 1 view 1
+ neighbor 10.0.0.1 remote-as 2
+ neighbor 10.0.0.2 remote-as 3
+ !
+ router bgp 2 view 2
+ neighbor 10.0.0.3 remote-as 4
+ neighbor 10.0.0.4 remote-as 5
+
+.. index:: show [ip] bgp view NAME
+.. clicmd:: show [ip] bgp view NAME
+
+ Display the routing table of BGP view ``NAME``.
+
+
Route Selection
---------------
overwriting other values. Multiple large-community values can be specified.
-.. _bgp-vrfs:
+.. _bgp-l3vpn-vrfs:
-VRFs
-----
+L3VPN VRFs
+----------
-BGP supports multiple VRF instances with the following command:
-
-.. index:: router bgp ASN vrf VRFNAME
-.. clicmd:: router bgp ASN vrf VRFNAME
+*bgpd* supports :abbr:`L3VPN (Layer 3 Virtual Private Networks)` :abbr:`VRFs
+(Virtual Routing and Forwarding)` for IPv4 :rfc:`4364` and IPv6 :rfc:`4659`.
+L3VPN routes, and their associated VRF MPLS labels, can be distributed to VPN
+SAFI neighbors in the *default*, i.e., non VRF, BGP instance. VRF MPLS labels
+are reached using *core* MPLS labels which are distributed using LDP or BGP
+labeled unicast. *bgpd* also supports inter-VRF route leaking.
-``VRFNAME`` is matched against VRFs configured in the kernel. When
-``vrf VRFNAME`` is not specified, the BGP protocol process belongs to the
-default VRF.
-With VRF, you can isolate networking information. Having BGP VRF allows you to
-have several BGP instances on the same system process. This solution solves
-scalabiliy issues where the network administrator had previously to run
-separately several BGP processes on each namespace. Now, not only BGP VRF
-solves this, but also this method applies to both kind of VRFs backend: default
-VRF from Linux kernel or network namespaces. Also, having separate BGP
-instances does not imply that the AS number has to be different. For internal
-purposes, it is possible to do iBGP peering from two differents network
-namespaces.
+.. _bgp-vrf-route-leaking:
VRF Route Leaking
-^^^^^^^^^^^^^^^^^
+-----------------
BGP routes may be leaked (i.e. copied) between a unicast VRF RIB and the VPN
SAFI RIB of the default VRF for use in MPLS-based L3VPNs. Unicast routes may
to VPN.
Required parameters
-"""""""""""""""""""
+^^^^^^^^^^^^^^^^^^^
Routes exported from a unicast VRF to the VPN RIB must be augmented by two
parameters:
auto-derived.
General configuration
-"""""""""""""""""""""
+^^^^^^^^^^^^^^^^^^^^^
Configuration of route leaking between a unicast VRF RIB and the VPN SAFI RIB
of the default VRF is accomplished via commands in the context of a VRF
Disables automatic leaking from vrf VRFNAME to the current VRF using
the VPN RIB as intermediary.
-.. _bgp-instances-and-views:
-
-Instances and Views
--------------------
-
-A BGP *instance* is a normal BGP process. Routes selected by BGP are installed
-into the kernel routing table.
-
-.. note::
- In previous versions of FRR, running multiple AS's from the same BGP process
- was not supported; in order to run multiple AS's it was necessary to run
- multiple BGP processes. This had to be explicitly configured with the
- ``bgp multiple-instance`` command. Recent versions of FRR support multiple
- BGP AS's within the same process by simply defining multiple
- ``router bgp X`` blocks, so the ``multiple-instance`` command is now
- unnecessary and deprecated.
-
-.. index:: router bgp AS-NUMBER
-.. clicmd:: router bgp AS-NUMBER
-
- Make a new BGP instance. You can use an arbitrary word for the `name`.
-
- .. code-block:: frr
-
- router bgp 1
- neighbor 10.0.0.1 remote-as 2
- neighbor 10.0.0.2 remote-as 3
- !
- router bgp 2
- neighbor 10.0.0.3 remote-as 4
- neighbor 10.0.0.4 remote-as 5
-
-.. deprecated:: 5.0
- This command does nothing and can be safely removed.
-
-.. index:: bgp multiple-instance
-.. clicmd:: bgp multiple-instance
-
- Enable BGP multiple instance feature. Because this is now the default
- configuration this command will not be displayed in the running
- configuration.
-
-.. deprecated:: 5.0
- This command does nothing and can be safely removed.
-
-.. index:: no bgp multiple-instance
-.. clicmd:: no bgp multiple-instance
-
- In previous versions of FRR, this command disabled the BGP multiple instance
- feature. This functionality is automatically turned on when BGP multiple
- instances or views exist so this command no longer does anything.
-
-BGP views are almost same as normal BGP processes, except that routes selected
-by BGP are not installed into the kernel routing table. The view functionality
-allows the exchange of BGP routing information only without affecting the
-kernel routing tables.
-
-.. index:: router bgp AS-NUMBER view NAME
-.. clicmd:: router bgp AS-NUMBER view NAME
-
- Make a new BGP view. You can use arbitrary word for the ``NAME``. Routes selected by the view are not installed into the kernel routing table.
- view's route selection result does not go to the kernel routing table.
-
- With this command, you can setup Route Server like below.
-
- .. code-block:: frr
-
- !
- router bgp 1 view 1
- neighbor 10.0.0.1 remote-as 2
- neighbor 10.0.0.2 remote-as 3
- !
- router bgp 2 view 2
- neighbor 10.0.0.3 remote-as 4
- neighbor 10.0.0.4 remote-as 5
-
-.. index:: show [ip] bgp view NAME
-.. clicmd:: show [ip] bgp view NAME
-
- Display the routing table of BGP view ``NAME``.
.. _bgp-cisco-compatibility:
tn->serno);
if (successors)
- list_delete_and_null(&successors);
+ list_delete(&successors);
}
void show_ip_eigrp_nexthop_entry(struct vty *vty, struct eigrp *eigrp,
// neighbors left
}
- list_delete_and_null(&successors);
+ list_delete(&successors);
return 1;
}
// neighbors left
}
- list_delete_and_null(&successors);
+ list_delete(&successors);
return 1;
}
ne = listnode_head(successors);
eigrp_send_reply(ne->adv_router, prefix);
- list_delete_and_null(&successors);
+ list_delete(&successors);
}
prefix->state = EIGRP_FSM_STATE_PASSIVE;
msg);
- list_delete_and_null(&successors);
+ list_delete(&successors);
return 1;
}
ne = listnode_head(successors);
eigrp_send_reply(ne->adv_router, prefix);
- list_delete_and_null(&successors);
+ list_delete(&successors);
}
prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
listnode_add(eigrp->topology_changes_internalIPV4, prefix);
// neighbors left
}
- list_delete_and_null(&successors);
+ list_delete(&successors);
return 1;
}
msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2;
msg->prefix->distance = ne->distance;
- list_delete_and_null(&successors);
+ list_delete(&successors);
return 1;
}
if (!ei)
return 0;
- list_delete_and_null(&ei->nbrs);
+ list_delete(&ei->nbrs);
eigrp = ei->eigrp;
listnode_delete(eigrp->eiflist, ei);
eigrp_if_down(ei);
- list_delete_and_null(&ei->nbrs);
+ list_delete(&ei->nbrs);
listnode_delete(ei->eigrp->eiflist, ei);
}
}
}
- if (!has_tlv) {
- if (ep)
- eigrp_packet_free(ep);
+ if (!has_tlv)
return;
- }
if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
&& ei->params.auth_keychain != NULL)
eigrp_zebra_route_add(node->destination, l);
}
- list_delete_and_null(&l);
+ list_delete(&l);
}
/*
for (ALL_LIST_ELEMENTS(pe->entries, node, nnode, ne))
eigrp_nexthop_entry_delete(pe, ne);
- list_delete_and_null(&pe->entries);
- list_delete_and_null(&pe->rij);
+ list_delete(&pe->entries);
+ list_delete(&pe->rij);
eigrp_zebra_route_delete(pe->destination);
prefix_free(pe->destination);
* If we have no successors return NULL
*/
if (!successors->count) {
- list_delete_and_null(&successors);
+ list_delete(&successors);
successors = NULL;
}
for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
entry->flags |= EIGRP_NEXTHOP_ENTRY_INTABLE_FLAG;
- list_delete_and_null(&successors);
+ list_delete(&successors);
} else {
eigrp_zebra_route_delete(prefix->destination);
for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry))
eigrp_update_send_all(eigrp, ei);
if (nbr_prefixes)
- list_delete_and_null(&nbr_prefixes);
+ list_delete(&nbr_prefixes);
}
/*send EIGRP Update packet*/
THREAD_OFF(eigrp->t_read);
close(eigrp->fd);
- list_delete_and_null(&eigrp->eiflist);
- list_delete_and_null(&eigrp->oi_write_q);
+ list_delete(&eigrp->eiflist);
+ list_delete(&eigrp->oi_write_q);
eigrp_topology_free(eigrp->topology_table);
eigrp_nbr_delete(eigrp->neighbor_self);
- list_delete_and_null(&eigrp->topology_changes_externalIPV4);
- list_delete_and_null(&eigrp->topology_changes_internalIPV4);
+ list_delete(&eigrp->topology_changes_externalIPV4);
+ list_delete(&eigrp->topology_changes_internalIPV4);
listnode_delete(eigrp_om->eigrp, eigrp);
if (circuit->ip_addrs) {
assert(listcount(circuit->ip_addrs) == 0);
- list_delete_and_null(&circuit->ip_addrs);
+ list_delete(&circuit->ip_addrs);
}
if (circuit->ipv6_link) {
assert(listcount(circuit->ipv6_link) == 0);
- list_delete_and_null(&circuit->ipv6_link);
+ list_delete(&circuit->ipv6_link);
}
if (circuit->ipv6_non_link) {
assert(listcount(circuit->ipv6_non_link) == 0);
- list_delete_and_null(&circuit->ipv6_non_link);
+ list_delete(&circuit->ipv6_non_link);
}
circuit->circ_type = CIRCUIT_T_UNKNOWN;
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
/* destroy neighbour lists */
if (circuit->u.bc.lan_neighs[0]) {
- list_delete_and_null(&circuit->u.bc.lan_neighs[0]);
+ list_delete(&circuit->u.bc.lan_neighs[0]);
circuit->u.bc.lan_neighs[0] = NULL;
}
if (circuit->u.bc.lan_neighs[1]) {
- list_delete_and_null(&circuit->u.bc.lan_neighs[1]);
+ list_delete(&circuit->u.bc.lan_neighs[1]);
circuit->u.bc.lan_neighs[1] = NULL;
}
/* destroy adjacency databases */
if (circuit->u.bc.adjdb[0]) {
circuit->u.bc.adjdb[0]->del = isis_delete_adj;
- list_delete_and_null(&circuit->u.bc.adjdb[0]);
+ list_delete(&circuit->u.bc.adjdb[0]);
circuit->u.bc.adjdb[0] = NULL;
}
if (circuit->u.bc.adjdb[1]) {
circuit->u.bc.adjdb[1]->del = isis_delete_adj;
- list_delete_and_null(&circuit->u.bc.adjdb[1]);
+ list_delete(&circuit->u.bc.adjdb[1]);
circuit->u.bc.adjdb[1] = NULL;
}
if (circuit->u.bc.is_dr[0]) {
if (!adjdb) {
zlog_warn("isis_dr_elect() adjdb == NULL");
- list_delete_and_null(&list);
+ list_delete(&list);
return ISIS_WARNING;
}
isis_adj_build_up_list(adjdb, list);
*/
if (circuit->u.bc.is_dr[level - 1])
retval = isis_dr_resign(circuit, level);
- list_delete_and_null(&list);
+ list_delete(&list);
return retval;
}
if (circuit->u.bc.is_dr[level - 1])
retval = isis_dr_resign(circuit, level);
}
- list_delete_and_null(&list);
+ list_delete(&list);
return retval;
}
circuit->lsp_regenerate_pending[idx] = 0;
circuit->u.bc.run_dr_elect[idx] = 0;
if (circuit->u.bc.lan_neighs[idx] != NULL)
- list_delete_and_null(&circuit->u.bc.lan_neighs[idx]);
+ list_delete(&circuit->u.bc.lan_neighs[idx]);
}
return;
lsp_clear_data(lsp);
if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0 && lsp->lspu.frags) {
- list_delete_and_null(&lsp->lspu.frags);
+ list_delete(&lsp->lspu.frags);
lsp->lspu.frags = NULL;
}
frag->tlvs = tlvs;
}
- list_delete_and_null(&fragments);
+ list_delete(&fragments);
lsp_debug("ISIS (%s): LSP construction is complete. Serializing...",
area->area_tag);
return;
LSP_PSEUDO_ID(ne_id));
}
}
- list_delete_and_null(&adj_list);
+ list_delete(&adj_list);
return;
}
void area_mt_finish(struct isis_area *area)
{
- list_delete_and_null(&area->mt_settings);
+ list_delete(&area->mt_settings);
}
struct isis_area_mt_setting *area_get_mt_setting(struct isis_area *area,
void circuit_mt_finish(struct isis_circuit *circuit)
{
- list_delete_and_null(&circuit->mt_settings);
+ list_delete(&circuit->mt_settings);
}
struct isis_circuit_mt_setting *
}
/* lets free it */
- list_delete_and_null(&lsp_list);
+ list_delete(&lsp_list);
}
if (fabricd_initial_sync_is_complete(circuit->area) && resync_needed)
if (route_info->nexthops) {
route_info->nexthops->del =
(void (*)(void *))isis_nexthop_delete;
- list_delete_and_null(&route_info->nexthops);
+ list_delete(&route_info->nexthops);
}
if (route_info->nexthops6) {
route_info->nexthops6->del =
(void (*)(void *))isis_nexthop6_delete;
- list_delete_and_null(&route_info->nexthops6);
+ list_delete(&route_info->nexthops6);
}
XFREE(MTYPE_ISIS_ROUTE_INFO, route_info);
adjdb = circuit->u.bc.adjdb[spftree->level - 1];
isis_adj_build_up_list(adjdb, adj_list);
if (listcount(adj_list) == 0) {
- list_delete_and_null(&adj_list);
+ list_delete(&adj_list);
if (isis->debugs & DEBUG_SPF_EVENTS)
zlog_debug(
"ISIS-Spf: no L%d adjacencies on circuit %s",
"isis_spf_preload_tent unknow adj type");
}
}
- list_delete_and_null(&adj_list);
+ list_delete(&adj_list);
/*
* Add the pseudonode
*/
__attribute__((__unused__))
static void isis_vertex_del(struct isis_vertex *vertex)
{
- list_delete_and_null(&vertex->Adj_N);
- list_delete_and_null(&vertex->parents);
+ list_delete(&vertex->Adj_N);
+ list_delete(&vertex->parents);
if (vertex->firsthops) {
hash_clean(vertex->firsthops, NULL);
hash_free(vertex->firsthops);
skiplist_free(queue->l.slist);
queue->l.slist = NULL;
} else
- list_delete_and_null(&queue->l.list);
+ list_delete(&queue->l.list);
}
__attribute__((__unused__))
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(rv, node, fragment_tlvs))
isis_free_tlvs(fragment_tlvs);
- list_delete_and_null(&rv);
+ list_delete(&rv);
}
stream_free(dummy_stream);
circuit->ipv6_router = 0;
isis_csm_state_change(ISIS_DISABLE, circuit, area);
}
- list_delete_and_null(&area->circuit_list);
+ list_delete(&area->circuit_list);
}
if (area->lspdb[0] != NULL) {
}
vector comps = completions_to_vec(completions);
- list_delete_and_null(&completions);
+ list_delete(&completions);
// set status code appropriately
switch (vector_active(comps)) {
// if matcher error, return corresponding CMD_ERR
if (MATCHER_ERROR(status)) {
if (argv_list)
- list_delete_and_null(&argv_list);
+ list_delete(&argv_list);
switch (status) {
case MATCHER_INCOMPLETE:
return CMD_ERR_INCOMPLETE;
ret = matched_element->func(matched_element, vty, argc, argv);
// delete list and cmd_token's in it
- list_delete_and_null(&argv_list);
+ list_delete(&argv_list);
XFREE(MTYPE_TMP, argv);
return ret;
if (host.config)
XFREE(MTYPE_HOST, host.config);
- list_delete_and_null(&varhandlers);
+ list_delete(&varhandlers);
qobj_finish();
}
status = MATCHER_INCOMPLETE;
// cleanup
- list_delete_and_null(&next);
+ list_delete(&next);
return status;
}
unsigned int idx;
for (idx = 0; idx < vector_active(vline) && next->count > 0; idx++) {
- list_delete_and_null(¤t);
+ list_delete(¤t);
current = next;
next = list_new();
next->del = stack_del;
}
}
- list_delete_and_null(¤t);
- list_delete_and_null(&next);
+ list_delete(¤t);
+ list_delete(&next);
return mrv;
}
list_delete_node(list, tail);
// delete the rest of the list as usual
- list_delete_and_null(&list);
+ list_delete(&list);
}
/*---------- token level matching functions ----------*/
json_object_free(top);
}
- list_delete_and_null(&errlist);
+ list_delete(&errlist);
}
DEFUN_NOSH(show_error_code,
{
pthread_mutex_lock(&frr_pthread_list_mtx);
{
- list_delete_and_null(&frr_pthread_list);
+ list_delete(&frr_pthread_list);
}
pthread_mutex_unlock(&frr_pthread_list_mtx);
}
vty_out(vty, "%% No match\n");
// free resources
- list_delete_and_null(&completions);
+ list_delete(&completions);
cmd_free_strvec(command);
XFREE(MTYPE_TMP, cmdstr);
vty_out(vty, "func: %p\n", element->func);
- list_delete_and_null(&argvv);
+ list_delete(&argvv);
} else {
assert(MATCHER_ERROR(result));
switch (result) {
}
prev = cur;
}
- list_delete_and_null(&commands);
+ list_delete(&commands);
vty_out(vty, "\n");
} while (scan && scannode < LINK_PARAMS_NODE);
if (_hashes) {
listnode_delete(_hashes, hash);
if (_hashes->count == 0) {
- list_delete_and_null(&_hashes);
+ list_delete(&_hashes);
}
}
}
if_delete_retain(ifp);
- list_delete_and_null(&ifp->connected);
- list_delete_and_null(&ifp->nbr_connected);
+ list_delete(&ifp->connected);
+ list_delete(&ifp->nbr_connected);
if_link_params_free(ifp);
if (keychain->name)
XFREE(MTYPE_KEYCHAIN, keychain->name);
- list_delete_and_null(&keychain->key);
+ list_delete(&keychain->key);
listnode_delete(keychain_list, keychain);
keychain_free(keychain);
}
fclose(fp);
}
}
+
+#ifdef INTERP
+static const char interp[]
+ __attribute__((section(".interp"), used)) = INTERP;
+#endif
+/*
+ * executable entry point for libfrr.so
+ *
+ * note that libc initialization is skipped for this so the set of functions
+ * that can be called is rather limited
+ */
+extern void _libfrr_version(void)
+ __attribute__((visibility("hidden"), noreturn));
+void _libfrr_version(void)
+{
+ const char banner[] =
+ FRR_FULL_NAME " " FRR_VERSION ".\n"
+ FRR_COPYRIGHT GIT_INFO "\n"
+ "configured with:\n " FRR_CONFIG_ARGS "\n";
+ write(1, banner, sizeof(banner) - 1);
+ _exit(0);
+}
list->count = 0;
}
-void list_delete_and_null(struct list **list)
+void list_delete(struct list **list)
{
assert(*list);
list_delete_all_node(*list);
*list = NULL;
}
-void list_delete_original(struct list *list)
-{
- list_delete_and_null(&list);
-}
-
struct listnode *listnode_lookup(struct list *list, void *data)
{
struct listnode *node;
extern void list_sort(struct list *list,
int (*cmp)(const void **, const void **));
-/*
- * The usage of list_delete is being transitioned to pass in
- * the double pointer to remove use after free's.
- * list_free usage is deprecated, it leads to memory leaks
- * of the linklist nodes. Please use list_delete_and_null
- *
- * In Oct of 2018, rename list_delete_and_null to list_delete
- * and remove list_delete_original and the list_delete #define
- * Additionally remove list_free entirely
- */
-#if CONFDATE > 20181001
-CPP_NOTICE("list_delete without double pointer is deprecated, please fixup")
-#endif
-
/*
* Delete a list and NULL its pointer.
*
* pointer to list pointer; this will be set to NULL after the list has been
* deleted
*/
-extern void list_delete_and_null(struct list **plist);
-
-/*
- * Delete a list.
- *
- * If non-null, list->del is called with each data element.
- *
- * plist
- * pointer to list pointer
- */
-extern void list_delete_original(struct list *list);
-#define list_delete(X) \
- list_delete_original((X)) \
- CPP_WARN("Please transition to using list_delete_and_null")
-#define list_free(X) \
- list_delete_original((X)) \
- CPP_WARN("Please transition tousing list_delete_and_null")
+extern void list_delete(struct list **plist);
/*
* Delete all nodes from a list without deleting the list itself.
RB_REMOVE(nhgc_entry_head, &nhgc_entries, nhgc);
- list_delete_and_null(&nhgc->nhg_list);
+ list_delete(&nhgc->nhg_list);
XFREE(MTYPE_TMP, nhgc);
}
const char *arg,
route_map_event_t type);
+ /* match ip next hop type */
+ int (*match_ip_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type);
+
+ /* no match ip next hop type */
+ int (*no_match_ip_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type);
+
/* match ipv6 address */
int (*match_ipv6_address)(struct vty *vty,
struct route_map_index *index,
const char *arg,
route_map_event_t type);
+ /* match ipv6 next-hop type */
+ int (*match_ipv6_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type);
+
+ /* no match ipv6next-hop type */
+ int (*no_match_ipv6_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command, const char *arg,
+ route_map_event_t type);
+
/* match metric */
int (*match_metric)(struct vty *vty, struct route_map_index *index,
const char *command, const char *arg,
rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func;
}
+/* match ip next hop type */
+void route_map_match_ip_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type))
+{
+ rmap_match_set_hook.match_ip_next_hop_type = func;
+}
+
+/* no match ip next hop type */
+void route_map_no_match_ip_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type))
+{
+ rmap_match_set_hook.no_match_ip_next_hop_type = func;
+}
+
/* match ipv6 address */
void route_map_match_ipv6_address_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
rmap_match_set_hook.no_match_ipv6_address_prefix_list = func;
}
+/* match ipv6 next-hop type */
+void route_map_match_ipv6_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type))
+{
+ rmap_match_set_hook.match_ipv6_next_hop_type = func;
+}
+
+/* no match ipv6 next-hop type */
+void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
+}
+
/* match metric */
void route_map_match_metric_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
for (ALL_LIST_ELEMENTS_RO(maplist, ln, map))
vty_show_route_map_entry(vty, map);
- list_delete_and_null(&maplist);
+ list_delete(&maplist);
}
return CMD_SUCCESS;
}
return CMD_SUCCESS;
}
+DEFUN(match_ip_next_hop_type, match_ip_next_hop_type_cmd,
+ "match ip next-hop type <blackhole>",
+ MATCH_STR IP_STR
+ "Match next-hop address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 4;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.match_ip_next_hop_type)
+ return rmap_match_set_hook.match_ip_next_hop_type(
+ vty, index, "ip next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_ADDED);
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_match_ip_next_hop_type, no_match_ip_next_hop_type_cmd,
+ "no match ip next-hop type [<blackhole>]",
+ NO_STR MATCH_STR IP_STR
+ "Match next-hop address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 5;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.no_match_ip_next_hop) {
+ if (argc <= idx_word)
+ return rmap_match_set_hook.no_match_ip_next_hop(
+ vty, index, "ip next-hop type", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+ return rmap_match_set_hook.no_match_ip_next_hop(
+ vty, index, "ip next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_DELETED);
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (match_ipv6_address,
match_ipv6_address_cmd,
return CMD_SUCCESS;
}
+DEFUN(match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd,
+ "match ipv6 next-hop type <blackhole>",
+ MATCH_STR IPV6_STR
+ "Match address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 4;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.match_ipv6_next_hop_type)
+ return rmap_match_set_hook.match_ipv6_next_hop_type(
+ vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_ADDED);
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd,
+ "no match ipv6 next-hop type [<blackhole>]",
+ NO_STR MATCH_STR IPV6_STR
+ "Match address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 5;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.no_match_ipv6_next_hop_type)
+ return rmap_match_set_hook.no_match_ipv6_next_hop_type(
+ vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_DELETED);
+ return CMD_SUCCESS;
+}
DEFUN (match_metric,
match_metric_cmd,
install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
+ install_element(RMAP_NODE, &match_ip_next_hop_type_cmd);
+ install_element(RMAP_NODE, &no_match_ip_next_hop_type_cmd);
+
install_element(RMAP_NODE, &match_ipv6_address_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_type_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_next_hop_type_cmd);
+
install_element(RMAP_NODE, &match_metric_cmd);
install_element(RMAP_NODE, &no_match_metric_cmd);
extern void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
+/* match ip next hop type */
+extern void route_map_match_ip_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type));
+/* no match ip next hop type */
+extern void route_map_no_match_ip_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type));
/* match ipv6 address */
extern void route_map_match_ipv6_address_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
extern void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
+/* match ipv6 next-hop type */
+extern void route_map_match_ipv6_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type));
+/* no match ipv6 next-hop type */
+extern void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
+ struct vty *vty, struct route_map_index *index, const char *command,
+ const char *arg, route_map_event_t type));
/* match metric */
extern void route_map_match_metric_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
# libfrr
#
lib_LTLIBRARIES += lib/libfrr.la
-lib_libfrr_la_LDFLAGS = -version-info 0:0:0
+lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version
lib_libfrr_la_LIBADD = @LIBCAP@
lib_libfrr_la_SOURCES = \
lib/plist_int.h \
#end
+# General note about module and module helper library (libfrrsnmp, libfrrzmq)
+# linking: If we're linking libfrr statically into daemons, we *must* remove
+# libfrr from modules because modules will always link it in dynamically and
+# thus 2 copies of libfrr will be loaded... hilarity ensues.
+#
+# Not linking libfrr into modules should generally work fine because the
+# executable refers to libfrr either way and the dynamic linker should make
+# libfrr available to modules. If some OS platform has a dynamic linker that
+# doesn't do that, libfrr needs to be readded to modules, but _only_ _if_
+# it's not linked into daemons statically.
+
#
# SNMP support
#
lib_libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99
lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
-lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS)
+lib_libfrrsnmp_la_LIBADD = $(SNMP_LIBS)
lib_libfrrsnmp_la_SOURCES = \
lib/agentx.c \
lib/snmp.c \
lib_libfrrzmq_la_CFLAGS = $(WERROR) $(ZEROMQ_CFLAGS)
lib_libfrrzmq_la_LDFLAGS = -version-info 0:0:0
-lib_libfrrzmq_la_LIBADD = lib/libfrr.la $(ZEROMQ_LIBS)
+lib_libfrrzmq_la_LIBADD = $(ZEROMQ_LIBS)
lib_libfrrzmq_la_SOURCES = \
lib/frr_zmq.c \
#end
{
listnode_delete(masters, m);
if (masters->count == 0) {
- list_delete_and_null(&masters);
+ list_delete(&masters);
}
}
pthread_mutex_unlock(&masters_mtx);
pthread_cond_destroy(&m->cancel_cond);
close(m->io_pipe[0]);
close(m->io_pipe[1]);
- list_delete_and_null(&m->cancel_req);
+ list_delete(&m->cancel_req);
m->cancel_req = NULL;
hash_clean(m->cpu_record, cpu_record_hash_free);
int i;
for (i = 0; i < wheel->slots; i++) {
- list_delete_and_null(&wheel->wheel_slot_lists[i]);
+ list_delete(&wheel->wheel_slot_lists[i]);
}
THREAD_OFF(wheel->timer);
XFREE(MTYPE_REDIST_INST, id);
if (!red->instances->count) {
red->enabled = 0;
- list_delete_and_null(&red->instances);
+ list_delete(&red->instances);
}
}
*.m4
+!*.patch
!ax_compare_version.m4
!ax_prog_perl_modules.m4
--- /dev/null
+--- /usr/share/libtool/build-aux/ltmain.sh 2017-08-01 07:13:09.611041402 +0200
++++ ltmain.sh 2018-08-31 17:32:15.381903718 +0200
+@@ -8439,8 +8439,13 @@
+ # shared platforms.
+ if test unsupported != "$hardcode_direct"; then
+ test -n "$old_library" && linklib=$old_library
+- compile_deplibs="$dir/$linklib $compile_deplibs"
+- finalize_deplibs="$dir/$linklib $finalize_deplibs"
++ if test yes,yes = "$export_dynamic,$with_gnu_ld"; then
++ compile_deplibs="-Wl,--no-whole-archive $dir/$linklib -Wl,--whole-archive $compile_deplibs"
++ finalize_deplibs="-Wl,--no-whole-archive $dir/$linklib -Wl,--whole-archive $finalize_deplibs"
++ else
++ compile_deplibs="$dir/$linklib $compile_deplibs"
++ finalize_deplibs="$dir/$linklib $finalize_deplibs"
++ fi
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
/* AS External routes are never considered */
if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
|| route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
- if (is_debug)
- zlog_debug("Path type is external, skip");
+#if 0
+ zlog_debug("Path type is external, skip");
+#endif
return 0;
}
for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi))
oi->area = NULL;
- list_delete_and_null(&oa->if_list);
+ list_delete(&oa->if_list);
ospf6_lsdb_delete(oa->lsdb);
ospf6_lsdb_delete(oa->lsdb_self);
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
ospf6_neighbor_delete(on);
- list_delete_and_null(&oi->neighbor_list);
+ list_delete(&oi->neighbor_list);
THREAD_OFF(oi->thread_send_hello);
THREAD_OFF(oi->thread_send_lsupdate);
void ospf6_path_free(struct ospf6_path *op)
{
if (op->nh_list)
- list_delete_and_null(&op->nh_list);
+ list_delete(&op->nh_list);
XFREE(MTYPE_OSPF6_PATH, op);
}
{
if (route) {
if (route->nh_list)
- list_delete_and_null(&route->nh_list);
+ list_delete(&route->nh_list);
if (route->paths)
- list_delete_and_null(&route->paths);
+ list_delete(&route->paths);
XFREE(MTYPE_OSPF6_ROUTE, route);
}
}
static void ospf6_vertex_delete(struct ospf6_vertex *v)
{
- list_delete_and_null(&v->nh_list);
- list_delete_and_null(&v->child_list);
+ list_delete(&v->nh_list);
+ list_delete(&v->child_list);
XFREE(MTYPE_OSPF6_VERTEX, v);
}
ospf6_area_delete(oa);
- list_delete_and_null(&o->area_list);
+ list_delete(&o->area_list);
ospf6_lsdb_delete(o->lsdb);
ospf6_lsdb_delete(o->lsdb_self);
ospfclient_ospfclient_LDADD = \
ospfclient/libfrrospfapiclient.la \
- lib/libfrr.la \
@LIBCAP@ \
# end
+
+if STATIC_BIN
+# libfrr is linked in through libfrrospfapiclient. If we list it here too,
+# it gets linked twice and we get a ton of symbol collisions.
+
+else # !STATIC_BIN
+# For most systems we don't need this, except Debian, who patch their linker
+# to disallow transitive references *while* *als* not patching their libtool
+# to work appropriately. RedHat has the same linker behaviour, but things
+# work as expected since they also patch libtool.
+ospfclient_ospfclient_LDADD += lib/libfrr.la
+endif
+
ospfclient_ospfclient_SOURCES = \
ospfclient/ospfclient.c \
# end
/* Free client list itself */
if (apiserver_list)
- list_delete_and_null(&apiserver_list);
+ list_delete(&apiserver_list);
/* Free wildcard list */
/* XXX */
/* If none is found -- look through all. */
if (listcount(chosen) == 0) {
- list_delete_and_null(&chosen);
+ list_delete(&chosen);
chosen = rn->info;
}
}
if (chosen != rn->info)
- list_delete_and_null(&chosen);
+ list_delete(&chosen);
return best;
}
if ((lst = rn->info) != NULL) {
for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa))
ospf_lsa_unlock(&lsa); /* external_lsas lst */
- list_delete_and_null(&lst);
+ list_delete(&lst);
}
route_table_finish(rt);
}
/* Initialize debug commands. */
-void debug_init()
+void ospf_debug_init(void)
{
install_node(&debug_node, config_write_debug);
extern const char *ospf_timeval_dump(struct timeval *, char *, size_t);
extern void ospf_ip_header_dump(struct ip *);
extern void ospf_packet_dump(struct stream *);
-extern void debug_init(void);
+extern void ospf_debug_init(void);
/* Appropriate buffer size to use with ospf_timer_dump and ospf_timeval_dump: */
#define OSPF_TIME_DUMP_SIZE 16
ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
OPAQUE_TYPE_EXTENDED_LINK_LSA);
- list_delete_and_null(&OspfEXT.iflist);
+ list_delete(&OspfEXT.iflist);
OspfEXT.scope = 0;
OspfEXT.enabled = false;
route_table_finish(oi->ls_upd_queue);
/* Free any lists that should be freed */
- list_delete_and_null(&oi->nbr_nbma);
+ list_delete(&oi->nbr_nbma);
- list_delete_and_null(&oi->ls_ack);
- list_delete_and_null(&oi->ls_ack_direct.ls_ack);
+ list_delete(&oi->ls_ack);
+ list_delete(&oi->ls_ack_direct.ls_ack);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf interface %s vrf %s id %u deleted",
void ospf_del_if_params(struct ospf_if_params *oip)
{
- list_delete_and_null(&oip->auth_crypt);
+ list_delete(&oip->auth_crypt);
bfd_info_free(&(oip->bfd_info));
XFREE(MTYPE_OSPF_IF_PARAMS, oip);
}
else
DR(oi).s_addr = 0;
- list_delete_and_null(&dr_list);
+ list_delete(&dr_list);
return dr;
}
else
BDR(oi).s_addr = 0;
- list_delete_and_null(&bdr_list);
- list_delete_and_null(&no_dr_list);
+ list_delete(&bdr_list);
+ list_delete(&no_dr_list);
return bdr;
}
zlog_debug("DR-Election[2nd]: DR %s", inet_ntoa(DR(oi)));
}
- list_delete_and_null(&el_list);
+ list_delete(&el_list);
/* if DR or BDR changes, cause AdjOK? neighbor event. */
if (!IPV4_ADDR_SAME(&old_dr, &DR(oi))
ospf->lsa_refresh_queue.qs[lsa->refresh_list];
listnode_delete(refresh_list, lsa);
if (!listcount(refresh_list)) {
- list_delete_and_null(&refresh_list);
+ list_delete(&refresh_list);
ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL;
}
ospf_lsa_unlock(&lsa); /* lsa_refresh_queue */
lsa->refresh_list = -1;
listnode_add(lsa_to_refresh, lsa);
}
- list_delete_and_null(&refresh_list);
+ list_delete(&refresh_list);
}
}
&lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/
}
- list_delete_and_null(&lsa_to_refresh);
+ list_delete(&lsa_to_refresh);
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
master = om->master;
/* Library inits. */
- debug_init();
+ ospf_debug_init();
ospf_vrf_init();
access_list_init();
int ospf_opaque_type9_lsa_init(struct ospf_interface *oi)
{
if (oi->opaque_lsa_self != NULL)
- list_delete_and_null(&oi->opaque_lsa_self);
+ list_delete(&oi->opaque_lsa_self);
oi->opaque_lsa_self = list_new();
oi->opaque_lsa_self->del = free_opaque_info_per_type;
{
OSPF_TIMER_OFF(oi->t_opaque_lsa_self);
if (oi->opaque_lsa_self != NULL)
- list_delete_and_null(&oi->opaque_lsa_self);
+ list_delete(&oi->opaque_lsa_self);
oi->opaque_lsa_self = NULL;
return;
}
int ospf_opaque_type10_lsa_init(struct ospf_area *area)
{
if (area->opaque_lsa_self != NULL)
- list_delete_and_null(&area->opaque_lsa_self);
+ list_delete(&area->opaque_lsa_self);
area->opaque_lsa_self = list_new();
area->opaque_lsa_self->del = free_opaque_info_per_type;
OSPF_TIMER_OFF(area->t_opaque_lsa_self);
if (area->opaque_lsa_self != NULL)
- list_delete_and_null(&area->opaque_lsa_self);
+ list_delete(&area->opaque_lsa_self);
return;
}
int ospf_opaque_type11_lsa_init(struct ospf *top)
{
if (top->opaque_lsa_self != NULL)
- list_delete_and_null(&top->opaque_lsa_self);
+ list_delete(&top->opaque_lsa_self);
top->opaque_lsa_self = list_new();
top->opaque_lsa_self->del = free_opaque_info_per_type;
OSPF_TIMER_OFF(top->t_opaque_lsa_self);
if (top->opaque_lsa_self != NULL)
- list_delete_and_null(&top->opaque_lsa_self);
+ list_delete(&top->opaque_lsa_self);
return;
}
struct list *funclist;
funclist = ospf_opaque_wildcard_funclist;
- list_delete_and_null(&funclist);
+ list_delete(&funclist);
funclist = ospf_opaque_type9_funclist;
- list_delete_and_null(&funclist);
+ list_delete(&funclist);
funclist = ospf_opaque_type10_funclist;
- list_delete_and_null(&funclist);
+ list_delete(&funclist);
funclist = ospf_opaque_type11_funclist;
- list_delete_and_null(&funclist);
+ list_delete(&funclist);
return;
}
}
OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
- list_delete_and_null(&oipt->id_list);
+ list_delete(&oipt->id_list);
XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
return;
}
if (listcount(update) > 0)
ospf_ls_upd_send(nbr, update, OSPF_SEND_PACKET_DIRECT,
0);
- list_delete_and_null(&update);
+ list_delete(&update);
}
/* Set LS Update retransmission timer. */
/* Verify LSA type. */
if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA) {
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq);
- list_delete_and_null(&ls_upd);
+ list_delete(&ls_upd);
return;
}
adv_router);
if (find == NULL) {
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq);
- list_delete_and_null(&ls_upd);
+ list_delete(&ls_upd);
return;
}
ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT,
0);
- list_delete_and_null(&ls_upd);
+ list_delete(&ls_upd);
} else
- list_delete_and_null(&ls_upd);
+ list_delete(&ls_upd);
}
/* Get the list of LSAs from Link State Update packet.
for (ALL_LIST_ELEMENTS(lsas, node, nnode, lsa))
ospf_lsa_discard(lsa);
- list_delete_and_null(&lsas);
+ list_delete(&lsas);
}
/* OSPF Link State Update message read -- RFC2328 Section 13. */
#undef DISCARD_LSA
assert(listcount(lsas) == 0);
- list_delete_and_null(&lsas);
+ list_delete(&lsas);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
else
ospf_ls_upd_send(nbr, update, flag, 0);
- list_delete_and_null(&update);
+ list_delete(&update);
}
/* Determine size for packet. Must be at least big enough to accomodate next
/* list might not be empty. */
if (listcount(update) == 0) {
- list_delete_and_null((struct list **)&rn->info);
+ list_delete((struct list **)&rn->info);
route_unlock_node(rn);
} else
again = 1;
void ospf_router_info_term(void)
{
- list_delete_and_null(&OspfRI.pce_info.pce_domain);
- list_delete_and_null(&OspfRI.pce_info.pce_neighbor);
+ list_delete(&OspfRI.pce_info.pce_domain);
+ list_delete(&OspfRI.pce_info.pce_neighbor);
OspfRI.enabled = false;
void ospf_route_free(struct ospf_route * or)
{
if (or->paths)
- list_delete_and_null(& or->paths);
+ list_delete(& or->paths);
XFREE(MTYPE_OSPF_ROUTE, or);
}
zlog_debug("Pruning router node %s",
inet_ntoa(rn->p.u.prefix4));
- list_delete_and_null(&paths);
+ list_delete(&paths);
rn->info = NULL;
route_unlock_node(rn);
}
// assert (listcount (v->parents) == 0);
if (v->children)
- list_delete_and_null(&v->children);
+ list_delete(&v->children);
if (v->parents)
- list_delete_and_null(&v->parents);
+ list_delete(&v->parents);
v->lsa = NULL;
for (ALL_LIST_ELEMENTS(or_list, node, nnode, or))
ospf_route_free(or);
- list_delete_and_null(&or_list);
+ list_delete(&or_list);
/* Unlock the node. */
rn->info = NULL;
return;
/* Clean Extended Link */
- list_delete_and_null(&srn->ext_link);
+ list_delete(&srn->ext_link);
/* Clean Prefix List */
- list_delete_and_null(&srn->ext_prefix);
+ list_delete(&srn->ext_prefix);
XFREE(MTYPE_OSPF_SR_PARAMS, srn);
}
/*
* Remove all SR Nodes from the Hash table. Prefix and Link SID will
- * be remove though list_delete_and_null() call. See sr_node_del()
+ * be remove though list_delete() call. See sr_node_del()
*/
hash_clean(OspfSR.neighbors, (void *)sr_node_del);
}
void ospf_mpls_te_term(void)
{
- list_delete_and_null(&OspfMplsTE.iflist);
+ list_delete(&OspfMplsTE.iflist);
ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
listnode_delete(ospf->external[type], ext);
if (!ospf->external[type]->count)
- list_delete_and_null(&ospf->external[type]);
+ list_delete(&ospf->external[type]);
XFREE(MTYPE_OSPF_EXTERNAL, ext);
}
if (red) {
listnode_delete(ospf->redist[type], red);
if (!ospf->redist[type]->count) {
- list_delete_and_null(&ospf->redist[type]);
+ list_delete(&ospf->redist[type]);
}
ospf_routemap_unset(red);
XFREE(MTYPE_OSPF_REDISTRIBUTE, red);
for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
ospf_vl_delete(ospf, vl_data);
- list_delete_and_null(&ospf->vlinks);
+ list_delete(&ospf->vlinks);
/* Remove any ospf interface config params */
FOR_ALL_INTERFACES (vrf, ifp) {
/* Reset interface. */
for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
ospf_if_free(oi);
- list_delete_and_null(&ospf->oiflist);
+ list_delete(&ospf->oiflist);
/* De-Register VRF */
ospf_zebra_vrf_deregister(ospf);
ospf_ase_external_lsas_finish(ospf->external_lsas);
}
- list_delete_and_null(&ospf->areas);
- list_delete_and_null(&ospf->oi_write_q);
+ list_delete(&ospf->areas);
+ list_delete(&ospf->oi_write_q);
for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) {
struct list *ext_list;
ospf_lsa_unlock(&area->router_lsa_self);
route_table_finish(area->ranges);
- list_delete_and_null(&area->oiflist);
+ list_delete(&area->oiflist);
if (EXPORT_NAME(area))
free(EXPORT_NAME(area));
if ((lst = (struct list *)rn->info)) {
for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa))
ospf_lsa_unlock(&lsa); /* oi->ls_upd_queue */
- list_delete_and_null(&lst);
+ list_delete(&lst);
rn->info = NULL;
}
#define FREE_ADDR_LIST \
if (hello_option_addr_list) { \
- list_delete_and_null(&hello_option_addr_list); \
+ list_delete(&hello_option_addr_list); \
}
#define FREE_ADDR_LIST_THEN_RETURN(code) \
pim_if_del_vif(ifp);
- list_delete_and_null(&pim_ifp->igmp_socket_list);
- list_delete_and_null(&pim_ifp->pim_neighbor_list);
- list_delete_and_null(&pim_ifp->upstream_switch_list);
- list_delete_and_null(&pim_ifp->sec_addr_list);
+ list_delete(&pim_ifp->igmp_socket_list);
+ list_delete(&pim_ifp->pim_neighbor_list);
+ list_delete(&pim_ifp->upstream_switch_list);
+ list_delete(&pim_ifp->sec_addr_list);
if (pim_ifp->boundary_oil_plist)
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
listnode_delete(pim_ifp->igmp_join_list, ij);
igmp_join_free(ij);
if (listcount(pim_ifp->igmp_join_list) < 1) {
- list_delete_and_null(&pim_ifp->igmp_join_list);
+ list_delete(&pim_ifp->igmp_join_list);
pim_ifp->igmp_join_list = 0;
}
pim_ifchannel_remove_children(ch);
if (ch->sources)
- list_delete_and_null(&ch->sources);
+ list_delete(&ch->sources);
listnode_delete(ch->upstream->ifchannels, ch);
static void igmp_group_free(struct igmp_group *group)
{
- list_delete_and_null(&group->group_source_list);
+ list_delete(&group->group_source_list);
XFREE(MTYPE_PIM_IGMP_GROUP, group);
}
zassert(igmp->igmp_group_list);
zassert(!listcount(igmp->igmp_group_list));
- list_delete_and_null(&igmp->igmp_group_list);
+ list_delete(&igmp->igmp_group_list);
hash_free(igmp->igmp_group_hash);
XFREE(MTYPE_PIM_IGMP_SOCKET, igmp);
}
if (pim->static_routes)
- list_delete_and_null(&pim->static_routes);
+ list_delete(&pim->static_routes);
pim_upstream_terminate(pim);
void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag)
{
- list_delete_and_null(&jag->sources);
+ list_delete(&jag->sources);
XFREE(MTYPE_PIM_JP_AGG_GROUP, jag);
}
js->up = NULL;
XFREE(MTYPE_PIM_JP_AGG_SOURCE, js);
}
- list_delete_and_null(&jag->sources);
+ list_delete(&jag->sources);
listnode_delete(group, jag);
XFREE(MTYPE_PIM_JP_AGG_GROUP, jag);
}
}
if (jag->sources->count == 0) {
- list_delete_and_null(&jag->sources);
+ list_delete(&jag->sources);
listnode_delete(group, jag);
XFREE(MTYPE_PIM_JP_AGG_GROUP, jag);
}
XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name);
if (mg->mbr_list)
- list_delete_and_null(&mg->mbr_list);
+ list_delete(&mg->mbr_list);
XFREE(MTYPE_PIM_MSDP_MG, pim->msdp.mg);
}
}
if (pim->msdp.peer_list) {
- list_delete_and_null(&pim->msdp.peer_list);
+ list_delete(&pim->msdp.peer_list);
}
if (pim->msdp.sa_hash) {
}
if (pim->msdp.sa_list) {
- list_delete_and_null(&pim->msdp.sa_list);
+ list_delete(&pim->msdp.sa_list);
}
if (pim->msdp.work_obuf)
}
#endif
- list_delete_and_null(&neigh->prefix_list);
+ list_delete(&neigh->prefix_list);
}
}
delete_prefix_list(neigh);
- list_delete_and_null(&neigh->upstream_jp_agg);
+ list_delete(&neigh->upstream_jp_agg);
THREAD_OFF(neigh->jp_timer);
if (neigh->bfd_info)
pim_sendmsg_zebra_rnh(pim, zclient, pnc,
ZEBRA_NEXTHOP_UNREGISTER);
- list_delete_and_null(&pnc->rp_list);
+ list_delete(&pnc->rp_list);
hash_free(pnc->upstream_hash);
hash_release(pim->rpf_hash, pnc);
void pim_oil_terminate(struct pim_instance *pim)
{
if (pim->channel_oil_list)
- list_delete_and_null(&pim->channel_oil_list);
+ list_delete(&pim->channel_oil_list);
if (pim->channel_oil_hash)
hash_free(pim->channel_oil_hash);
{
struct pim_nexthop_cache *pnc = (struct pim_nexthop_cache *)data;
- list_delete_and_null(&pnc->rp_list);
+ list_delete(&pnc->rp_list);
hash_clean(pnc->upstream_hash, NULL);
hash_free(pnc->upstream_hash);
if (!str2prefix("224.0.0.0/4", &rp_info->group)) {
flog_err(EC_LIB_DEVELOPMENT,
"Unable to convert 224.0.0.0/4 to prefix");
- list_delete_and_null(&pim->rp_list);
+ list_delete(&pim->rp_list);
route_table_finish(pim->rp_table);
XFREE(MTYPE_PIM_RP, rp_info);
return;
void pim_rp_free(struct pim_instance *pim)
{
if (pim->rp_list)
- list_delete_and_null(&pim->rp_list);
+ list_delete(&pim->rp_list);
}
/*
void pim_ssmpingd_destroy(struct pim_instance *pim)
{
if (pim->ssmpingd_list)
- list_delete_and_null(&pim->ssmpingd_list);
+ list_delete(&pim->ssmpingd_list);
}
static struct ssmpingd_sock *ssmpingd_find(struct pim_instance *pim,
#define FREE_ADDR_LIST(hello_option_addr_list) \
{ \
if (hello_option_addr_list) { \
- list_delete_and_null(&hello_option_addr_list); \
+ list_delete(&hello_option_addr_list); \
hello_option_addr_list = 0; \
} \
}
if (child)
child->parent = NULL;
}
- list_delete_and_null(&up->sources);
+ list_delete(&up->sources);
}
/*
for (ALL_LIST_ELEMENTS(up->ifchannels, node, nnode, ch))
pim_ifchannel_delete(ch);
- list_delete_and_null(&up->ifchannels);
+ list_delete(&up->ifchannels);
pim_upstream_remove_children(pim, up);
if (up->sources)
- list_delete_and_null(&up->sources);
+ list_delete(&up->sources);
if (up->parent && up->parent->sources)
listnode_delete(up->parent->sources, up);
pim_upstream_remove_children(pim, up);
if (up->sources)
- list_delete_and_null(&up->sources);
+ list_delete(&up->sources);
- list_delete_and_null(&up->ifchannels);
+ list_delete(&up->ifchannels);
hash_release(pim->upstream_hash, up);
XFREE(MTYPE_PIM_UPSTREAM, up);
pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
}
- list_delete_and_null(&pim->upstream_list);
+ list_delete(&pim->upstream_list);
}
if (pim->upstream_hash)
void rip_offset_clean()
{
- list_delete_and_null(&rip_offset_list_master);
+ list_delete(&rip_offset_list_master);
rip_offset_list_master = list_new();
rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
/* Unlock route_node. */
listnode_delete(rp->info, rinfo);
if (list_isempty((struct list *)rp->info)) {
- list_delete_and_null((struct list **)&rp->info);
+ list_delete((struct list **)&rp->info);
route_unlock_node(rp);
}
RIP_TIMER_OFF(rinfo->t_garbage_collect);
rip_info_free(rinfo);
}
- list_delete_and_null(&list);
+ list_delete(&list);
rp->info = NULL;
route_unlock_node(rp);
}
void ripng_rte_free(struct list *ripng_rte_list)
{
- list_delete_and_null(&ripng_rte_list);
+ list_delete(&ripng_rte_list);
}
/* Delete RTE */
void ripng_offset_clean(void)
{
- list_delete_and_null(&ripng_offset_list_master);
+ list_delete(&ripng_offset_list_master);
ripng_offset_list_master = list_new();
ripng_offset_list_master->cmp =
/* Unlock route_node. */
listnode_delete(rp->info, rinfo);
if (list_isempty((struct list *)rp->info)) {
- list_delete_and_null((struct list **)&rp->info);
+ list_delete((struct list **)&rp->info);
agg_unlock_node(rp);
}
}
if (list_isempty(list)) {
- list_delete_and_null(&list);
+ list_delete(&list);
rp->info = NULL;
agg_unlock_node(rp);
}
rinfo->t_garbage_collect);
ripng_info_free(rinfo);
}
- list_delete_and_null(&list);
+ list_delete(&list);
rp->info = NULL;
agg_unlock_node(rp);
}
check_lookup_result(list, arglist);
- list_delete_and_null(&list);
+ list_delete(&list);
va_end(arglist);
test->vty = NULL;
}
if (test->log)
- list_delete_and_null(&test->log);
+ list_delete(&test->log);
if (test->desc)
XFREE(MTYPE_TMP, test->desc);
if (test->error)
bgp_zebra_destroy();
bf_free(bm->rd_idspace);
- list_delete_and_null(&bm->bgp);
+ list_delete(&bm->bgp);
memset(bm, 0, sizeof(*bm));
vty_terminate();
XFREE(MTYPE_TMP, pa);
}
- list_delete_and_null(&pa_list);
+ list_delete(&pa_list);
bgp_shutdown();
return 0;
sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs));
isis_free_tlvs(tlvs);
}
- list_delete_and_null(&fragments);
+ list_delete(&fragments);
stream_free(s);
char *fragment_content = sortlines((char *)sbuf_buf(&fragment_format));
--- /dev/null
+#!/bin/sh
+#
+# Written by Daniil Baturin, 2018
+# This file is public domain
+
+git diff-index --quiet HEAD || echo "Warning: git working directory is not clean!"
+
+# Set the defaults
+if [ "$EXTRA_VERSION" = "" ]; then
+ EXTRA_VERSION="-MyDebPkgVersion"
+fi
+
+if [ "$WANT_SNMP" = "" ]; then
+ WANT_SNMP=0
+fi
+
+if [ "$WANT_CUMULUS_MODE" = "" ]; then
+ WANT_CUMULUS_MODE=0
+fi
+
+echo "Preparing the build"
+./bootstrap.sh
+./configure --with-pkg-extra-version=$EXTRA_VERSION
+make dist
+
+echo "Preparing Debian source package"
+mv debianpkg debian
+make -f debian/rules backports
+
+echo "Unpacking the source to frrpkg/"
+mkdir frrpkg
+cd frrpkg
+tar xf ../frr_*.orig.tar.gz
+cd frr*
+. /etc/os-release
+tar xf ../../frr_*${ID}${VERSION_ID}*.debian.tar.xz
+
+echo "Building the Debian package"
+debuild --no-lintian --set-envvar=WANT_SNMP=$WANT_SNMP --set-envvar=WANT_CUMULUS_MODE=$WANT_CUMULUS_MODE -b -uc -us
+
tools/rrlookup.pl \
tools/zc.pl \
tools/zebra.el \
+ tools/build-debian-package.sh \
# end
static void config_del(struct config *config)
{
- list_delete_and_null(&config->line);
+ list_delete(&config->line);
if (config->name)
XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
XFREE(MTYPE_VTYSH_CONFIG, config);
for (i = 0; i < vector_active(configvec); i++)
if ((master = vector_slot(configvec, i)) != NULL) {
- list_delete_and_null(&master);
+ list_delete(&master);
vector_slot(configvec, i) = NULL;
}
list_delete_all_node(config_top);
struct route_node *node)
{
if (node->info)
- list_delete_and_null((struct list **)&node->info);
+ list_delete((struct list **)&node->info);
route_node_destroy(delegate, table, node);
}
struct rtadvconf *rtadv;
rtadv = &zebra_if->rtadv;
- list_delete_and_null(&rtadv->AdvPrefixList);
+ list_delete(&rtadv->AdvPrefixList);
#endif /* HAVE_RTADV */
THREAD_OFF(zebra_if->speed_update);
}
/* Otherwise, free list and route node. */
- list_delete_and_null(&addr_list);
+ list_delete(&addr_list);
rn->info = NULL;
route_unlock_node(rn);
}
/* Free chain list and respective route node. */
- list_delete_and_null(&addr_list);
+ list_delete(&addr_list);
rn->info = NULL;
route_unlock_node(rn);
} else if (cp.family == AF_INET6) {
irdp_advert_off(ifp);
- list_delete_and_null(&irdp->AdvPrefList);
+ list_delete(&irdp->AdvPrefList);
irdp->flags = 0;
}
void label_manager_close()
{
- list_delete_and_null(&lbl_mgr.lc_list);
+ list_delete(&lbl_mgr.lc_list);
stream_free(obuf);
}
prefix_list_reset();
route_map_finish();
- list_delete_and_null(&zebrad.client_list);
+ list_delete(&zebrad.client_list);
work_queue_free_and_null(&zebrad.ribq);
meta_queue_free(zebrad.mq);
{
if (ns_id != NS_DEFAULT)
return;
- list_delete_and_null(&tbl_mgr.lc_list);
+ list_delete(&tbl_mgr.lc_list);
}
*/
static int fec_del(zebra_fec_t *fec)
{
- list_delete_and_null(&fec->client_list);
+ list_delete(&fec->client_list);
fec->rn->info = NULL;
route_unlock_node(fec->rn);
XFREE(MTYPE_FEC, fec);
vty_out(vty, "\n");
}
- list_delete_and_null(&lsp_list);
+ list_delete(&lsp_list);
}
/*
}
}
- list_delete_and_null(&slsp_list);
+ list_delete(&slsp_list);
return (zvrf->slsp_table->count ? 1 : 0);
}
unsigned i;
for (i = 0; i < MQ_SIZE; i++)
- list_delete_and_null(&mq->subq[i]);
+ list_delete(&mq->subq[i]);
XFREE(MTYPE_WORK_QUEUE, mq);
}
void zebra_free_rnh(struct rnh *rnh)
{
rnh->flags |= ZEBRA_NHT_DELETED;
- list_delete_and_null(&rnh->client_list);
- list_delete_and_null(&rnh->zebra_pseudowire_list);
+ list_delete(&rnh->client_list);
+ list_delete(&rnh->zebra_pseudowire_list);
free_state(rnh->vrf_id, rnh->state, rnh->node);
XFREE(MTYPE_RNH, rnh);
}
{
zebra_mac_t *tmp_mac;
- list_delete_and_null(&mac->neigh_list);
+ list_delete(&mac->neigh_list);
/* Free the VNI hash entry and allocated memory. */
tmp_mac = hash_release(zvni->mac_table, mac);
assert(zns);
/* free the list of l2vnis */
- list_delete_and_null(&zl3vni->l2vnis);
+ list_delete(&zl3vni->l2vnis);
zl3vni->l2vnis = NULL;
/* Free the rmac table */