summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_addpath.c25
-rw-r--r--bgpd/bgp_addpath.h12
-rw-r--r--bgpd/bgp_advertise.c19
-rw-r--r--bgpd/bgp_advertise.h4
-rw-r--r--bgpd/bgp_aspath.c16
-rw-r--r--bgpd/bgp_aspath.h2
-rw-r--r--bgpd/bgp_attr.c138
-rw-r--r--bgpd/bgp_attr.h9
-rw-r--r--bgpd/bgp_attr_evpn.c12
-rw-r--r--bgpd/bgp_attr_evpn.h2
-rw-r--r--bgpd/bgp_bfd.c27
-rw-r--r--bgpd/bgp_bfd.h4
-rw-r--r--bgpd/bgp_bmp.c3
-rw-r--r--bgpd/bgp_btoa.c4
-rw-r--r--bgpd/bgp_clist.c136
-rw-r--r--bgpd/bgp_clist.h14
-rw-r--r--bgpd/bgp_community.c19
-rw-r--r--bgpd/bgp_community.h4
-rw-r--r--bgpd/bgp_debug.c81
-rw-r--r--bgpd/bgp_debug.h12
-rw-r--r--bgpd/bgp_ecommunity.c93
-rw-r--r--bgpd/bgp_ecommunity.h27
-rw-r--r--bgpd/bgp_evpn.c72
-rw-r--r--bgpd/bgp_evpn.h12
-rw-r--r--bgpd/bgp_evpn_private.h11
-rw-r--r--bgpd/bgp_evpn_vty.c10
-rw-r--r--bgpd/bgp_filter.c26
-rw-r--r--bgpd/bgp_filter.h2
-rw-r--r--bgpd/bgp_flowspec.h2
-rw-r--r--bgpd/bgp_flowspec_util.c15
-rw-r--r--bgpd/bgp_flowspec_util.h7
-rw-r--r--bgpd/bgp_flowspec_vty.c2
-rw-r--r--bgpd/bgp_fsm.c92
-rw-r--r--bgpd/bgp_fsm.h7
-rw-r--r--bgpd/bgp_lcommunity.c32
-rw-r--r--bgpd/bgp_lcommunity.h6
-rw-r--r--bgpd/bgp_mplsvpn.c31
-rw-r--r--bgpd/bgp_nexthop.c59
-rw-r--r--bgpd/bgp_nexthop.h21
-rw-r--r--bgpd/bgp_open.c6
-rw-r--r--bgpd/bgp_packet.c35
-rw-r--r--bgpd/bgp_rd.c6
-rw-r--r--bgpd/bgp_rd.h6
-rw-r--r--bgpd/bgp_route.c231
-rw-r--r--bgpd/bgp_route.h56
-rw-r--r--bgpd/bgp_routemap.c75
-rw-r--r--bgpd/bgp_rpki.c58
-rw-r--r--bgpd/bgp_snmp.c2
-rw-r--r--bgpd/bgp_table.c3
-rw-r--r--bgpd/bgp_table.h11
-rw-r--r--bgpd/bgp_updgrp.c62
-rw-r--r--bgpd/bgp_updgrp.h10
-rw-r--r--bgpd/bgp_updgrp_packet.c16
-rw-r--r--bgpd/bgp_vty.c19
-rw-r--r--bgpd/bgp_zebra.c65
-rw-r--r--bgpd/bgp_zebra.h10
-rw-r--r--bgpd/bgpd.c81
-rw-r--r--bgpd/bgpd.h109
-rw-r--r--bgpd/rfapi/rfapi_backend.h2
-rw-r--r--bgpd/rfapi/rfapi_import.c2
-rw-r--r--bgpd/rfapi/rfapi_vty.c2
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c2
-rwxr-xr-xconfigure.ac316
-rw-r--r--doc/developer/building-frr-for-archlinux.rst129
-rw-r--r--doc/developer/building-frr-for-centos6.rst14
-rw-r--r--doc/developer/building.rst1
-rw-r--r--doc/user/ldpd.rst5
-rw-r--r--doc/user/nhrpd.rst25
-rw-r--r--doc/user/overview.rst6
-rw-r--r--doc/user/pim.rst8
-rw-r--r--doc/user/routemap.rst11
-rw-r--r--doc/user/sharp.rst17
-rw-r--r--isisd/isis_bpf.c2
-rw-r--r--isisd/isis_cli.c4
-rw-r--r--isisd/isis_dlpi.c2
-rw-r--r--isisd/isis_misc.c18
-rw-r--r--isisd/isis_pdu.c2
-rw-r--r--isisd/isis_tlvs.c4
-rw-r--r--isisd/isis_vty_fabricd.c16
-rw-r--r--ldpd/lde.c90
-rw-r--r--ldpd/lde.h2
-rw-r--r--ldpd/lde_lib.c91
-rw-r--r--ldpd/ldp_vty.h1
-rw-r--r--ldpd/ldp_vty_cmds.c10
-rw-r--r--ldpd/ldp_vty_conf.c16
-rw-r--r--ldpd/ldpd.c8
-rw-r--r--ldpd/ldpd.h2
-rw-r--r--lib/agg_table.h6
-rw-r--r--lib/lib_vty.c2
-rw-r--r--lib/libfrr.h3
-rw-r--r--lib/memory.h3
-rw-r--r--lib/mlag.c5
-rw-r--r--lib/monotime.h20
-rw-r--r--lib/ntop.c2
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/stream.h3
-rw-r--r--lib/zclient.c5
-rw-r--r--lib/zclient.h2
-rw-r--r--m4/ax_python.m42
-rw-r--r--nhrpd/netlink_arp.c41
-rw-r--r--nhrpd/nhrp_cache.c86
-rw-r--r--nhrpd/nhrp_peer.c134
-rw-r--r--nhrpd/nhrp_shortcut.c89
-rw-r--r--nhrpd/nhrp_vty.c277
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospfd/ospf_nsm.c2
-rw-r--r--ospfd/ospf_packet.c2
-rw-r--r--pimd/pim_cmd.c157
-rw-r--r--pimd/pim_iface.c12
-rw-r--r--pimd/pim_ifchannel.c6
-rw-r--r--pimd/pim_ifchannel.h19
-rw-r--r--pimd/pim_instance.c3
-rw-r--r--pimd/pim_instance.h4
-rw-r--r--pimd/pim_join.c21
-rw-r--r--pimd/pim_memory.c2
-rw-r--r--pimd/pim_memory.h2
-rw-r--r--pimd/pim_mroute.c10
-rw-r--r--pimd/pim_neighbor.c11
-rw-r--r--pimd/pim_register.c56
-rw-r--r--pimd/pim_rp.c11
-rw-r--r--pimd/pim_upstream.c8
-rw-r--r--pimd/pim_vty.c5
-rw-r--r--pimd/pim_vxlan.c15
-rw-r--r--pimd/pim_zebra.c7
-rw-r--r--ripd/rip_peer.c15
-rw-r--r--ripngd/ripng_peer.c15
-rw-r--r--sharpd/sharp_vty.c122
-rw-r--r--sharpd/sharp_zebra.c92
-rw-r--r--sharpd/sharp_zebra.h4
-rw-r--r--staticd/static_vty.c8
-rw-r--r--tests/bgpd/test_aspath.c29
-rw-r--r--tests/bgpd/test_aspath.py2
-rw-r--r--tests/bgpd/test_mp_attr.c21
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin206007 -> 182891 bytes
-rwxr-xr-xtests/topotests/all-protocol-startup/test_all_protocol_startup.py4
-rwxr-xr-xtests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py6
-rwxr-xr-xtests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py9
-rw-r--r--tests/topotests/bgp_prefix_sid/__init__.py0
-rw-r--r--tests/topotests/bgp_prefix_sid/exabgp.env53
-rw-r--r--tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg103
-rwxr-xr-xtests/topotests/bgp_prefix_sid/peer2/exa-receive.py37
-rw-r--r--tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg19
-rw-r--r--tests/topotests/bgp_prefix_sid/r1/bgpd.conf15
-rw-r--r--tests/topotests/bgp_prefix_sid/r1/zebra.conf7
-rwxr-xr-xtests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py173
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/ldpd.conf25
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf7
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json12
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref171
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref55
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref11
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref10
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf17
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf28
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf7
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json31
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref209
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref63
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref18
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref16
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf27
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf24
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf8
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json20
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref209
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref62
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref11
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref10
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf22
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf24
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf7
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json21
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref196
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref68
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref2
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref2
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf17
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot76
-rwxr-xr-xtests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py227
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/ldpd.conf24
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/ospfd.conf7
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json12
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref171
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref61
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref11
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref10
-rw-r--r--tests/topotests/ldp-oc-topo1/r1/zebra.conf17
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/ldpd.conf28
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/ospfd.conf7
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json31
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref209
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref63
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref18
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref16
-rw-r--r--tests/topotests/ldp-oc-topo1/r2/zebra.conf27
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/ldpd.conf24
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/ospfd.conf8
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json20
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref209
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref61
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref11
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref10
-rw-r--r--tests/topotests/ldp-oc-topo1/r3/zebra.conf22
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/ldpd.conf24
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/ospfd.conf7
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json21
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref196
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref68
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref2
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref2
-rw-r--r--tests/topotests/ldp-oc-topo1/r4/zebra.conf17
-rw-r--r--tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot76
-rwxr-xr-xtests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py227
-rw-r--r--tests/topotests/ldp-topo1/r1/ip_mpls_route.ref1
-rw-r--r--tests/topotests/lib/bgp.py4
-rwxr-xr-xtests/topotests/ospf6-topo1/test_ospf6_topo1.py12
-rw-r--r--tests/topotests/pim-basic/r1/pimd.conf4
-rw-r--r--tests/topotests/pim-basic/r1/zebra.conf3
-rw-r--r--tests/topotests/pim-basic/r3/pimd.conf1
-rw-r--r--tests/topotests/pim-basic/r3/zebra.conf8
-rw-r--r--tests/topotests/pim-basic/rp/pimd.conf3
-rw-r--r--tests/topotests/pim-basic/test_pim.py13
-rw-r--r--tools/coccinelle/int_to_bool_function.cocci24
-rw-r--r--zebra/main.c9
-rw-r--r--zebra/redistribute.c3
-rw-r--r--zebra/rt_netlink.c93
-rw-r--r--zebra/zapi_msg.c20
-rw-r--r--zebra/zebra_mlag.c4
-rw-r--r--zebra/zebra_ptm_redistribute.c3
-rw-r--r--zebra/zebra_rnh.c2
-rw-r--r--zebra/zebra_routemap.c9
-rw-r--r--zebra/zebra_routemap.h1
-rw-r--r--zebra/zebra_vty.c45
-rw-r--r--zebra/zserv.c42
-rw-r--r--zebra/zserv.h2
235 files changed, 6813 insertions, 1433 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
index aaa77b04d..75fdb0bb4 100644
--- a/bgpd/bgp_addpath.c
+++ b/bgpd/bgp_addpath.c
@@ -65,8 +65,8 @@ bgp_addpath_names(enum bgp_addpath_strat strat)
/*
* 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)
+bool bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi,
+ safi_t safi)
{
return d->total_peercount[afi][safi] > 0;
}
@@ -123,15 +123,15 @@ uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi,
* 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)
+bool 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 true;
- return 0;
+ return false;
}
/*
@@ -152,7 +152,7 @@ void bgp_addpath_free_node_data(struct bgp_addpath_bgp_data *bd,
/*
* Check to see if the addpath strategy requires DMED to be configured to work.
*/
-int bgp_addpath_dmed_required(int strategy)
+bool bgp_addpath_dmed_required(int strategy)
{
return strategy == BGP_ADDPATH_BEST_PER_AS;
}
@@ -161,21 +161,20 @@ 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)
+bool bgp_addpath_tx_path(enum bgp_addpath_strat strat, struct bgp_path_info *pi)
{
switch (strat) {
case BGP_ADDPATH_NONE:
- return 0;
+ return false;
case BGP_ADDPATH_ALL:
- return 1;
+ return true;
case BGP_ADDPATH_BEST_PER_AS:
if (CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))
- return 1;
+ return true;
else
- return 0;
+ return false;
default:
- return 0;
+ return false;
}
}
diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h
index 786873a00..f61d68e18 100644
--- a/bgpd/bgp_addpath.h
+++ b/bgpd/bgp_addpath.h
@@ -32,8 +32,8 @@
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);
+bool 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,
@@ -43,7 +43,7 @@ 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);
+bool 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);
@@ -51,14 +51,14 @@ uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi,
const struct bgp_addpath_strategy_names *
bgp_addpath_names(enum bgp_addpath_strat strat);
-int bgp_addpath_dmed_required(int strategy);
+bool 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);
+bool bgp_addpath_tx_path(enum bgp_addpath_strat strat,
+ struct bgp_path_info *pi);
/*
* Change the type of addpath used for a peer.
*/
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 8d1c83cf5..9ee6a24bc 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -144,8 +144,8 @@ void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa)
}
}
-int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
- uint32_t addpath_tx_id)
+bool bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
+ uint32_t addpath_tx_id)
{
struct bgp_adj_out *adj;
struct peer_af *paf;
@@ -169,11 +169,12 @@ int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
&& adj->addpath_tx_id != addpath_tx_id)
continue;
- return (adj->adv ? (adj->adv->baa ? 1 : 0)
- : (adj->attr ? 1 : 0));
+ return (adj->adv
+ ? (adj->adv->baa ? true : false)
+ : (adj->attr ? true : false));
}
- return 0;
+ return false;
}
@@ -208,8 +209,8 @@ void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai)
XFREE(MTYPE_BGP_ADJ_IN, bai);
}
-int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
- uint32_t addpath_id)
+bool bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
+ uint32_t addpath_id)
{
struct bgp_adj_in *adj;
struct bgp_adj_in *adj_next;
@@ -217,7 +218,7 @@ int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
adj = rn->adj_in;
if (!adj)
- return 0;
+ return false;
while (adj) {
adj_next = adj->next;
@@ -230,7 +231,7 @@ int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
adj = adj_next;
}
- return 1;
+ return true;
}
void bgp_sync_init(struct peer *peer)
diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h
index c98359875..6223dc94a 100644
--- a/bgpd/bgp_advertise.h
+++ b/bgpd/bgp_advertise.h
@@ -139,10 +139,10 @@ struct bgp_synchronize {
#define BGP_ADJ_IN_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_in)
/* Prototypes. */
-extern int bgp_adj_out_lookup(struct peer *, struct bgp_node *, uint32_t);
+extern bool bgp_adj_out_lookup(struct peer *, struct bgp_node *, uint32_t);
extern void bgp_adj_in_set(struct bgp_node *, struct peer *, struct attr *,
uint32_t);
-extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, uint32_t);
+extern bool bgp_adj_in_unset(struct bgp_node *, struct peer *, uint32_t);
extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *);
extern void bgp_sync_init(struct peer *);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index be80675b5..44962f5af 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -428,6 +428,22 @@ bool aspath_check_as_sets(struct aspath *aspath)
return false;
}
+/* Check if aspath has BGP_AS_ZERO */
+bool aspath_check_as_zero(struct aspath *aspath)
+{
+ struct assegment *seg = aspath->segments;
+ unsigned int i;
+
+ while (seg) {
+ for (i = 0; i < seg->length; i++)
+ if (seg->as[i] == BGP_AS_ZERO)
+ return true;
+ seg = seg->next;
+ }
+
+ return false;
+}
+
/* Estimate size aspath /might/ take if encoded into an
* ASPATH attribute.
*
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index f327751f3..9df352fcd 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -39,6 +39,7 @@
#define BGP_PRIVATE_AS4_MAX 4294967294U
/* we leave BGP_AS_MAX as the 16bit AS MAX number. */
+#define BGP_AS_ZERO 0
#define BGP_AS_MAX 65535U
#define BGP_AS4_MAX 4294967295U
/* Transition 16Bit AS as defined by IANA */
@@ -121,6 +122,7 @@ extern bool aspath_left_confed_check(struct aspath *);
extern unsigned long aspath_count(void);
extern unsigned int aspath_count_hops(const struct aspath *);
extern bool aspath_check_as_sets(struct aspath *aspath);
+extern bool aspath_check_as_zero(struct aspath *aspath);
extern unsigned int aspath_count_confeds(struct aspath *);
extern unsigned int aspath_size(struct aspath *);
extern as_t aspath_highest(struct aspath *);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index a1278874c..0bdd079e0 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -130,14 +130,14 @@ static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
return cluster;
}
-int cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
+bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
{
int i;
for (i = 0; i < cluster->length / 4; i++)
if (cluster->list[i].s_addr == originator.s_addr)
- return 1;
- return 0;
+ return true;
+ return false;
}
static unsigned int cluster_hash_key_make(const void *p)
@@ -263,16 +263,16 @@ void bgp_attr_flush_encap(struct attr *attr)
*
* This algorithm could be made faster if needed
*/
-static int encap_same(const struct bgp_attr_encap_subtlv *h1,
- const struct bgp_attr_encap_subtlv *h2)
+static bool encap_same(const struct bgp_attr_encap_subtlv *h1,
+ const struct bgp_attr_encap_subtlv *h2)
{
const struct bgp_attr_encap_subtlv *p;
const struct bgp_attr_encap_subtlv *q;
if (h1 == h2)
- return 1;
+ return true;
if (h1 == NULL || h2 == NULL)
- return 0;
+ return false;
for (p = h1; p; p = p->next) {
for (q = h2; q; q = q->next) {
@@ -283,7 +283,7 @@ static int encap_same(const struct bgp_attr_encap_subtlv *h1,
}
}
if (!q)
- return 0;
+ return false;
}
for (p = h2; p; p = p->next) {
@@ -295,10 +295,10 @@ static int encap_same(const struct bgp_attr_encap_subtlv *h1,
}
}
if (!q)
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void *encap_hash_alloc(void *p)
@@ -1274,7 +1274,7 @@ const uint8_t attr_flags_values[] = {
};
static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
-static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
+static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
{
uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
const uint8_t flags = args->flags;
@@ -1282,9 +1282,9 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
/* there may be attributes we don't know about */
if (attr_code > attr_flags_values_max)
- return 0;
+ return false;
if (attr_flags_values[attr_code] == 0)
- return 0;
+ return false;
/* RFC4271, "For well-known attributes, the Transitive bit MUST be set
* to
@@ -1296,7 +1296,7 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
EC_BGP_ATTR_FLAG,
"%s well-known attributes must have transitive flag set (%x)",
lookup_msg(attr_str, attr_code, NULL), flags);
- return 1;
+ return true;
}
/* "For well-known attributes and for optional non-transitive
@@ -1309,7 +1309,7 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
"%s well-known attribute "
"must NOT have the partial flag set (%x)",
lookup_msg(attr_str, attr_code, NULL), flags);
- return 1;
+ return true;
}
if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
&& !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) {
@@ -1317,7 +1317,7 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
"%s optional + transitive attribute "
"must NOT have the partial flag set (%x)",
lookup_msg(attr_str, attr_code, NULL), flags);
- return 1;
+ return true;
}
}
@@ -1329,10 +1329,10 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
if ((flags & ~mask) == attr_flags_values[attr_code])
- return 0;
+ return false;
bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
- return 1;
+ return true;
}
/* Get origin attribute of the update message. */
@@ -1398,6 +1398,15 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
0);
}
+ /* Codification of AS 0 Processing */
+ if (aspath_check_as_zero(attr->aspath)) {
+ flog_err(EC_BGP_ATTR_MAL_AS_PATH,
+ "Malformed AS path, contains BGP_AS_ZERO(0) from %s",
+ peer->host);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ 0);
+ }
+
/* Set aspath attribute flag. */
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
@@ -1469,6 +1478,15 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
0);
}
+ /* Codification of AS 0 Processing */
+ if (aspath_check_as_zero(*as4_path)) {
+ flog_err(EC_BGP_ATTR_MAL_AS_PATH,
+ "Malformed AS4 path, contains BGP_AS_ZERO(0) from %s",
+ peer->host);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ 0);
+ }
+
/* Set aspath attribute flag. */
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
@@ -1615,6 +1633,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
+ as_t aggregator_as;
int wantedlen = 6;
@@ -1632,9 +1651,19 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
}
if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
- attr->aggregator_as = stream_getl(peer->curr);
+ aggregator_as = stream_getl(peer->curr);
else
- attr->aggregator_as = stream_getw(peer->curr);
+ aggregator_as = stream_getw(peer->curr);
+
+ /* Codification of AS 0 Processing */
+ if (aggregator_as == BGP_AS_ZERO) {
+ flog_err(EC_BGP_ATTR_LEN,
+ "AGGREGATOR attribute is BGP_AS_ZERO(0)");
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ args->total);
+ }
+
+ attr->aggregator_as = aggregator_as;
attr->aggregator_addr.s_addr = stream_get_ipv4(peer->curr);
/* Set atomic aggregate flag. */
@@ -1652,6 +1681,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
+ as_t aggregator_as;
if (length != 8) {
flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
@@ -1660,7 +1690,16 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
0);
}
- *as4_aggregator_as = stream_getl(peer->curr);
+ /* Codification of AS 0 Processing */
+ aggregator_as = stream_getl(peer->curr);
+ if (aggregator_as == BGP_AS_ZERO) {
+ flog_err(EC_BGP_ATTR_LEN,
+ "AS4_AGGREGATOR attribute is BGP_AS_ZERO(0)");
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ 0);
+ }
+
+ *as4_aggregator_as = aggregator_as;
as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr);
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
@@ -2343,8 +2382,7 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
* Returns 0 if there was an error that needs to be passed up the stack
*/
static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
- struct bgp_attr_parser_args *args,
- struct bgp_nlri *mp_update)
+ struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -2382,15 +2420,6 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
/* Store label index; subsequently, we'll check on
* address-family */
attr->label_index = label_index;
-
- /*
- * Ignore the Label index attribute unless received for
- * labeled-unicast
- * SAFI.
- */
- if (!mp_update->length
- || mp_update->safi != SAFI_LABELED_UNICAST)
- attr->label_index = BGP_INVALID_LABEL_INDEX;
}
/* Placeholder code for the IPv6 SID type */
@@ -2589,8 +2618,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
/* Prefix SID attribute
* draft-ietf-idr-bgp-prefix-sid-05
*/
-bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
- struct bgp_nlri *mp_update)
+bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -2601,8 +2629,10 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
uint8_t type;
uint16_t length;
size_t headersz = sizeof(type) + sizeof(length);
+ size_t psid_parsed_length = 0;
- while (STREAM_READABLE(peer->curr) > 0) {
+ while (STREAM_READABLE(peer->curr) > 0
+ && psid_parsed_length < args->length) {
if (STREAM_READABLE(peer->curr) < headersz) {
flog_err(
@@ -2620,7 +2650,7 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
if (STREAM_READABLE(peer->curr) < length) {
flog_err(
EC_BGP_ATTR_LEN,
- "Malformed Prefix SID attribute - insufficient data (need %" PRIu8
+ "Malformed Prefix SID attribute - insufficient data (need %" PRIu16
" for attribute body, have %zu remaining in UPDATE)",
length, STREAM_READABLE(peer->curr));
return bgp_attr_malformed(args,
@@ -2628,10 +2658,23 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
args->total);
}
- ret = bgp_attr_psid_sub(type, length, args, mp_update);
+ ret = bgp_attr_psid_sub(type, length, args);
if (ret != BGP_ATTR_PARSE_PROCEED)
return ret;
+
+ psid_parsed_length += length + headersz;
+
+ if (psid_parsed_length > args->length) {
+ flog_err(
+ EC_BGP_ATTR_LEN,
+ "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu"
+ " for TLV length, have %zu overflowed in UPDATE)",
+ length + headersz, psid_parsed_length - (length + headersz));
+ return bgp_attr_malformed(
+ args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
}
return BGP_ATTR_PARSE_PROCEED;
@@ -3027,7 +3070,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
startp);
break;
case BGP_ATTR_PREFIX_SID:
- ret = bgp_attr_prefix_sid(&attr_args, mp_update);
+ ret = bgp_attr_prefix_sid(&attr_args);
break;
case BGP_ATTR_PMSI_TUNNEL:
ret = bgp_attr_pmsi_tunnel(&attr_args);
@@ -3074,6 +3117,17 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
}
}
+ /*
+ * draft-ietf-idr-bgp-prefix-sid-27#section-3:
+ * About Prefix-SID path attribute,
+ * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
+ * may only appear in a BGP Prefix-SID attribute attached to
+ * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
+ * It MUST be ignored when received for other BGP AFI/SAFI combinations.
+ */
+ if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
+ attr->label_index = BGP_INVALID_LABEL_INDEX;
+
/* Check final read pointer is same as end pointer. */
if (BGP_INPUT_PNT(peer) != endp) {
flog_warn(EC_BGP_ATTRIBUTES_MISMATCH,
@@ -3508,7 +3562,7 @@ void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
}
-static int bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
+static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
{
if (!BGP_AS_IS_PRIVATE(peer->local_as)
|| (BGP_AS_IS_PRIVATE(peer->local_as)
@@ -3520,8 +3574,8 @@ static int bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
&& !CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
- return 1;
- return 0;
+ return true;
+ return false;
}
/* Make attribute packet. */
@@ -4076,7 +4130,7 @@ void bgp_attr_finish(void)
/* Make attribute packet. */
void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
- struct prefix *prefix)
+ const struct prefix *prefix)
{
unsigned long cp;
unsigned long len;
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 2e91f56df..04b3a20d6 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -324,8 +324,8 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
struct prefix *, afi_t, safi_t,
struct peer *, struct prefix_rd *,
mpls_label_t *, uint32_t, int, uint32_t);
-extern void bgp_dump_routes_attr(struct stream *, struct attr *,
- struct prefix *);
+extern void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
+ const struct prefix *p);
extern bool attrhash_cmp(const void *arg1, const void *arg2);
extern unsigned int attrhash_key_make(const void *);
extern void attr_show_all(struct vty *);
@@ -333,7 +333,7 @@ extern unsigned long int attr_count(void);
extern unsigned long int attr_unknown_count(void);
/* Cluster list prototypes. */
-extern int cluster_loop_check(struct cluster_list *, struct in_addr);
+extern bool cluster_loop_check(struct cluster_list *, struct in_addr);
extern void cluster_unintern(struct cluster_list *);
/* Below exported for unit-test purposes only */
@@ -351,8 +351,7 @@ extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *);
extern bgp_attr_parse_ret_t
-bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
- struct bgp_nlri *mp_update);
+bgp_attr_prefix_sid(struct bgp_attr_parser_args *args);
extern struct bgp_attr_encap_subtlv *
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index ec9656a98..7239ddef9 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -54,25 +54,25 @@ void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
* format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
* if id is null, check only is done
*/
-int str2esi(const char *str, struct eth_segment_id *id)
+bool str2esi(const char *str, struct eth_segment_id *id)
{
unsigned int a[ESI_LEN];
int i;
if (!str)
- return 0;
+ return false;
if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
!= ESI_LEN) {
/* error in incoming str length */
- return 0;
+ return false;
}
/* valid mac address */
if (!id)
- return 1;
+ return true;
for (i = 0; i < ESI_LEN; ++i)
id->val[i] = a[i] & 0xff;
- return 1;
+ return true;
}
char *esi2str(struct eth_segment_id *id)
@@ -186,7 +186,7 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
* one.
*/
for (i = 0; i < ecom->size; i++) {
- uint8_t *pnt;
+ const uint8_t *pnt;
uint8_t type, sub_type;
uint32_t seq_num;
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index 25654ba70..c1bfd8376 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -51,7 +51,7 @@ struct bgp_route_evpn {
union gw_addr gw_ip;
};
-extern int str2esi(const char *str, struct eth_segment_id *id);
+extern bool str2esi(const char *str, struct eth_segment_id *id);
extern char *esi2str(struct eth_segment_id *id);
extern char *ecom_mac2str(char *ecom_mac);
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 1f650aaeb..a200589bd 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -72,21 +72,21 @@ void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
* bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single
* hop.
*/
-int bgp_bfd_is_peer_multihop(struct peer *peer)
+bool bgp_bfd_is_peer_multihop(struct peer *peer)
{
struct bfd_info *bfd_info;
bfd_info = (struct bfd_info *)peer->bfd_info;
if (!bfd_info)
- return 0;
+ return false;
if ((bfd_info->type == BFD_TYPE_MULTIHOP)
|| ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network)
|| is_ebgp_multihop_configured(peer))
- return 1;
+ return true;
else
- return 0;
+ return false;
}
/*
@@ -200,6 +200,25 @@ static void bgp_bfd_update_peer(struct peer *peer)
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE);
}
+/**
+ * bgp_bfd_reset_peer - reinitialise bfd
+ * ensures that bfd state machine is restarted
+ * to be synced with remote bfd
+ */
+void bgp_bfd_reset_peer(struct peer *peer)
+{
+ struct bfd_info *bfd_info;
+
+ if (!peer->bfd_info)
+ return;
+ bfd_info = (struct bfd_info *)peer->bfd_info;
+
+ /* if status is not down, reset bfd */
+ if (bfd_info->status != BFD_STATUS_DOWN)
+ bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
+ bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
+}
+
/*
* bgp_bfd_update_type - update session type with BFD through zebra.
*/
diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h
index caa5651e3..f2fa959b4 100644
--- a/bgpd/bgp_bfd.h
+++ b/bgpd/bgp_bfd.h
@@ -31,12 +31,14 @@ extern void bgp_bfd_register_peer(struct peer *peer);
extern void bgp_bfd_deregister_peer(struct peer *peer);
+extern void bgp_bfd_reset_peer(struct peer *peer);
+
extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer,
char *addr);
extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer, bool use_json,
json_object *json_neigh);
-extern int bgp_bfd_is_peer_multihop(struct peer *peer);
+extern bool bgp_bfd_is_peer_multihop(struct peer *peer);
#endif /* _QUAGGA_BGP_BFD_H */
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 24a9cab5d..32865da37 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -664,8 +664,7 @@ static int bmp_peer_established(struct peer *peer)
return 0;
/* Check if this peer just went to Established */
- if ((peer->last_major_event != OpenConfirm) ||
- !(peer_established(peer)))
+ if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
return 0;
if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
index cc37e352e..cbe18e23c 100644
--- a/bgpd/bgp_btoa.c
+++ b/bgpd/bgp_btoa.c
@@ -68,7 +68,7 @@ enum MRT_MSG_TYPES {
MSG_TABLE_DUMP /* routing table dump */
};
-static int attr_parse(struct stream *s, uint16_t len)
+static void attr_parse(struct stream *s, uint16_t len)
{
unsigned int flag;
unsigned int type;
@@ -115,8 +115,6 @@ static int attr_parse(struct stream *s, uint16_t len)
break;
}
}
-
- return 0;
}
int main(int argc, char **argv)
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 5c461dbe7..cf4d44ea2 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -311,9 +311,9 @@ static void community_list_delete(struct community_list_master *cm,
community_list_free(list);
}
-static int community_list_empty_p(struct community_list *list)
+static bool community_list_empty_p(struct community_list *list)
{
- return (list->head == NULL && list->tail == NULL) ? 1 : 0;
+ return list->head == NULL && list->tail == NULL;
}
/* Delete community-list entry from the list. */
@@ -497,7 +497,7 @@ static char *community_str_get(struct community *com, int i)
/* Internal function to perform regular expression match for
* a single community. */
-static int community_regexp_include(regex_t *reg, struct community *com, int i)
+static bool community_regexp_include(regex_t *reg, struct community *com, int i)
{
char *str;
int rv;
@@ -514,16 +514,12 @@ static int community_regexp_include(regex_t *reg, struct community *com, int i)
XFREE(MTYPE_COMMUNITY_STR, str);
- if (rv == 0)
- return 1;
-
- /* No match. */
- return 0;
+ return rv == 0;
}
/* Internal function to perform regular expression match for community
attribute. */
-static int community_regexp_match(struct community *com, regex_t *reg)
+static bool community_regexp_match(struct community *com, regex_t *reg)
{
const char *str;
@@ -536,10 +532,10 @@ static int community_regexp_match(struct community *com, regex_t *reg)
/* Regular expression match. */
if (regexec(reg, str, 0, NULL, 0) == 0)
- return 1;
+ return true;
/* No match. */
- return 0;
+ return false;
}
static char *lcommunity_str_get(struct lcommunity *lcom, int i)
@@ -549,7 +545,7 @@ static char *lcommunity_str_get(struct lcommunity *lcom, int i)
uint32_t localdata1;
uint32_t localdata2;
char *str;
- uint8_t *ptr;
+ const uint8_t *ptr;
char *pnt;
ptr = lcom->val + (i * LCOMMUNITY_SIZE);
@@ -574,8 +570,8 @@ static char *lcommunity_str_get(struct lcommunity *lcom, int i)
/* Internal function to perform regular expression match for
* a single community. */
-static int lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom,
- int i)
+static bool lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom,
+ int i)
{
char *str;
@@ -589,15 +585,15 @@ static int lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom,
/* Regular expression match. */
if (regexec(reg, str, 0, NULL, 0) == 0) {
XFREE(MTYPE_LCOMMUNITY_STR, str);
- return 1;
+ return true;
}
XFREE(MTYPE_LCOMMUNITY_STR, str);
/* No match. */
- return 0;
+ return false;
}
-static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg)
+static bool lcommunity_regexp_match(struct lcommunity *com, regex_t *reg)
{
const char *str;
@@ -610,14 +606,14 @@ static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg)
/* Regular expression match. */
if (regexec(reg, str, 0, NULL, 0) == 0)
- return 1;
+ return true;
/* No match. */
- return 0;
+ return false;
}
-static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg)
+static bool ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg)
{
const char *str;
@@ -630,10 +626,10 @@ static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg)
/* Regular expression match. */
if (regexec(reg, str, 0, NULL, 0) == 0)
- return 1;
+ return true;
/* No match. */
- return 0;
+ return false;
}
#if 0
@@ -718,125 +714,113 @@ community_regexp_delete (struct community *com, regex_t * reg)
/* When given community attribute matches to the community-list return
1 else return 0. */
-int community_list_match(struct community *com, struct community_list *list)
+bool community_list_match(struct community *com, struct community_list *list)
{
struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) {
if (entry->any)
- return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (entry->style == COMMUNITY_LIST_STANDARD) {
if (community_include(entry->u.com, COMMUNITY_INTERNET))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (community_match(com, entry->u.com))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
} else if (entry->style == COMMUNITY_LIST_EXPANDED) {
if (community_regexp_match(com, entry->reg))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
}
}
- return 0;
+ return false;
}
-int lcommunity_list_match(struct lcommunity *lcom, struct community_list *list)
+bool lcommunity_list_match(struct lcommunity *lcom, struct community_list *list)
{
struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) {
if (entry->any)
- return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) {
if (lcommunity_match(lcom, entry->u.lcom))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
} else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) {
if (lcommunity_regexp_match(lcom, entry->reg))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
}
}
- return 0;
+ return false;
}
/* Perform exact matching. In case of expanded large-community-list, do
* same thing as lcommunity_list_match().
*/
-int lcommunity_list_exact_match(struct lcommunity *lcom,
- struct community_list *list)
+bool lcommunity_list_exact_match(struct lcommunity *lcom,
+ struct community_list *list)
{
struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) {
if (entry->any)
- return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) {
if (lcommunity_cmp(lcom, entry->u.com))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
} else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) {
if (lcommunity_regexp_match(lcom, entry->reg))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
}
}
- return 0;
+ return false;
}
-int ecommunity_list_match(struct ecommunity *ecom, struct community_list *list)
+bool ecommunity_list_match(struct ecommunity *ecom, struct community_list *list)
{
struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) {
if (entry->any)
- return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (entry->style == EXTCOMMUNITY_LIST_STANDARD) {
if (ecommunity_match(ecom, entry->u.ecom))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
} else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) {
if (ecommunity_regexp_match(ecom, entry->reg))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
}
}
- return 0;
+ return false;
}
/* Perform exact matching. In case of expanded community-list, do
same thing as community_list_match(). */
-int community_list_exact_match(struct community *com,
- struct community_list *list)
+bool community_list_exact_match(struct community *com,
+ struct community_list *list)
{
struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) {
if (entry->any)
- return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (entry->style == COMMUNITY_LIST_STANDARD) {
if (community_include(entry->u.com, COMMUNITY_INTERNET))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
if (community_cmp(com, entry->u.com))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
} else if (entry->style == COMMUNITY_LIST_EXPANDED) {
if (community_regexp_match(com, entry->reg))
- return entry->direct == COMMUNITY_PERMIT ? 1
- : 0;
+ return entry->direct == COMMUNITY_PERMIT;
}
}
- return 0;
+ return false;
}
/* Delete all permitted communities in the list from com. */
@@ -900,8 +884,8 @@ struct community *community_list_match_delete(struct community *com,
/* To avoid duplicated entry in the community-list, this function
compares specified entry to existing entry. */
-static int community_list_dup_check(struct community_list *list,
- struct community_entry *new)
+static bool community_list_dup_check(struct community_list *list,
+ struct community_entry *new)
{
struct community_entry *entry;
@@ -916,32 +900,32 @@ static int community_list_dup_check(struct community_list *list,
continue;
if (entry->any)
- return 1;
+ return true;
switch (entry->style) {
case COMMUNITY_LIST_STANDARD:
if (community_cmp(entry->u.com, new->u.com))
- return 1;
+ return true;
break;
case LARGE_COMMUNITY_LIST_STANDARD:
if (lcommunity_cmp(entry->u.lcom, new->u.lcom))
- return 1;
+ return true;
break;
case EXTCOMMUNITY_LIST_STANDARD:
if (ecommunity_cmp(entry->u.ecom, new->u.ecom))
- return 1;
+ return true;
break;
case COMMUNITY_LIST_EXPANDED:
case EXTCOMMUNITY_LIST_EXPANDED:
case LARGE_COMMUNITY_LIST_EXPANDED:
if (strcmp(entry->config, new->config) == 0)
- return 1;
+ return true;
break;
default:
break;
}
}
- return 0;
+ return false;
}
/* Set community-list. */
@@ -1104,7 +1088,7 @@ struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
}
/* Helper to check if every octet do not exceed UINT_MAX */
-static int lcommunity_list_valid(const char *community)
+static bool lcommunity_list_valid(const char *community)
{
int octets = 0;
char **splits;
@@ -1114,10 +1098,10 @@ static int lcommunity_list_valid(const char *community)
for (int i = 0; i < num; i++) {
if (strtoul(splits[i], NULL, 10) > UINT_MAX)
- return 0;
+ return false;
if (strlen(splits[i]) == 0)
- return 0;
+ return false;
octets++;
XFREE(MTYPE_TMP, splits[i]);
@@ -1125,9 +1109,9 @@ static int lcommunity_list_valid(const char *community)
XFREE(MTYPE_TMP, splits);
if (octets < 3)
- return 0;
+ return false;
- return 1;
+ return true;
}
/* Set lcommunity-list. */
diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h
index c5718aeca..4cb5d7c59 100644
--- a/bgpd/bgp_clist.h
+++ b/bgpd/bgp_clist.h
@@ -165,13 +165,13 @@ extern struct community_list *
community_list_lookup(struct community_list_handler *c, const char *name,
uint32_t name_hash, int master);
-extern int community_list_match(struct community *, struct community_list *);
-extern int ecommunity_list_match(struct ecommunity *, struct community_list *);
-extern int lcommunity_list_match(struct lcommunity *, struct community_list *);
-extern int community_list_exact_match(struct community *,
- struct community_list *);
-extern int lcommunity_list_exact_match(struct lcommunity *lcom,
- struct community_list *list);
+extern bool community_list_match(struct community *, struct community_list *);
+extern bool ecommunity_list_match(struct ecommunity *, struct community_list *);
+extern bool lcommunity_list_match(struct lcommunity *, struct community_list *);
+extern bool community_list_exact_match(struct community *,
+ struct community_list *);
+extern bool lcommunity_list_exact_match(struct lcommunity *lcom,
+ struct community_list *list);
extern struct community *community_list_match_delete(struct community *,
struct community_list *);
extern struct lcommunity *
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index c145c47d0..195c0f394 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -128,7 +128,7 @@ static int community_compare(const void *a1, const void *a2)
return 0;
}
-int community_include(struct community *com, uint32_t val)
+bool community_include(struct community *com, uint32_t val)
{
int i;
@@ -136,9 +136,8 @@ int community_include(struct community *com, uint32_t val)
for (i = 0; i < com->size; i++)
if (memcmp(&val, com_nthval(com, i), sizeof(uint32_t)) == 0)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
uint32_t community_val_get(struct community *com, int i)
@@ -564,19 +563,19 @@ unsigned int community_hash_make(const struct community *com)
return jhash2(pnt, com->size, 0x43ea96c1);
}
-int community_match(const struct community *com1, const struct community *com2)
+bool community_match(const struct community *com1, const struct community *com2)
{
int i = 0;
int j = 0;
if (com1 == NULL && com2 == NULL)
- return 1;
+ return true;
if (com1 == NULL || com2 == NULL)
- return 0;
+ return false;
if (com1->size < com2->size)
- return 0;
+ return false;
/* Every community on com2 needs to be on com1 for this to match */
while (i < com1->size && j < com2->size) {
@@ -586,9 +585,9 @@ int community_match(const struct community *com1, const struct community *com2)
}
if (j == com2->size)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
/* If two aspath have same value then return 1 else return 0. This
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index 74a3a6b50..31a061370 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -77,7 +77,7 @@ extern void community_unintern(struct community **);
extern char *community_str(struct community *, bool make_json);
extern unsigned int community_hash_make(const struct community *);
extern struct community *community_str2com(const char *);
-extern int community_match(const struct community *, const struct community *);
+extern bool community_match(const struct community *, const struct community *);
extern bool community_cmp(const struct community *c1,
const struct community *c2);
extern struct community *community_merge(struct community *,
@@ -85,7 +85,7 @@ extern struct community *community_merge(struct community *,
extern struct community *community_delete(struct community *,
struct community *);
extern struct community *community_dup(struct community *);
-extern int community_include(struct community *, uint32_t);
+extern bool community_include(struct community *, uint32_t);
extern void community_del_val(struct community *, uint32_t *);
extern unsigned long community_count(void);
extern struct hash *community_hash(void);
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 466fecc58..bae1079a1 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -170,12 +170,22 @@ static const struct message bgp_notify_capability_msg[] = {
{BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"},
{0}};
+static const struct message bgp_notify_fsm_msg[] = {
+ {BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC, "/Unspecific"},
+ {BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT,
+ "/Receive Unexpected Message in OpenSent State"},
+ {BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM,
+ "/Receive Unexpected Message in OpenConfirm State"},
+ {BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED,
+ "/Receive Unexpected Message in Established State"},
+ {0}};
+
/* Origin strings. */
const char *const bgp_origin_str[] = {"i", "e", "?"};
const char *const bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"};
-static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
- struct prefix *p);
+static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
+ struct prefix *p);
/* Given a string return a pointer the corresponding peer structure */
static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str)
{
@@ -305,8 +315,8 @@ static void bgp_debug_list_add_entry(struct list *list, const char *host,
listnode_add(list, filter);
}
-static int bgp_debug_list_remove_entry(struct list *list, const char *host,
- struct prefix *p)
+static bool bgp_debug_list_remove_entry(struct list *list, const char *host,
+ struct prefix *p)
{
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
@@ -316,21 +326,21 @@ static int bgp_debug_list_remove_entry(struct list *list, const char *host,
listnode_delete(list, filter);
XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
- return 1;
+ return true;
} else if (p && filter->p->prefixlen == p->prefixlen
&& prefix_match(filter->p, p)) {
listnode_delete(list, filter);
prefix_free(&filter->p);
XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-static int bgp_debug_list_has_entry(struct list *list, const char *host,
- const struct prefix *p)
+static bool bgp_debug_list_has_entry(struct list *list, const char *host,
+ const struct prefix *p)
{
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
@@ -338,32 +348,32 @@ static int bgp_debug_list_has_entry(struct list *list, const char *host,
for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
if (host) {
if (strcmp(filter->host, host) == 0) {
- return 1;
+ return true;
}
} else if (p) {
if (filter->p->prefixlen == p->prefixlen
&& prefix_match(filter->p, p)) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
-int bgp_debug_peer_updout_enabled(char *host)
+bool bgp_debug_peer_updout_enabled(char *host)
{
return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
NULL));
}
/* Dump attribute. */
-int bgp_dump_attr(struct attr *attr, char *buf, size_t size)
+bool bgp_dump_attr(struct attr *attr, char *buf, size_t size)
{
char addrbuf[BUFSIZ];
if (!attr)
- return 0;
+ return false;
buf[0] = '\0';
@@ -445,9 +455,9 @@ int bgp_dump_attr(struct attr *attr, char *buf, size_t size)
}
if (strlen(buf) > 1)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
const char *bgp_notify_code_str(char code)
@@ -471,7 +481,8 @@ const char *bgp_notify_subcode_str(char code, char subcode)
case BGP_NOTIFY_HOLD_ERR:
break;
case BGP_NOTIFY_FSM_ERR:
- break;
+ return lookup_msg(bgp_notify_fsm_msg, subcode,
+ "Unrecognized Error Subcode");
case BGP_NOTIFY_CEASE:
return lookup_msg(bgp_notify_cease_msg, subcode,
"Unrecognized Error Subcode");
@@ -550,8 +561,8 @@ static void bgp_debug_clear_updgrp_update_dbg(struct bgp *bgp)
update_group_walk(bgp, update_group_clear_update_dbg, NULL);
}
-static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
- struct prefix *p)
+static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
+ struct prefix *p)
{
char evpn_desc[PREFIX2STR_BUFFER + INET_ADDRSTRLEN];
char buf[PREFIX2STR_BUFFER];
@@ -590,8 +601,6 @@ static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
}
vty_out(vty, "%s %s\n", desc, evpn_desc);
-
- return 0;
}
static int bgp_debug_parse_evpn_prefix(struct vty *vty, struct cmd_token **argv,
@@ -2395,7 +2404,7 @@ void bgp_debug_init(void)
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
* for BGP_DEBUG_TYPE
*/
-static int bgp_debug_per_prefix(struct prefix *p,
+static int bgp_debug_per_prefix(const struct prefix *p,
unsigned long term_bgp_debug_type,
unsigned int BGP_DEBUG_TYPE,
struct list *per_prefix_list)
@@ -2480,8 +2489,8 @@ int bgp_debug_keepalive(struct peer *peer)
bgp_debug_keepalive_peers);
}
-int bgp_debug_update(struct peer *peer, struct prefix *p,
- struct update_group *updgrp, unsigned int inbound)
+bool bgp_debug_update(struct peer *peer, const struct prefix *p,
+ struct update_group *updgrp, unsigned int inbound)
{
char *host = NULL;
@@ -2492,7 +2501,7 @@ int bgp_debug_update(struct peer *peer, struct prefix *p,
if (bgp_debug_per_peer(host, term_bgp_debug_update,
BGP_DEBUG_UPDATE_IN,
bgp_debug_update_in_peers))
- return 1;
+ return true;
}
/* outbound */
@@ -2500,12 +2509,12 @@ int bgp_debug_update(struct peer *peer, struct prefix *p,
if (bgp_debug_per_peer(host, term_bgp_debug_update,
BGP_DEBUG_UPDATE_OUT,
bgp_debug_update_out_peers))
- return 1;
+ return true;
/* Check if update debugging implicitly enabled for the group.
*/
if (updgrp && UPDGRP_DBG_ON(updgrp))
- return 1;
+ return true;
}
@@ -2513,34 +2522,34 @@ int bgp_debug_update(struct peer *peer, struct prefix *p,
if (bgp_debug_per_prefix(p, term_bgp_debug_update,
BGP_DEBUG_UPDATE_PREFIX,
bgp_debug_update_prefixes))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int bgp_debug_bestpath(struct prefix *p)
+bool bgp_debug_bestpath(struct prefix *p)
{
if (BGP_DEBUG(bestpath, BESTPATH)) {
if (bgp_debug_per_prefix(p, term_bgp_debug_bestpath,
BGP_DEBUG_BESTPATH,
bgp_debug_bestpath_prefixes))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int bgp_debug_zebra(struct prefix *p)
+bool bgp_debug_zebra(const struct prefix *p)
{
if (BGP_DEBUG(zebra, ZEBRA)) {
if (bgp_debug_per_prefix(p, term_bgp_debug_zebra,
BGP_DEBUG_ZEBRA,
bgp_debug_zebra_prefixes))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index 1e6482e96..51f939692 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -157,8 +157,8 @@ struct bgp_debug_filter {
extern const char *const bgp_type_str[];
-extern int bgp_dump_attr(struct attr *, char *, size_t);
-extern int bgp_debug_peer_updout_enabled(char *host);
+extern bool bgp_dump_attr(struct attr *, char *, size_t);
+extern bool bgp_debug_peer_updout_enabled(char *host);
extern const char *bgp_notify_code_str(char);
extern const char *bgp_notify_subcode_str(char, char);
extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *);
@@ -166,10 +166,10 @@ extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *);
extern const struct message bgp_status_msg[];
extern int bgp_debug_neighbor_events(struct peer *peer);
extern int bgp_debug_keepalive(struct peer *peer);
-extern int bgp_debug_update(struct peer *peer, struct prefix *p,
- struct update_group *updgrp, unsigned int inbound);
-extern int bgp_debug_bestpath(struct prefix *p);
-extern int bgp_debug_zebra(struct prefix *p);
+extern bool bgp_debug_update(struct peer *peer, const struct prefix *p,
+ struct update_group *updgrp, unsigned int inbound);
+extern bool bgp_debug_bestpath(struct prefix *p);
+extern bool bgp_debug_zebra(const struct prefix *p);
extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *,
union prefixconstptr, mpls_label_t *,
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 2711cf7a6..fc6649474 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -75,7 +75,7 @@ static void ecommunity_hash_free(struct ecommunity *ecom)
structure, we don't add the value. Newly added value is sorted by
numerical order. When the value is added to the structure return 1
else return 0. */
-int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval)
+bool ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval)
{
int c;
@@ -84,7 +84,7 @@ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval)
ecom->size = 1;
ecom->val = XCALLOC(MTYPE_ECOMMUNITY_VAL, ECOMMUNITY_SIZE);
memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE);
- return 1;
+ return true;
}
/* If the value already exists in the structure return 0. */
@@ -93,7 +93,7 @@ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval)
p += ECOMMUNITY_SIZE, c++) {
int ret = memcmp(p, eval->val, ECOMMUNITY_SIZE);
if (ret == 0)
- return 0;
+ return false;
else if (ret > 0)
break;
}
@@ -108,7 +108,7 @@ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval)
(ecom->size - 1 - c) * ECOMMUNITY_SIZE);
memcpy(ecom->val + (c * ECOMMUNITY_SIZE), eval->val, ECOMMUNITY_SIZE);
- return 1;
+ return true;
}
/* This function takes pointer to Extended Communites strucutre then
@@ -555,7 +555,7 @@ struct ecommunity *ecommunity_str2com(const char *str, int type,
return ecom;
}
-static int ecommunity_rt_soo_str(char *buf, size_t bufsz, uint8_t *pnt,
+static int ecommunity_rt_soo_str(char *buf, size_t bufsz, const uint8_t *pnt,
int type, int sub_type, int format)
{
int len = 0;
@@ -837,20 +837,20 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
return str_buf;
}
-int ecommunity_match(const struct ecommunity *ecom1,
- const struct ecommunity *ecom2)
+bool ecommunity_match(const struct ecommunity *ecom1,
+ const struct ecommunity *ecom2)
{
int i = 0;
int j = 0;
if (ecom1 == NULL && ecom2 == NULL)
- return 1;
+ return true;
if (ecom1 == NULL || ecom2 == NULL)
- return 0;
+ return false;
if (ecom1->size < ecom2->size)
- return 0;
+ return false;
/* Every community on com2 needs to be on com1 for this to match */
while (i < ecom1->size && j < ecom2->size) {
@@ -862,9 +862,9 @@ int ecommunity_match(const struct ecommunity *ecom1,
}
if (j == ecom2->size)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
/* return first occurence of type */
@@ -889,54 +889,63 @@ extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *ecom,
/* remove ext. community matching type and subtype
* return 1 on success ( removed ), 0 otherwise (not present)
*/
-extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
- uint8_t subtype)
+extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type,
+ uint8_t subtype)
{
- uint8_t *p;
+ uint8_t *p, *q, *new;
int c, found = 0;
/* When this is fist value, just add it. */
- if (ecom == NULL || ecom->val == NULL) {
- return 0;
- }
+ if (ecom == NULL || ecom->val == NULL)
+ return false;
- /* If the value already exists in the structure return 0. */
+ /* Check if any existing ext community matches. */
+ /* Certain extended communities like the Route Target can be present
+ * multiple times, handle that.
+ */
c = 0;
for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
- if (p[0] == type && p[1] == subtype) {
- found = 1;
- break;
- }
+ if (p[0] == type && p[1] == subtype)
+ found++;
}
+ /* If no matching ext community exists, return. */
if (found == 0)
- return 0;
- /* Strip The selected value */
- ecom->size--;
- /* size is reduced. no memmove to do */
- p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE);
- if (c != 0)
- memcpy(p, ecom->val, c * ECOMMUNITY_SIZE);
- if ((ecom->size - c) != 0)
- memcpy(p + (c)*ECOMMUNITY_SIZE,
- ecom->val + (c + 1) * ECOMMUNITY_SIZE,
- (ecom->size - c) * ECOMMUNITY_SIZE);
- /* shift last ecommunities */
- XFREE(MTYPE_ECOMMUNITY, ecom->val);
- ecom->val = p;
- return 1;
+ return false;
+
+ /* Handle the case where everything needs to be stripped. */
+ if (found == ecom->size) {
+ XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
+ ecom->size = 0;
+ return true;
+ }
+
+ /* Strip matching ext community(ies). */
+ new = XMALLOC(MTYPE_ECOMMUNITY_VAL,
+ (ecom->size - found) * ECOMMUNITY_SIZE);
+ q = new;
+ for (c = 0, p = ecom->val; c < ecom->size; c++, p += ECOMMUNITY_SIZE) {
+ if (!(p[0] == type && p[1] == subtype)) {
+ memcpy(q, p, ECOMMUNITY_SIZE);
+ q += ECOMMUNITY_SIZE;
+ }
+ }
+ XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
+ ecom->val = new;
+ ecom->size -= found;
+ return true;
}
/*
* Remove specified extended community value from extended community.
* Returns 1 if value was present (and hence, removed), 0 otherwise.
*/
-int ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
+bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
{
uint8_t *p;
int c, found = 0;
/* Make sure specified value exists. */
if (ecom == NULL || ecom->val == NULL)
- return 0;
+ return false;
c = 0;
for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
if (!memcmp(p, eval->val, ECOMMUNITY_SIZE)) {
@@ -945,7 +954,7 @@ int ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
}
}
if (found == 0)
- return 0;
+ return false;
/* Delete the selected value */
ecom->size--;
@@ -958,7 +967,7 @@ int ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
(ecom->size - c) * ECOMMUNITY_SIZE);
XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
ecom->val = p;
- return 1;
+ return true;
}
int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index ae64f41ca..df0da091d 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -165,22 +165,22 @@ extern unsigned int ecommunity_hash_make(const void *);
extern struct ecommunity *ecommunity_str2com(const char *, int, int);
extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
extern void ecommunity_strfree(char **s);
-extern int ecommunity_match(const struct ecommunity *,
- const struct ecommunity *);
+extern bool ecommunity_match(const struct ecommunity *,
+ const struct ecommunity *);
extern char *ecommunity_str(struct ecommunity *);
extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
uint8_t, uint8_t);
-extern int ecommunity_add_val(struct ecommunity *ecom,
- struct ecommunity_val *eval);
+extern bool ecommunity_add_val(struct ecommunity *ecom,
+ struct ecommunity_val *eval);
/* for vpn */
extern struct ecommunity *ecommunity_new(void);
-extern int ecommunity_add_val(struct ecommunity *, struct ecommunity_val *);
-extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
- uint8_t subtype);
+extern bool ecommunity_add_val(struct ecommunity *, struct ecommunity_val *);
+extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type,
+ uint8_t subtype);
extern struct ecommunity *ecommunity_new(void);
-extern int ecommunity_del_val(struct ecommunity *ecom,
- struct ecommunity_val *eval);
+extern bool ecommunity_del_val(struct ecommunity *ecom,
+ struct ecommunity_val *eval);
struct bgp_pbr_entry_action;
extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
struct bgp_pbr_entry_action *api);
@@ -202,4 +202,13 @@ extern void bgp_remove_ecomm_from_aggregate_hash(
struct ecommunity *ecommunity);
extern void bgp_aggr_ecommunity_remove(void *arg);
+
+static inline void ecommunity_strip_rts(struct ecommunity *ecom)
+{
+ uint8_t subtype = ECOMMUNITY_ROUTE_TARGET;
+
+ ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS, subtype);
+ ecommunity_strip(ecom, ECOMMUNITY_ENCODE_IP, subtype);
+ ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS4, subtype);
+}
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 664d62fd1..5972359f7 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -496,7 +496,7 @@ static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn,
}
static void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct attr *attr, uint8_t flags)
{
struct bgp *bgp_vrf = vpn->bgp_vrf;
@@ -583,7 +583,7 @@ static void evpn_convert_nexthop_to_ipv6(struct attr *attr)
* Add (update) or delete MACIP from zebra.
*/
static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct in_addr remote_vtep_ip, int add,
uint8_t flags, uint32_t seq)
{
@@ -651,8 +651,8 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
* Add (update) or delete remote VTEP from zebra.
*/
static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
- int flood_control, int add)
+ const struct prefix_evpn *p,
+ int flood_control, int add)
{
struct stream *s;
@@ -930,7 +930,8 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
/* Install EVPN route into zebra. */
static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p, struct bgp_path_info *pi)
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi)
{
int ret;
uint8_t flags;
@@ -970,7 +971,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
/* Uninstall EVPN route from zebra. */
static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct in_addr remote_vtep_ip)
{
int ret;
@@ -1054,9 +1055,8 @@ static int is_vtep_present_in_list(struct list *list,
* Best path for ES route was changed,
* update the list of VTEPs for this ES
*/
-static int evpn_es_install_vtep(struct bgp *bgp,
- struct evpnes *es,
- struct prefix_evpn *p,
+static int evpn_es_install_vtep(struct bgp *bgp, struct evpnes *es,
+ const struct prefix_evpn *p,
struct in_addr rvtep)
{
struct in_addr *vtep_ip;
@@ -1157,7 +1157,7 @@ static int evpn_es_route_select_install(struct bgp *bgp,
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_IMPORTED) {
ret = evpn_es_install_vtep(bgp, es,
- (struct prefix_evpn *)&rn->p,
+ (const struct prefix_evpn *)&rn->p,
new_select->attr->nexthop);
} else {
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
@@ -2555,7 +2555,7 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
/* Install EVPN route entry in ES */
static int install_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct bgp_path_info *parent_pi)
{
int ret = 0;
@@ -2619,7 +2619,7 @@ static int install_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es,
* Install route entry into the VRF routing table and invoke route selection.
*/
static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
- struct prefix_evpn *evp,
+ const struct prefix_evpn *evp,
struct bgp_path_info *parent_pi)
{
struct bgp_node *rn;
@@ -2726,7 +2726,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
* Install route entry into the VNI routing table and invoke route selection.
*/
static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct bgp_path_info *parent_pi)
{
struct bgp_node *rn;
@@ -2782,7 +2782,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* Uninstall EVPN route entry from ES route table */
static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct bgp_path_info *parent_pi)
{
int ret;
@@ -2825,7 +2825,7 @@ static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es,
* to zebra, if appropriate.
*/
static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
- struct prefix_evpn *evp,
+ const struct prefix_evpn *evp,
struct bgp_path_info *parent_pi)
{
struct bgp_node *rn;
@@ -2895,7 +2895,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
* to zebra, if appropriate.
*/
static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
+ const struct prefix_evpn *p,
struct bgp_path_info *parent_pi)
{
struct bgp_node *rn;
@@ -2932,7 +2932,7 @@ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/*
* Given a prefix, see if it belongs to ES.
*/
-static int is_prefix_matching_for_es(struct prefix_evpn *p,
+static int is_prefix_matching_for_es(const struct prefix_evpn *p,
struct evpnes *es)
{
/* if not an ES route return false */
@@ -3153,7 +3153,7 @@ static int install_uninstall_routes_for_es(struct bgp *bgp,
* route into bgp vrf table and remote rmac in bridge table.
*/
static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf,
- struct prefix_evpn *evp,
+ const struct prefix_evpn *evp,
struct bgp_path_info *pi)
{
/* evpn route could have learnt prior to L3vni has come up,
@@ -4465,7 +4465,7 @@ static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp)
*/
/* withdraw type-5 route corresponding to ip prefix */
-void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p,
+void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, const struct prefix *p,
afi_t afi, safi_t safi)
{
int ret = 0;
@@ -4535,7 +4535,7 @@ void bgp_evpn_install_uninstall_default_route(struct bgp *bgp_vrf, afi_t afi,
* path in the case of the attr. In the case of a local prefix (when we
* are advertising local subnets), the src_attr will be NULL.
*/
-void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p,
+void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, const struct prefix *p,
struct attr *src_attr, afi_t afi,
safi_t safi)
{
@@ -4576,16 +4576,34 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
/* apply the route-map */
if (bgp_vrf->adv_cmd_rmap[afi][safi].map) {
route_map_result_t ret;
+ struct bgp_path_info tmp_pi;
+ struct bgp_path_info_extra tmp_pie;
+ struct attr tmp_attr;
+
+ tmp_attr = *pi->attr;
+
+ /* Fill temp path_info */
+ prep_for_rmap_apply(
+ &tmp_pi, &tmp_pie, rn, pi,
+ pi->peer, &tmp_attr);
+
+ RESET_FLAG(tmp_attr.rmap_change_flags);
ret = route_map_apply(
bgp_vrf->adv_cmd_rmap[afi][safi]
.map,
- &rn->p, RMAP_BGP, pi);
- if (ret == RMAP_DENYMATCH)
+ &rn->p, RMAP_BGP, &tmp_pi);
+ if (ret == RMAP_DENYMATCH) {
+ bgp_attr_flush(&tmp_attr);
continue;
- }
- bgp_evpn_advertise_type5_route(
- bgp_vrf, &rn->p, pi->attr, afi, safi);
+ }
+ bgp_evpn_advertise_type5_route(
+ bgp_vrf, &rn->p, &tmp_attr,
+ afi, safi);
+ } else
+ bgp_evpn_advertise_type5_route(
+ bgp_vrf, &rn->p, pi->attr,
+ afi, safi);
break;
}
}
@@ -4882,7 +4900,7 @@ char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels, char *buf,
* Function to convert evpn route to json format.
* NOTE: We don't use prefix2str as the output here is a bit different.
*/
-void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
+void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json)
{
char buf1[ETHER_ADDR_STRLEN];
char buf2[PREFIX2STR_BUFFER];
@@ -4947,7 +4965,7 @@ void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
* Function to convert evpn route to string.
* NOTE: We don't use prefix2str as the output here is a bit different.
*/
-char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
+char *bgp_evpn_route2str(const struct prefix_evpn *p, char *buf, int len)
{
char buf1[ETHER_ADDR_STRLEN];
char buf2[PREFIX2STR_BUFFER];
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index b030f0a33..308ced098 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -140,11 +140,12 @@ static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi)
}
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
- struct prefix *p,
+ const struct prefix *p,
struct attr *src_attr, afi_t afi,
safi_t safi);
-extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p,
- afi_t afi, safi_t safi);
+extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf,
+ const struct prefix *p, afi_t afi,
+ safi_t safi);
extern void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi,
safi_t safi);
extern void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
@@ -153,8 +154,9 @@ extern void bgp_evpn_vrf_delete(struct bgp *bgp_vrf);
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
extern char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels,
char *buf, int len);
-extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
-extern void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json);
+extern char *bgp_evpn_route2str(const struct prefix_evpn *p, char *buf,
+ int len);
+extern void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json);
extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
struct prefix_rd *prd, mpls_label_t *label,
uint32_t num_labels, struct attr *attr,
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 76cf8b2cd..ea1ae087f 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -366,7 +366,7 @@ static inline void encode_na_flag_extcomm(struct ecommunity_val *eval,
eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG;
}
-static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
+static inline void ip_prefix_from_type5_prefix(const struct prefix_evpn *evp,
struct prefix *ip)
{
memset(ip, 0, sizeof(struct prefix));
@@ -392,7 +392,7 @@ static inline int is_evpn_prefix_default(const struct prefix *evp)
1 : 0);
}
-static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
+static inline void ip_prefix_from_type2_prefix(const struct prefix_evpn *evp,
struct prefix *ip)
{
memset(ip, 0, sizeof(struct prefix));
@@ -409,7 +409,7 @@ static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
}
}
-static inline void ip_prefix_from_evpn_prefix(struct prefix_evpn *evp,
+static inline void ip_prefix_from_evpn_prefix(const struct prefix_evpn *evp,
struct prefix *ip)
{
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
@@ -432,8 +432,9 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
memcpy(&p->prefix.macip_addr.ip, ip, sizeof(*ip));
}
-static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
- struct prefix *ip_prefix)
+static inline void
+build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
+ const struct prefix *ip_prefix)
{
struct ipaddr ip;
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 7ed37319b..70bd7b219 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -59,7 +59,7 @@ struct vni_walk_ctx {
static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
json_object *json)
{
- uint8_t *pnt;
+ const uint8_t *pnt;
uint8_t type, sub_type;
struct ecommunity_as eas;
struct ecommunity_ip eip;
@@ -167,7 +167,7 @@ static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
static void display_import_rt(struct vty *vty, struct irt_node *irt,
json_object *json)
{
- uint8_t *pnt;
+ const uint8_t *pnt;
uint8_t type, sub_type;
struct ecommunity_as eas;
struct ecommunity_ip eip;
@@ -2210,13 +2210,13 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
* appropriate action) and the VNI marked as unconfigured; the
* VNI will continue to exist, purely as a "learnt" entity.
*/
-static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
+static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
assert(bgp->vnihash);
if (!is_vni_live(vpn)) {
bgp_evpn_free(bgp, vpn);
- return 0;
+ return;
}
/* We need to take the unconfigure action for each parameter of this VNI
@@ -2234,8 +2234,6 @@ static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
/* Next, deal with the import side. */
if (is_import_rt_configured(vpn))
evpn_unconfigure_import_rt(bgp, vpn, NULL);
-
- return 0;
}
/*
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index a03551e79..7de8dc2c8 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -302,12 +302,9 @@ static void as_list_delete(struct as_list *aslist)
as_list_free(aslist);
}
-static int as_list_empty(struct as_list *aslist)
+static bool as_list_empty(struct as_list *aslist)
{
- if (aslist->head == NULL && aslist->tail == NULL)
- return 1;
- else
- return 0;
+ return aslist->head == NULL && aslist->tail == NULL;
}
static void as_list_filter_delete(struct as_list *aslist,
@@ -337,11 +334,9 @@ static void as_list_filter_delete(struct as_list *aslist,
XFREE(MTYPE_AS_STR, name);
}
-static int as_filter_match(struct as_filter *asfilter, struct aspath *aspath)
+static bool as_filter_match(struct as_filter *asfilter, struct aspath *aspath)
{
- if (bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH)
- return 1;
- return 0;
+ return bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH;
}
/* Apply AS path filter to AS. */
@@ -374,26 +369,25 @@ void as_list_delete_hook(void (*func)(const char *))
as_list_master.delete_hook = func;
}
-static int as_list_dup_check(struct as_list *aslist, struct as_filter *new)
+static bool as_list_dup_check(struct as_list *aslist, struct as_filter *new)
{
struct as_filter *asfilter;
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
if (asfilter->type == new->type
&& strcmp(asfilter->reg_str, new->reg_str) == 0)
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int config_bgp_aspath_validate(const char *regstr)
+bool config_bgp_aspath_validate(const char *regstr)
{
char valid_chars[] = "1234567890_^|[,{}() ]$*+.?-\\";
if (strspn(regstr, valid_chars) == strlen(regstr))
- return 1;
-
- return 0;
+ return true;
+ return false;
}
DEFUN(as_path, bgp_as_path_cmd,
diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h
index 3c49e357f..9357a2d38 100644
--- a/bgpd/bgp_filter.h
+++ b/bgpd/bgp_filter.h
@@ -31,6 +31,6 @@ extern enum as_filter_type as_list_apply(struct as_list *, void *);
extern struct as_list *as_list_lookup(const char *);
extern void as_list_add_hook(void (*func)(char *));
extern void as_list_delete_hook(void (*func)(const char *));
-extern int config_bgp_aspath_validate(const char *regstr);
+extern bool config_bgp_aspath_validate(const char *regstr);
#endif /* _QUAGGA_BGP_FILTER_H */
diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h
index bc201b739..94c571f2f 100644
--- a/bgpd/bgp_flowspec.h
+++ b/bgpd/bgp_flowspec.h
@@ -43,7 +43,7 @@ extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
char *return_string, int format,
json_object *json_path);
-extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
+extern void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json_paths);
extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp,
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 002aae561..79d5268c7 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -76,9 +76,8 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len,
return ret;
}
-bool bgp_flowspec_contains_prefix(struct prefix *pfs,
- struct prefix *input,
- int prefix_check)
+bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
+ struct prefix *input, int prefix_check)
{
uint32_t offset = 0;
int type;
@@ -599,8 +598,8 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
}
/* return 1 if FS entry invalid or no NH IP */
-int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
- struct prefix *p)
+bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
+ struct prefix *p)
{
struct bgp_pbr_entry_main api;
int i;
@@ -609,7 +608,7 @@ int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
memset(&api, 0, sizeof(struct bgp_pbr_entry_main));
if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0)
- return 1;
+ return true;
for (i = 0; i < api.action_num; i++) {
api_action = &api.actions[i];
if (api_action->action != ACTION_REDIRECT_IP)
@@ -617,7 +616,7 @@ int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
p->family = AF_INET;
p->prefixlen = IPV4_MAX_BITLEN;
p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
- return 0;
+ return false;
}
- return 1;
+ return true;
}
diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h
index 2ce911da4..0e78c7a53 100644
--- a/bgpd/bgp_flowspec_util.h
+++ b/bgpd/bgp_flowspec_util.h
@@ -50,12 +50,11 @@ struct bgp_pbr_entry_main;
extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
struct bgp_pbr_entry_main *bpem);
-extern bool bgp_flowspec_contains_prefix(struct prefix *pfs,
+extern bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
struct prefix *input,
int prefix_check);
-extern int bgp_flowspec_get_first_nh(struct bgp *bgp,
- struct bgp_path_info *pi,
- struct prefix *nh);
+extern bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
+ struct prefix *nh);
#endif /* _FRR_BGP_FLOWSPEC_UTIL_H */
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index 80384c12c..c453c4e81 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -252,7 +252,7 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
}
}
-void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
+void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json_paths)
{
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 71e2b0260..fdffe374c 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -130,8 +130,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
afi_t afi;
safi_t safi;
int fd;
- int status, pstatus;
- unsigned char last_evt, last_maj_evt;
+ enum bgp_fsm_status status, pstatus;
+ enum bgp_fsm_events last_evt, last_maj_evt;
assert(from_peer != NULL);
@@ -456,6 +456,10 @@ void bgp_timer_set(struct peer *peer)
bgp_keepalives_off(peer);
BGP_TIMER_OFF(peer->t_routeadv);
break;
+ case BGP_STATUS_MAX:
+ flog_err(EC_LIB_DEVELOPMENT,
+ "BGP_STATUS_MAX while a legal state is not valid state for the FSM");
+ break;
}
}
@@ -660,32 +664,29 @@ static int bgp_graceful_deferral_timer_expire(struct thread *thread)
return bgp_best_path_select_defer(bgp, afi, safi);
}
-static int bgp_update_delay_applicable(struct bgp *bgp)
+static bool bgp_update_delay_applicable(struct bgp *bgp)
{
/* update_delay_over flag should be reset (set to 0) for any new
applicability of the update-delay during BGP process lifetime.
And it should be set after an occurence of the update-delay is
over)*/
if (!bgp->update_delay_over)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
-int bgp_update_delay_active(struct bgp *bgp)
+bool bgp_update_delay_active(struct bgp *bgp)
{
if (bgp->t_update_delay)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
-int bgp_update_delay_configured(struct bgp *bgp)
+bool bgp_update_delay_configured(struct bgp *bgp)
{
if (bgp->v_update_delay)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
/* Do the post-processing needed when bgp comes out of the read-only mode
@@ -836,28 +837,25 @@ void bgp_adjust_routeadv(struct peer *peer)
}
}
-static int bgp_maxmed_onstartup_applicable(struct bgp *bgp)
+static bool bgp_maxmed_onstartup_applicable(struct bgp *bgp)
{
if (!bgp->maxmed_onstartup_over)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
-int bgp_maxmed_onstartup_configured(struct bgp *bgp)
+bool bgp_maxmed_onstartup_configured(struct bgp *bgp)
{
if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
-int bgp_maxmed_onstartup_active(struct bgp *bgp)
+bool bgp_maxmed_onstartup_active(struct bgp *bgp)
{
if (bgp->t_maxmed_onstartup)
- return 1;
-
- return 0;
+ return true;
+ return false;
}
void bgp_maxmed_update(struct bgp *bgp)
@@ -885,6 +883,27 @@ void bgp_maxmed_update(struct bgp *bgp)
}
}
+int bgp_fsm_error_subcode(int status)
+{
+ int fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC;
+
+ switch (status) {
+ case OpenSent:
+ fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT;
+ break;
+ case OpenConfirm:
+ fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM;
+ break;
+ case Established:
+ fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED;
+ break;
+ default:
+ break;
+ }
+
+ return fsm_err_subcode;
+}
+
/* The maxmed onstartup timer expiry callback. */
static int bgp_maxmed_onstartup_timer(struct thread *thread)
{
@@ -1455,9 +1474,8 @@ static int bgp_connect_success(struct peer *peer)
flog_err_sys(EC_LIB_SOCKET,
"%s: bgp_getsockname(): failed for peer %s, fd %d",
__func__, peer->host, peer->fd);
- bgp_notify_send(
- peer, BGP_NOTIFY_FSM_ERR,
- BGP_NOTIFY_SUBCODE_UNSPECIFIC); /* internal error */
+ bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
+ bgp_fsm_error_subcode(peer->status));
bgp_writes_on(peer);
return -1;
}
@@ -1657,7 +1675,8 @@ static int bgp_fsm_event_error(struct peer *peer)
flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
- return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0);
+ return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR,
+ bgp_fsm_error_subcode(peer->status));
}
/* Hold timer expire. This is error of BGP connection. So cut the
@@ -1935,8 +1954,7 @@ static int bgp_establish(struct peer *peer)
hash_release(peer->bgp->peerhash, peer);
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
- bgp_bfd_deregister_peer(peer);
- bgp_bfd_register_peer(peer);
+ bgp_bfd_reset_peer(peer);
return ret;
}
@@ -2017,7 +2035,7 @@ void bgp_fsm_event_update(struct peer *peer, int valid)
/* Finite State Machine structure */
static const struct {
int (*func)(struct peer *);
- int next_state;
+ enum bgp_fsm_status next_state;
} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
{
/* Idle state: In Idle state, all events other than BGP_Start is
@@ -2164,7 +2182,7 @@ static const struct {
/* Execute event process. */
int bgp_event(struct thread *thread)
{
- int event;
+ enum bgp_fsm_events event;
struct peer *peer;
int ret;
@@ -2176,9 +2194,9 @@ int bgp_event(struct thread *thread)
return (ret);
}
-int bgp_event_update(struct peer *peer, int event)
+int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
{
- int next;
+ enum bgp_fsm_status next;
int ret = 0;
struct peer *other;
int passive_conn = 0;
@@ -2517,7 +2535,7 @@ int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd)
peer->peer_gr_present_state = peer_new_state;
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
- "[BGP_GR] Succesfully change the state of the peer to : %s : !",
+ "[BGP_GR] Successfully change the state of the peer to : %s : !",
print_peer_gr_mode(peer_new_state));
return BGP_GR_SUCCESS;
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index 6feabbf57..2fd5f6fc4 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -111,7 +111,7 @@
/* Prototypes. */
extern void bgp_fsm_event_update(struct peer *peer, int valid);
extern int bgp_event(struct thread *);
-extern int bgp_event_update(struct peer *, int event);
+extern int bgp_event_update(struct peer *, enum bgp_fsm_events event);
extern int bgp_stop(struct peer *peer);
extern void bgp_timer_set(struct peer *);
extern int bgp_routeadv_timer(struct thread *);
@@ -119,8 +119,9 @@ extern void bgp_fsm_change_status(struct peer *peer, int status);
extern const char *const peer_down_str[];
extern void bgp_update_delay_end(struct bgp *);
extern void bgp_maxmed_update(struct bgp *);
-extern int bgp_maxmed_onstartup_configured(struct bgp *);
-extern int bgp_maxmed_onstartup_active(struct bgp *);
+extern bool bgp_maxmed_onstartup_configured(struct bgp *);
+extern bool bgp_maxmed_onstartup_active(struct bgp *);
+extern int bgp_fsm_error_subcode(int status);
/**
* Start the route advertisement timer (that honors MRAI) for all the
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index 7a4435f6f..c21056f30 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -59,8 +59,8 @@ static void lcommunity_hash_free(struct lcommunity *lcom)
structure, we don't add the value. Newly added value is sorted by
numerical order. When the value is added to the structure return 1
else return 0. */
-static int lcommunity_add_val(struct lcommunity *lcom,
- struct lcommunity_val *lval)
+static bool lcommunity_add_val(struct lcommunity *lcom,
+ struct lcommunity_val *lval)
{
uint8_t *p;
int ret;
@@ -71,7 +71,7 @@ static int lcommunity_add_val(struct lcommunity *lcom,
lcom->size++;
lcom->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, lcom_length(lcom));
memcpy(lcom->val, lval->val, LCOMMUNITY_SIZE);
- return 1;
+ return true;
}
/* If the value already exists in the structure return 0. */
@@ -79,7 +79,7 @@ static int lcommunity_add_val(struct lcommunity *lcom,
for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) {
ret = memcmp(p, lval->val, LCOMMUNITY_SIZE);
if (ret == 0)
- return 0;
+ return false;
if (ret > 0)
break;
}
@@ -94,7 +94,7 @@ static int lcommunity_add_val(struct lcommunity *lcom,
(lcom->size - 1 - c) * LCOMMUNITY_SIZE);
memcpy(lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE);
- return 1;
+ return true;
}
/* This function takes pointer to Large Communites strucutre then
@@ -178,7 +178,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
int i;
int len;
char *str_buf;
- uint8_t *pnt;
+ const uint8_t *pnt;
uint32_t global, local1, local2;
json_object *json_lcommunity_list = NULL;
json_object *json_string = NULL;
@@ -456,7 +456,7 @@ struct lcommunity *lcommunity_str2com(const char *str)
return lcom;
}
-int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr)
+bool lcommunity_include(struct lcommunity *lcom, uint8_t *ptr)
{
int i;
uint8_t *lcom_ptr;
@@ -464,25 +464,25 @@ int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr)
for (i = 0; i < lcom->size; i++) {
lcom_ptr = lcom->val + (i * LCOMMUNITY_SIZE);
if (memcmp(ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0)
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int lcommunity_match(const struct lcommunity *lcom1,
- const struct lcommunity *lcom2)
+bool lcommunity_match(const struct lcommunity *lcom1,
+ const struct lcommunity *lcom2)
{
int i = 0;
int j = 0;
if (lcom1 == NULL && lcom2 == NULL)
- return 1;
+ return true;
if (lcom1 == NULL || lcom2 == NULL)
- return 0;
+ return false;
if (lcom1->size < lcom2->size)
- return 0;
+ return false;
/* Every community on com2 needs to be on com1 for this to match */
while (i < lcom1->size && j < lcom2->size) {
@@ -494,9 +494,9 @@ int lcommunity_match(const struct lcommunity *lcom1,
}
if (j == lcom2->size)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
/* Delete one lcommunity. */
diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h
index 7d63f4d26..e10ab0eef 100644
--- a/bgpd/bgp_lcommunity.h
+++ b/bgpd/bgp_lcommunity.h
@@ -66,10 +66,10 @@ extern void lcommunity_unintern(struct lcommunity **);
extern unsigned int lcommunity_hash_make(const void *);
extern struct hash *lcommunity_hash(void);
extern struct lcommunity *lcommunity_str2com(const char *);
-extern int lcommunity_match(const struct lcommunity *,
- const struct lcommunity *);
+extern bool lcommunity_match(const struct lcommunity *,
+ const struct lcommunity *);
extern char *lcommunity_str(struct lcommunity *, bool make_json);
-extern int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr);
+extern bool lcommunity_include(struct lcommunity *lcom, uint8_t *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr);
extern void bgp_compute_aggregate_lcommunity(
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 8758d0ca7..3e2ba9802 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -385,13 +385,13 @@ int vpn_leak_label_callback(
return 0;
}
-static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
+static bool ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
{
int i;
int j;
if (!e1 || !e2)
- return 0;
+ return false;
for (i = 0; i < e1->size; ++i) {
for (j = 0; j < e2->size; ++j) {
@@ -399,11 +399,11 @@ static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
e2->val + (j * ECOMMUNITY_SIZE),
ECOMMUNITY_SIZE)) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
@@ -744,10 +744,15 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
struct ecommunity *old_ecom;
struct ecommunity *new_ecom;
+ /* Export with the 'from' instance's export RTs. */
+ /* If doing VRF-to-VRF leaking, strip existing RTs first. */
old_ecom = static_attr.ecommunity;
if (old_ecom) {
- new_ecom = ecommunity_merge(
- ecommunity_dup(old_ecom),
+ new_ecom = ecommunity_dup(old_ecom);
+ if (CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT))
+ ecommunity_strip_rts(new_ecom);
+ new_ecom = ecommunity_merge(new_ecom,
bgp_vrf->vpn_policy[afi]
.rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
if (!old_ecom->refcnt)
@@ -1087,6 +1092,20 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
/* shallow copy */
static_attr = *path_vpn->attr;
+ struct ecommunity *old_ecom;
+ struct ecommunity *new_ecom;
+
+ /* If doing VRF-to-VRF leaking, strip RTs. */
+ old_ecom = static_attr.ecommunity;
+ if (old_ecom && CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ new_ecom = ecommunity_dup(old_ecom);
+ ecommunity_strip_rts(new_ecom);
+ static_attr.ecommunity = new_ecom;
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ }
+
/*
* Nexthop: stash and clear
*
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index ab0c3a3f1..23c5adbf2 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -470,8 +470,8 @@ static void bgp_connected_cleanup(struct route_table *table,
}
}
-int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type,
- struct attr *attr, struct bgp_node *rn)
+bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
+ uint8_t sub_type, struct attr *attr, struct bgp_node *rn)
{
uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6;
struct bgp_addr tmp_addr = {{0}}, *addr = NULL;
@@ -505,7 +505,7 @@ int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type,
attr->mp_nexthop_global_in;
tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
} else
- return 0;
+ return false;
}
break;
case AF_INET6:
@@ -523,7 +523,7 @@ int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type,
addr = hash_lookup(bgp->address_hash, &tmp_addr);
if (addr)
- return 1;
+ return true;
if (new_afi == AF_INET) {
memset(&tmp_tip, 0, sizeof(struct tip_addr));
@@ -539,13 +539,13 @@ int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type,
tip = hash_lookup(bgp->tip_hash, &tmp_tip);
if (tip)
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
+bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
{
struct bgp_node *rn1;
struct bgp_node *rn2;
@@ -558,7 +558,7 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
if (!rn1)
- return 0;
+ return false;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
@@ -567,18 +567,18 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
if (!rn2) {
bgp_unlock_node(rn1);
- return 0;
+ return false;
}
- ret = (rn1 == rn2) ? 1 : 0;
+ ret = (rn1 == rn2);
bgp_unlock_node(rn1);
bgp_unlock_node(rn2);
- return (ret);
+ return ret;
}
-int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
+bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
{
struct bgp_node *rn1;
struct bgp_node *rn2;
@@ -591,7 +591,7 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
if (!rn1)
- return 0;
+ return false;
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
@@ -600,10 +600,10 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
if (!rn2) {
bgp_unlock_node(rn1);
- return 0;
+ return false;
}
- ret = (rn1 == rn2) ? 1 : 0;
+ ret = (rn1 == rn2);
bgp_unlock_node(rn1);
bgp_unlock_node(rn2);
@@ -611,8 +611,9 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
return ret;
}
-int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
- struct update_subgroup *subgrp)
+bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
+ struct update_subgroup *subgrp,
+ struct peer *exclude)
{
struct bgp_node *rn1 = NULL, *rn2 = NULL;
struct peer_af *paf = NULL;
@@ -629,16 +630,19 @@ int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
bgp = SUBGRP_INST(subgrp);
rn1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np);
if (!rn1)
- return 0;
+ return false;
SUBGRP_FOREACH_PEER (subgrp, paf) {
+ /* Skip peer we're told to exclude - e.g., source of route. */
+ if (paf->peer == exclude)
+ continue;
p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
rn2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
if (rn1 == rn2) {
bgp_unlock_node(rn1);
bgp_unlock_node(rn2);
- return 1;
+ return true;
}
if (rn2)
@@ -646,11 +650,12 @@ int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
}
bgp_unlock_node(rn1);
- return 0;
+ return false;
}
-int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
- struct update_subgroup *subgrp)
+bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
+ struct update_subgroup *subgrp,
+ struct peer *exclude)
{
struct bgp_node *rn1, *rn2;
struct peer_af *paf;
@@ -667,16 +672,20 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
bgp = SUBGRP_INST(subgrp);
rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
if (!rn1)
- return 0;
+ return false;
SUBGRP_FOREACH_PEER (subgrp, paf) {
+ /* Skip peer we're told to exclude - e.g., source of route. */
+ if (paf->peer == exclude)
+ continue;
+
p.u.prefix4 = paf->peer->su.sin.sin_addr;
rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
if (rn1 == rn2) {
bgp_unlock_node(rn1);
bgp_unlock_node(rn2);
- return 1;
+ return true;
}
if (rn2)
@@ -684,7 +693,7 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
}
bgp_unlock_node(rn1);
- return 0;
+ return false;
}
static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index af4c0bc04..461e77211 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -81,16 +81,19 @@ struct bgp_addrv6 {
extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete(struct bgp *bgp, struct connected *c);
-extern int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
- struct update_subgroup *subgrp);
-extern int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
- struct update_subgroup *subgrp);
-extern int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer);
-extern int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer);
+extern bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
+ struct update_subgroup *subgrp,
+ struct peer *exclude);
+extern bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
+ struct update_subgroup *subgrp,
+ struct peer *exclude);
+extern bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer);
+extern bool bgp_multiaccess_check_v6(struct in6_addr nexthop,
+ struct peer *peer);
extern int bgp_config_write_scan_time(struct vty *);
-extern int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
- uint8_t sub_type, struct attr *attr,
- struct bgp_node *rn);
+extern bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
+ uint8_t sub_type, struct attr *attr,
+ struct bgp_node *rn);
extern struct bgp_nexthop_cache *bnc_new(void);
extern void bnc_free(struct bgp_nexthop_cache *bnc);
extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 81bb45aa7..4a2f7d588 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1013,15 +1013,15 @@ static int bgp_auth_parse(struct peer *peer, size_t length)
return -1;
}
-static int strict_capability_same(struct peer *peer)
+static bool strict_capability_same(struct peer *peer)
{
int i, j;
for (i = AFI_IP; i < AFI_MAX; i++)
for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
if (peer->afc[i][j] != peer->afc_nego[i][j])
- return 0;
- return 1;
+ return false;
+ return true;
}
/* peek into option, stores ASN to *as4 if the AS4 capability was found.
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 0e251dced..10e96497f 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -587,7 +587,7 @@ void bgp_open_send(struct peer *peer)
* @param peer
* @return 0
*/
-static int bgp_write_notify(struct peer *peer)
+static void bgp_write_notify(struct peer *peer)
{
int ret, val;
uint8_t type;
@@ -597,7 +597,7 @@ static int bgp_write_notify(struct peer *peer)
s = stream_fifo_pop(peer->obuf);
if (!s)
- return 0;
+ return;
assert(stream_get_endp(s) >= BGP_HEADER_SIZE);
@@ -617,7 +617,7 @@ static int bgp_write_notify(struct peer *peer)
if (ret <= 0) {
stream_free(s);
BGP_EVENT_ADD(peer, TCP_fatal_error);
- return 0;
+ return;
}
/* Disable Nagle, make NOTIFY packet go out right away */
@@ -649,8 +649,6 @@ static int bgp_write_notify(struct peer *peer)
BGP_EVENT_ADD(peer, BGP_Stop);
stream_free(s);
-
- return 0;
}
/*
@@ -1142,6 +1140,15 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
return BGP_Stop;
}
+ /* Codification of AS 0 Processing */
+ if (remote_as == BGP_AS_ZERO) {
+ flog_err(EC_BGP_PKT_OPEN, "%s bad OPEN, got AS set to 0",
+ peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_BAD_PEER_AS);
+ return BGP_Stop;
+ }
+
if (remote_as == BGP_AS_TRANS) {
/* Take the AS4 from the capability. We must have received the
* capability now! Otherwise we have a asn16 peer who uses
@@ -1447,7 +1454,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
peer->host,
lookup_msg(bgp_status_msg, peer->status, NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ bgp_fsm_error_subcode(peer->status));
return BGP_Stop;
}
@@ -1859,7 +1866,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
peer->host,
lookup_msg(bgp_status_msg, peer->status, NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ bgp_fsm_error_subcode(peer->status));
return BGP_Stop;
}
@@ -2251,7 +2258,7 @@ int bgp_capability_receive(struct peer *peer, bgp_size_t size)
peer->host,
lookup_msg(bgp_status_msg, peer->status, NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ bgp_fsm_error_subcode(peer->status));
return BGP_Stop;
}
@@ -2328,7 +2335,7 @@ int bgp_process_packet(struct thread *thread)
flog_err(
EC_BGP_PKT_OPEN,
"%s: BGP OPEN receipt failed for peer: %s",
- __FUNCTION__, peer->host);
+ __func__, peer->host);
break;
case BGP_MSG_UPDATE:
atomic_fetch_add_explicit(&peer->update_in, 1,
@@ -2339,7 +2346,7 @@ int bgp_process_packet(struct thread *thread)
flog_err(
EC_BGP_UPDATE_RCV,
"%s: BGP UPDATE receipt failed for peer: %s",
- __FUNCTION__, peer->host);
+ __func__, peer->host);
break;
case BGP_MSG_NOTIFY:
atomic_fetch_add_explicit(&peer->notify_in, 1,
@@ -2349,7 +2356,7 @@ int bgp_process_packet(struct thread *thread)
flog_err(
EC_BGP_NOTIFY_RCV,
"%s: BGP NOTIFY receipt failed for peer: %s",
- __FUNCTION__, peer->host);
+ __func__, peer->host);
break;
case BGP_MSG_KEEPALIVE:
peer->readtime = monotime(NULL);
@@ -2360,7 +2367,7 @@ int bgp_process_packet(struct thread *thread)
flog_err(
EC_BGP_KEEP_RCV,
"%s: BGP KEEPALIVE receipt failed for peer: %s",
- __FUNCTION__, peer->host);
+ __func__, peer->host);
break;
case BGP_MSG_ROUTE_REFRESH_NEW:
case BGP_MSG_ROUTE_REFRESH_OLD:
@@ -2371,7 +2378,7 @@ int bgp_process_packet(struct thread *thread)
flog_err(
EC_BGP_RFSH_RCV,
"%s: BGP ROUTEREFRESH receipt failed for peer: %s",
- __FUNCTION__, peer->host);
+ __func__, peer->host);
break;
case BGP_MSG_CAPABILITY:
atomic_fetch_add_explicit(&peer->dynamic_cap_in, 1,
@@ -2381,7 +2388,7 @@ int bgp_process_packet(struct thread *thread)
flog_err(
EC_BGP_CAP_RCV,
"%s: BGP CAPABILITY receipt failed for peer: %s",
- __FUNCTION__, peer->host);
+ __func__, peer->host);
break;
default:
/* Suppress uninitialized variable warning */
diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c
index be950dfa5..ea9758349 100644
--- a/bgpd/bgp_rd.c
+++ b/bgpd/bgp_rd.c
@@ -37,7 +37,7 @@
#include "bgpd/rfapi/rfapi_backend.h"
#endif
-uint16_t decode_rd_type(uint8_t *pnt)
+uint16_t decode_rd_type(const uint8_t *pnt)
{
uint16_t v;
@@ -60,7 +60,7 @@ void encode_rd_type(uint16_t v, uint8_t *pnt)
}
/* type == RD_TYPE_AS */
-void decode_rd_as(uint8_t *pnt, struct rd_as *rd_as)
+void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as)
{
rd_as->as = (uint16_t)*pnt++ << 8;
rd_as->as |= (uint16_t)*pnt++;
@@ -68,7 +68,7 @@ void decode_rd_as(uint8_t *pnt, struct rd_as *rd_as)
}
/* type == RD_TYPE_AS4 */
-void decode_rd_as4(uint8_t *pnt, struct rd_as *rd_as)
+void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as)
{
pnt = ptr_get_be32(pnt, &rd_as->as);
rd_as->val = ((uint16_t)*pnt++ << 8);
diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h
index c5ea34103..da8c553b4 100644
--- a/bgpd/bgp_rd.h
+++ b/bgpd/bgp_rd.h
@@ -54,11 +54,11 @@ struct rd_vnc_eth {
};
#endif
-extern uint16_t decode_rd_type(uint8_t *pnt);
+extern uint16_t decode_rd_type(const uint8_t *pnt);
extern void encode_rd_type(uint16_t, uint8_t *);
-extern void decode_rd_as(uint8_t *pnt, struct rd_as *rd_as);
-extern void decode_rd_as4(uint8_t *pnt, struct rd_as *rd_as);
+extern void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as);
+extern void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as);
extern void decode_rd_ip(uint8_t *pnt, struct rd_ip *rd_ip);
#if ENABLE_BGP_VNC
extern void decode_rd_vnc_eth(uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index c2c034d16..1bd5780a2 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -146,7 +146,7 @@ struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
}
struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
- safi_t safi, struct prefix *p,
+ safi_t safi, const struct prefix *p,
struct prefix_rd *prd)
{
struct bgp_node *rn;
@@ -1241,7 +1241,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
#undef FILTER_EXIST_WARN
}
-static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
+static enum filter_type bgp_output_filter(struct peer *peer,
+ const struct prefix *p,
struct attr *attr, afi_t afi,
safi_t safi)
{
@@ -1282,30 +1283,30 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
}
/* If community attribute includes no_export then return 1. */
-static int bgp_community_filter(struct peer *peer, struct attr *attr)
+static bool bgp_community_filter(struct peer *peer, struct attr *attr)
{
if (attr->community) {
/* NO_ADVERTISE check. */
if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
- return 1;
+ return true;
/* NO_EXPORT check. */
if (peer->sort == BGP_PEER_EBGP
&& community_include(attr->community, COMMUNITY_NO_EXPORT))
- return 1;
+ return true;
/* NO_EXPORT_SUBCONFED check. */
if (peer->sort == BGP_PEER_EBGP
|| peer->sort == BGP_PEER_CONFED)
if (community_include(attr->community,
COMMUNITY_NO_EXPORT_SUBCONFED))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Route reflection loop check. */
-static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
+static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
{
struct in_addr cluster_id;
@@ -1316,9 +1317,9 @@ static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
cluster_id = peer->bgp->router_id;
if (cluster_loop_check(attr->cluster, cluster_id))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
static int bgp_input_modifier(struct peer *peer, struct prefix *p,
@@ -1543,9 +1544,9 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
}
-int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
- struct update_subgroup *subgrp, struct prefix *p,
- struct attr *attr)
+bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
+ struct update_subgroup *subgrp,
+ const struct prefix *p, struct attr *attr)
{
struct bgp_filter *filter;
struct peer *from;
@@ -1562,7 +1563,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
int samepeer_safe = 0; /* for synthetic mplsvpns routes */
if (DISABLE_BGP_ANNOUNCE)
- return 0;
+ return false;
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
@@ -1609,7 +1610,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
|| CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
|| CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
- return 0;
+ return false;
}
/* If this is not the bestpath then check to see if there is an enabled
@@ -1617,14 +1618,14 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
* feature that requires us to advertise it */
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
- return 0;
+ return false;
}
}
/* Aggregate-address suppress check. */
if (pi->extra && pi->extra->suppress)
if (!UNSUPPRESS_MAP_NAME(filter)) {
- return 0;
+ return false;
}
/*
@@ -1635,7 +1636,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
*/
if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
&& pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
- return 0;
+ return false;
/* If it's labeled safi, make sure the route has a valid label. */
if (safi == SAFI_LABELED_UNICAST) {
@@ -1648,13 +1649,13 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
inet_ntop(p->family, &p->u.prefix,
buf, SU_ADDRSTRLEN),
p->prefixlen, &label);
- return 0;
+ return false;
}
}
/* Do not send back route to sender. */
if (onlypeer && from == onlypeer) {
- return 0;
+ return false;
}
/* Do not send the default route in the BGP table if the neighbor is
@@ -1662,9 +1663,9 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if (CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_DEFAULT_ORIGINATE)) {
if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
- return 0;
+ return false;
else if (p->family == AF_INET6 && p->prefixlen == 0)
- return 0;
+ return false;
}
/* Transparency check. */
@@ -1679,7 +1680,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
"subgrpannouncecheck: community filter check fail");
- return 0;
+ return false;
}
/* If the attribute has originator-id and it is same as remote
@@ -1692,7 +1693,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
"remote router-id",
onlypeer->host,
prefix2str(p, buf, sizeof(buf)));
- return 0;
+ return false;
}
/* ORF prefix-list filter check */
@@ -1710,7 +1711,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
peer->host,
prefix2str(p, buf,
sizeof(buf)));
- return 0;
+ return false;
}
}
@@ -1719,7 +1720,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug("%s [Update:SEND] %s is filtered",
peer->host, prefix2str(p, buf, sizeof(buf)));
- return 0;
+ return false;
}
/* AS path loop check. */
@@ -1730,7 +1731,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
"%s [Update:SEND] suppress announcement to peer AS %u "
"that is part of AS path.",
onlypeer->host, onlypeer->as);
- return 0;
+ return false;
}
/* If we're a CONFED we need to loop check the CONFED ID too */
@@ -1741,7 +1742,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
"%s [Update:SEND] suppress announcement to peer AS %u"
" is AS path.",
peer->host, bgp->confed_id);
- return 0;
+ return false;
}
}
@@ -1765,13 +1766,13 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
BGP_FLAG_NO_CLIENT_TO_CLIENT))
if (CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_REFLECTOR_CLIENT))
- return 0;
+ return false;
} else {
/* A route from a Non-client peer. Reflect to all other
clients. */
if (!CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_REFLECTOR_CLIENT))
- return 0;
+ return false;
}
}
@@ -1875,16 +1876,9 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
struct attr dummy_attr = {0};
- memset(&rmap_path, 0, sizeof(struct bgp_path_info));
- rmap_path.peer = peer;
- rmap_path.attr = attr;
- rmap_path.net = rn;
-
- if (pi->extra) {
- memcpy(&dummy_rmap_path_extra, pi->extra,
- sizeof(struct bgp_path_info_extra));
- rmap_path.extra = &dummy_rmap_path_extra;
- }
+ /* Fill temp path_info */
+ prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra,
+ rn, pi, peer, attr);
/* don't confuse inbound and outbound setting */
RESET_FLAG(attr->rmap_change_flags);
@@ -1917,7 +1911,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
peer->host, prefix2str(p, buf, sizeof(buf)));
bgp_attr_flush(attr);
- return 0;
+ return false;
}
}
@@ -1933,7 +1927,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if (peer->bgp->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED)
if (!bgp_outbound_policy_exists(peer, filter))
- return 0;
+ return false;
/* draft-ietf-idr-deprecate-as-set-confed-set
* Filter routes having AS_SET or AS_CONFED_SET in the path.
@@ -1943,7 +1937,11 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
*/
if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
if (aspath_check_as_sets(attr->aspath))
- return 0;
+ return false;
+
+ /* Codification of AS 0 Processing */
+ if (aspath_check_as_zero(attr->aspath))
+ return 0;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
if (peer->sort == BGP_PEER_IBGP
@@ -2002,7 +2000,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if ((p->family == AF_INET) &&
(!bgp_subgrp_multiaccess_check_v4(
piattr->nexthop,
- subgrp)))
+ subgrp, from)))
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
@@ -2012,7 +2010,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if ((p->family == AF_INET6) &&
(!bgp_subgrp_multiaccess_check_v6(
piattr->mp_nexthop_global,
- subgrp)))
+ subgrp, from)))
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
@@ -2051,7 +2049,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
subgroup_announce_reset_nhop(AF_INET6, attr);
}
- return 1;
+ return true;
}
static int bgp_route_select_timer_expire(struct thread *thread)
@@ -2103,6 +2101,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
if (debug)
prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
+ rn->reason = bgp_path_selection_none;
/* bgp deterministic-med */
new_select = NULL;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
@@ -2182,6 +2181,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
new_select = NULL;
for (pi = bgp_node_get_bgp_path_info(rn);
(pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
+ enum bgp_path_selection_reason reason;
+
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
old_select = pi;
@@ -2222,8 +2223,12 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
+ reason = rn->reason;
if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
debug, pfx_buf, afi, safi, &rn->reason)) {
+ if (new_select == NULL &&
+ reason != bgp_path_selection_none)
+ rn->reason = reason;
new_select = pi;
}
}
@@ -2309,10 +2314,10 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
* A new route/change in bestpath of an existing route. Evaluate the path
* for advertisement to the subgroup.
*/
-int subgroup_process_announce_selected(struct update_subgroup *subgrp,
- struct bgp_path_info *selected,
- struct bgp_node *rn,
- uint32_t addpath_tx_id)
+void subgroup_process_announce_selected(struct update_subgroup *subgrp,
+ struct bgp_path_info *selected,
+ struct bgp_node *rn,
+ uint32_t addpath_tx_id)
{
struct prefix *p;
struct peer *onlypeer;
@@ -2336,7 +2341,7 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp,
/* First update is deferred until ORF or ROUTE-REFRESH is received */
if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
PEER_STATUS_ORF_WAIT_REFRESH))
- return 0;
+ return;
memset(&attr, 0, sizeof(struct attr));
/* It's initialized in bgp_announce_check() */
@@ -2355,8 +2360,6 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp,
else {
bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
}
-
- return 0;
}
/*
@@ -2380,8 +2383,8 @@ void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
* if the route selection returns the same best route as earlier - to
* determine if we need to update zebra or not.
*/
-int bgp_zebra_has_route_changed(struct bgp_node *rn,
- struct bgp_path_info *selected)
+bool bgp_zebra_has_route_changed(struct bgp_node *rn,
+ struct bgp_path_info *selected)
{
struct bgp_path_info *mpinfo;
@@ -2393,7 +2396,7 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn,
*/
if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
|| CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
- return 1;
+ return true;
/*
* If this is multipath, check all selected paths for any nexthop change
@@ -2402,11 +2405,11 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn,
mpinfo = bgp_path_info_mpath_next(mpinfo)) {
if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
|| CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
- return 1;
+ return true;
}
/* Nothing has changed from the RIB's perspective. */
- return 0;
+ return false;
}
struct bgp_process_queue {
@@ -2486,7 +2489,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
*/
if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("SELECT_DEFER falg set for route %p", rn);
+ zlog_debug("SELECT_DEFER flag set for route %p", rn);
return;
}
@@ -2682,17 +2685,31 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
/* apply the route-map */
if (bgp->adv_cmd_rmap[afi][safi].map) {
route_map_result_t ret;
+ struct bgp_path_info rmap_path;
+ struct bgp_path_info_extra rmap_path_extra;
+ struct attr dummy_attr;
+
+ dummy_attr = *new_select->attr;
+
+ /* Fill temp path_info */
+ prep_for_rmap_apply(
+ &rmap_path, &rmap_path_extra,
+ rn, new_select, new_select->peer,
+ &dummy_attr);
+
+ RESET_FLAG(dummy_attr.rmap_change_flags);
ret = route_map_apply(
bgp->adv_cmd_rmap[afi][safi].map,
- &rn->p, RMAP_BGP, new_select);
- if (ret == RMAP_PERMITMATCH)
- bgp_evpn_advertise_type5_route(
- bgp, &rn->p, new_select->attr,
- afi, safi);
- else
+ &rn->p, RMAP_BGP, &rmap_path);
+ if (ret == RMAP_DENYMATCH) {
+ bgp_attr_flush(&dummy_attr);
bgp_evpn_withdraw_type5_route(
bgp, &rn->p, afi, safi);
+ } else
+ bgp_evpn_advertise_type5_route(
+ bgp, &rn->p, &dummy_attr,
+ afi, safi);
} else {
bgp_evpn_advertise_type5_route(bgp,
&rn->p,
@@ -2930,20 +2947,20 @@ static int bgp_maximum_prefix_restart_timer(struct thread *thread)
return 0;
}
-int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
- int always)
+bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
+ int always)
{
iana_afi_t pkt_afi;
iana_safi_t pkt_safi;
if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
- return 0;
+ return false;
if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
if (CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_LIMIT)
&& !always)
- return 0;
+ return false;
zlog_info(
"%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
@@ -2954,7 +2971,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
if (CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING))
- return 0;
+ return false;
/* Convert AFI, SAFI to values for packet. */
pkt_afi = afi_int2iana(afi);
@@ -2978,7 +2995,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
/* Dynamic peers will just close their connection. */
if (peer_dynamic_neighbor(peer))
- return 1;
+ return true;
/* restart timer start */
if (peer->pmax_restart[afi][safi]) {
@@ -2995,7 +3012,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
peer->v_pmax_restart);
}
- return 1;
+ return true;
} else
UNSET_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_LIMIT);
@@ -3005,7 +3022,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
if (CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_THRESHOLD)
&& !always)
- return 0;
+ return false;
zlog_info(
"%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
@@ -3017,7 +3034,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
} else
UNSET_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_THRESHOLD);
- return 0;
+ return false;
}
/* Unconditionally remove the route from the RIB, without taking
@@ -3186,23 +3203,23 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
}
/* Check if received nexthop is valid or not. */
-static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
- uint8_t type, uint8_t stype,
- struct attr *attr, struct bgp_node *rn)
+static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
+ uint8_t type, uint8_t stype,
+ struct attr *attr, struct bgp_node *rn)
{
- int ret = 0;
+ bool ret = 0;
/* Only validated for unicast and multicast currently. */
/* Also valid for EVPN where the nexthop is an IP address. */
if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
- return 0;
+ return false;
/* If NEXT_HOP is present, validate it. */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
if (attr->nexthop.s_addr == INADDR_ANY
|| IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
|| bgp_nexthop_self(bgp, afi, type, stype, attr, rn))
- return 1;
+ return true;
}
/* If MP_NEXTHOP is present, validate it. */
@@ -3233,7 +3250,7 @@ static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
break;
default:
- ret = 1;
+ ret = true;
break;
}
}
@@ -4592,30 +4609,30 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
}
}
-int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
+bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
if (peer->sort == BGP_PEER_IBGP)
- return 1;
+ return true;
if (peer->sort == BGP_PEER_EBGP
&& (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
|| FILTER_LIST_OUT_NAME(filter)
|| DISTRIBUTE_OUT_NAME(filter)))
- return 1;
- return 0;
+ return true;
+ return false;
}
-int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
+bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
if (peer->sort == BGP_PEER_IBGP)
- return 1;
+ return true;
if (peer->sort == BGP_PEER_EBGP
&& (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
|| FILTER_LIST_IN_NAME(filter)
|| DISTRIBUTE_IN_NAME(filter)))
- return 1;
- return 0;
+ return true;
+ return false;
}
static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
@@ -6005,11 +6022,11 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
XFREE(MTYPE_BGP_AGGREGATE, aggregate);
}
-static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
- struct aspath *aspath,
- struct community *comm,
- struct ecommunity *ecomm,
- struct lcommunity *lcomm)
+static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
+ struct aspath *aspath,
+ struct community *comm,
+ struct ecommunity *ecomm,
+ struct lcommunity *lcomm)
{
static struct aspath *ae = NULL;
@@ -6017,27 +6034,27 @@ static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
ae = aspath_empty();
if (!pi)
- return 0;
+ return false;
if (origin != pi->attr->origin)
- return 0;
+ return false;
if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
- return 0;
+ return false;
if (!community_cmp(pi->attr->community, comm))
- return 0;
+ return false;
if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
- return 0;
+ return false;
if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
- return 0;
+ return false;
if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
- return 0;
+ return false;
- return 1;
+ return true;
}
static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
@@ -7326,7 +7343,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
}
/* Static function to display route. */
-static void route_vty_out_route(struct prefix *p, struct vty *vty,
+static void route_vty_out_route(const struct prefix *p, struct vty *vty,
json_object *json)
{
int len = 0;
@@ -7483,7 +7500,7 @@ static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
}
/* called from terminal list command */
-void route_vty_out(struct vty *vty, struct prefix *p,
+void route_vty_out(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display, safi_t safi,
json_object *json_paths)
{
@@ -8079,7 +8096,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
vty_out(vty, "\n");
}
-void route_vty_out_tag(struct vty *vty, struct prefix *p,
+void route_vty_out_tag(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display, safi_t safi,
json_object *json)
{
@@ -8172,7 +8189,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
}
}
-void route_vty_out_overlay(struct vty *vty, struct prefix *p,
+void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json_paths)
{
@@ -12280,7 +12297,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str,
}
/* Apply BGP information to distance method. */
-uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
+uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
afi_t afi, safi_t safi, struct bgp *bgp)
{
struct bgp_node *rn;
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 0ad656d13..7115f2668 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -467,6 +467,23 @@ static inline bool is_pi_family_matching(struct bgp_path_info *pi,
return false;
}
+static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi,
+ struct bgp_path_info_extra *dst_pie,
+ struct bgp_node *rn,
+ struct bgp_path_info *src_pi,
+ struct peer *peer, struct attr *attr)
+{
+ memset(dst_pi, 0, sizeof(struct bgp_path_info));
+ dst_pi->peer = peer;
+ dst_pi->attr = attr;
+ dst_pi->net = rn;
+ if (src_pi->extra) {
+ memcpy(dst_pie, src_pi->extra,
+ sizeof(struct bgp_path_info_extra));
+ dst_pi->extra = dst_pie;
+ }
+}
+
/* called before bgp_process() */
DECLARE_HOOK(bgp_process,
(struct bgp *bgp, afi_t afi, safi_t safi,
@@ -489,8 +506,8 @@ extern void bgp_clear_route(struct peer *, afi_t, safi_t);
extern void bgp_clear_route_all(struct peer *);
extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t);
extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t);
-extern int bgp_outbound_policy_exists(struct peer *, struct bgp_filter *);
-extern int bgp_inbound_policy_exists(struct peer *, struct bgp_filter *);
+extern bool bgp_outbound_policy_exists(struct peer *, struct bgp_filter *);
+extern bool bgp_inbound_policy_exists(struct peer *, struct bgp_filter *);
extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p,
@@ -512,7 +529,7 @@ extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi,
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
-extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
+extern bool bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
const union g_addr *nexthop, ifindex_t ifindex,
@@ -573,8 +590,9 @@ extern void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
struct bgp_path_info *path, afi_t afi,
safi_t safi);
-extern uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *path,
- afi_t afi, safi_t safi, struct bgp *bgp);
+extern uint8_t bgp_distance_apply(const struct prefix *p,
+ struct bgp_path_info *path, afi_t afi,
+ safi_t safi, struct bgp *bgp);
extern afi_t bgp_node_afi(struct vty *);
extern safi_t bgp_node_safi(struct vty *);
@@ -584,35 +602,35 @@ extern struct bgp_path_info *info_make(int type, int sub_type,
struct peer *peer, struct attr *attr,
struct bgp_node *rn);
-extern void route_vty_out(struct vty *vty, struct prefix *p,
+extern void route_vty_out(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display, safi_t safi,
json_object *json_paths);
-extern void route_vty_out_tag(struct vty *vty, struct prefix *p,
+extern void route_vty_out_tag(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
safi_t safi, json_object *json);
extern void route_vty_out_tmp(struct vty *vty, struct prefix *p,
struct attr *attr, safi_t safi, bool use_json,
json_object *json_ar);
-extern void route_vty_out_overlay(struct vty *vty, struct prefix *p,
+extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json);
-extern int subgroup_process_announce_selected(struct update_subgroup *subgrp,
- struct bgp_path_info *selected,
- struct bgp_node *rn,
- uint32_t addpath_tx_id);
+extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
+ struct bgp_path_info *selected,
+ struct bgp_node *rn,
+ uint32_t addpath_tx_id);
-extern int subgroup_announce_check(struct bgp_node *rn,
- struct bgp_path_info *pi,
- struct update_subgroup *subgrp,
- struct prefix *p, struct attr *attr);
+extern bool subgroup_announce_check(struct bgp_node *rn,
+ struct bgp_path_info *pi,
+ struct update_subgroup *subgrp,
+ const struct prefix *p, struct attr *attr);
extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
extern void bgp_process_queues_drain_immediate(void);
/* for encap/vpn */
extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
- safi_t safi, struct prefix *p,
+ safi_t safi, const struct prefix *p,
struct prefix_rd *prd);
extern void bgp_path_info_restore(struct bgp_node *rn,
struct bgp_path_info *path);
@@ -629,8 +647,8 @@ extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
struct bgp_path_info_pair *result, afi_t afi,
safi_t safi);
extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn);
-extern int bgp_zebra_has_route_changed(struct bgp_node *rn,
- struct bgp_path_info *selected);
+extern bool bgp_zebra_has_route_changed(struct bgp_node *rn,
+ struct bgp_path_info *selected);
extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
struct bgp_node *rn,
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 52b540273..029570df3 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2830,6 +2830,57 @@ static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
route_match_ipv6_next_hop_free
};
+/* `match ip next-hop IP_ADDRESS' */
+
+static enum route_map_cmd_result_t
+route_match_ipv4_next_hop(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct in_addr *addr = rule;
+ struct bgp_path_info *path;
+
+ if (type == RMAP_BGP) {
+ path = object;
+
+ if (path->attr->nexthop.s_addr == addr->s_addr ||
+ (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4 &&
+ IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv4_next_hop_compile(const char *arg)
+{
+ struct in_addr *address;
+ int ret;
+
+ address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
+
+ ret = inet_pton(AF_INET, arg, address);
+ if (!ret) {
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
+ return NULL;
+ }
+
+ return address;
+}
+
+static void route_match_ipv4_next_hop_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
+ "ip next-hop address",
+ route_match_ipv4_next_hop,
+ route_match_ipv4_next_hop_compile,
+ route_match_ipv4_next_hop_free
+};
+
/* `match ipv6 address prefix-list PREFIX_LIST' */
static enum route_map_cmd_result_t
@@ -5110,6 +5161,28 @@ DEFUN (no_match_ipv6_next_hop,
RMAP_EVENT_MATCH_DELETED);
}
+DEFPY (match_ipv4_next_hop,
+ match_ipv4_next_hop_cmd,
+ "[no$no] match ip next-hop address [A.B.C.D]",
+ NO_STR
+ MATCH_STR
+ IP_STR
+ "Match IP next-hop address of route\n"
+ "IP address\n"
+ "IP address of next-hop\n")
+{
+ int idx_ipv4 = 4;
+
+ if (no)
+ return bgp_route_match_delete(vty, "ip next-hop address", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+
+ if (argv[idx_ipv4]->arg)
+ return bgp_route_match_add(vty, "ip next-hop address",
+ argv[idx_ipv4]->arg,
+ RMAP_EVENT_MATCH_ADDED);
+ return CMD_SUCCESS;
+}
DEFUN (set_ipv6_nexthop_peer,
set_ipv6_nexthop_peer_cmd,
@@ -5563,6 +5636,7 @@ void bgp_route_map_init(void)
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_ipv4_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);
@@ -5572,6 +5646,7 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
+ install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 2ca0c7b96..ee1c49666 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -94,6 +94,7 @@ enum return_values { SUCCESS = 0, ERROR = -1 };
struct rpki_for_each_record_arg {
struct vty *vty;
unsigned int *prefix_amount;
+ as_t as;
};
static int start(void);
@@ -273,6 +274,17 @@ static void print_record(const struct pfx_record *record, struct vty *vty)
record->max_len, record->asn);
}
+static void print_record_by_asn(const struct pfx_record *record, void *data)
+{
+ struct rpki_for_each_record_arg *arg = data;
+ struct vty *vty = arg->vty;
+
+ if (record->asn == arg->as) {
+ (*arg->prefix_amount)++;
+ print_record(record, vty);
+ }
+}
+
static void print_record_cb(const struct pfx_record *record, void *data)
{
struct rpki_for_each_record_arg *arg = data;
@@ -621,6 +633,36 @@ static struct rtr_mgr_group *get_connected_group(void)
return rtr_mgr_get_first_group(rtr_config);
}
+static void print_prefix_table_by_asn(struct vty *vty, as_t as)
+{
+ unsigned int number_of_ipv4_prefixes = 0;
+ unsigned int number_of_ipv6_prefixes = 0;
+ struct rtr_mgr_group *group = get_connected_group();
+ struct rpki_for_each_record_arg arg;
+
+ arg.vty = vty;
+ arg.as = as;
+
+ if (!group) {
+ vty_out(vty, "Cannot find a connected group.\n");
+ return;
+ }
+
+ struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
+
+ vty_out(vty, "RPKI/RTR prefix table\n");
+ vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
+
+ arg.prefix_amount = &number_of_ipv4_prefixes;
+ pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg);
+
+ arg.prefix_amount = &number_of_ipv6_prefixes;
+ pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg);
+
+ vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
+ vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
+}
+
static void print_prefix_table(struct vty *vty)
{
struct rpki_for_each_record_arg arg;
@@ -1190,6 +1232,21 @@ DEFUN (show_rpki_prefix_table,
return CMD_SUCCESS;
}
+DEFPY(show_rpki_as_number, show_rpki_as_number_cmd,
+ "show rpki as-number (1-4294967295)$by_asn",
+ SHOW_STR RPKI_OUTPUT_STRING
+ "Lookup by ASN in prefix table\n"
+ "AS Number\n")
+{
+ if (!is_synchronized()) {
+ vty_out(vty, "No Connection to RPKI cache server.\n");
+ return CMD_WARNING;
+ }
+
+ print_prefix_table_by_asn(vty, by_asn);
+ return CMD_SUCCESS;
+}
+
DEFPY (show_rpki_prefix,
show_rpki_prefix_cmd,
"show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
@@ -1523,6 +1580,7 @@ static void install_cli_commands(void)
install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
install_element(VIEW_NODE, &show_rpki_prefix_cmd);
+ install_element(VIEW_NODE, &show_rpki_as_number_cmd);
/* Install debug commands */
install_element(CONFIG_NODE, &debug_rpki_cmd);
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index d50716105..5cf0b7398 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -858,7 +858,7 @@ static int bgpTrapEstablished(struct peer *peer)
oid index[sizeof(oid) * IN_ADDR_SIZE];
/* Check if this peer just went to Established */
- if ((peer->last_major_event != OpenConfirm) || !(peer_established(peer)))
+ if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
return 0;
ret = inet_aton(peer->host, &addr);
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 04181d38b..3d74128da 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -187,7 +187,8 @@ bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit,
return NULL;
}
-void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
+void bgp_table_range_lookup(const struct bgp_table *table,
+ const struct prefix *p,
uint8_t maxlen, struct list *matches)
{
struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 69cca9eee..7b468cc03 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -217,7 +217,7 @@ static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node,
* bgp_node_get
*/
static inline struct bgp_node *bgp_node_get(struct bgp_table *const table,
- struct prefix *p)
+ const struct prefix *p)
{
return bgp_node_from_rnode(route_node_get(table->route_table, p));
}
@@ -226,7 +226,7 @@ static inline struct bgp_node *bgp_node_get(struct bgp_table *const table,
* bgp_node_lookup
*/
static inline struct bgp_node *
-bgp_node_lookup(const struct bgp_table *const table, struct prefix *p)
+bgp_node_lookup(const struct bgp_table *const table, const struct prefix *p)
{
return bgp_node_from_rnode(route_node_lookup(table->route_table, p));
}
@@ -243,7 +243,7 @@ static inline struct bgp_node *bgp_lock_node(struct bgp_node *node)
* bgp_node_match
*/
static inline struct bgp_node *bgp_node_match(const struct bgp_table *table,
- struct prefix *p)
+ const struct prefix *p)
{
return bgp_node_from_rnode(route_node_match(table->route_table, p));
}
@@ -277,7 +277,7 @@ static inline unsigned long bgp_table_count(const struct bgp_table *const table)
* bgp_table_get_next
*/
static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table,
- struct prefix *p)
+ const struct prefix *p)
{
return bgp_node_from_rnode(route_table_get_next(table->route_table, p));
}
@@ -347,7 +347,8 @@ static inline uint64_t bgp_table_version(struct bgp_table *table)
return table->version;
}
-void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
+void bgp_table_range_lookup(const struct bgp_table *table,
+ const struct prefix *p,
uint8_t maxlen, struct list *matches);
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 50824cd6d..a29721988 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -831,17 +831,17 @@ void update_subgroup_inherit_info(struct update_subgroup *to,
*
* Returns true if the subgroup was deleted.
*/
-static int update_subgroup_check_delete(struct update_subgroup *subgrp)
+static bool update_subgroup_check_delete(struct update_subgroup *subgrp)
{
if (!subgrp)
- return 0;
+ return false;
if (!LIST_EMPTY(&(subgrp->peers)))
- return 0;
+ return false;
update_subgroup_delete(subgrp);
- return 1;
+ return true;
}
/*
@@ -982,7 +982,7 @@ static struct update_subgroup *update_subgroup_find(struct update_group *updgrp,
* Returns true if this subgroup is in a state that allows it to be
* merged into another subgroup.
*/
-static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp)
+static bool update_subgroup_ready_for_merge(struct update_subgroup *subgrp)
{
/*
@@ -990,13 +990,13 @@ static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp)
* out to peers.
*/
if (!bpacket_queue_is_empty(SUBGRP_PKTQ(subgrp)))
- return 0;
+ return false;
/*
* Not ready if there enqueued updates waiting to be encoded.
*/
if (!advertise_list_is_empty(subgrp))
- return 0;
+ return false;
/*
* Don't attempt to merge a subgroup that needs a refresh. For one,
@@ -1004,9 +1004,9 @@ static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp)
* another group.
*/
if (update_subgroup_needs_refresh(subgrp))
- return 0;
+ return false;
- return 1;
+ return true;
}
/*
@@ -1095,13 +1095,13 @@ static void update_subgroup_merge(struct update_subgroup *subgrp,
* Returns true if the subgroup has been merged. The subgroup pointer
* should not be accessed in this case.
*/
-int update_subgroup_check_merge(struct update_subgroup *subgrp,
- const char *reason)
+bool update_subgroup_check_merge(struct update_subgroup *subgrp,
+ const char *reason)
{
struct update_subgroup *target;
if (!update_subgroup_ready_for_merge(subgrp))
- return 0;
+ return false;
/*
* Look for a subgroup to merge into.
@@ -1112,10 +1112,10 @@ int update_subgroup_check_merge(struct update_subgroup *subgrp,
}
if (!target)
- return 0;
+ return false;
update_subgroup_merge(subgrp, target, reason);
- return 1;
+ return true;
}
/*
@@ -1143,14 +1143,14 @@ static int update_subgroup_merge_check_thread_cb(struct thread *thread)
*
* Returns true if a merge check will be performed shortly.
*/
-int update_subgroup_trigger_merge_check(struct update_subgroup *subgrp,
- int force)
+bool update_subgroup_trigger_merge_check(struct update_subgroup *subgrp,
+ int force)
{
if (subgrp->t_merge_check)
- return 1;
+ return true;
if (!force && !update_subgroup_ready_for_merge(subgrp))
- return 0;
+ return false;
subgrp->t_merge_check = NULL;
thread_add_timer_msec(bm->master, update_subgroup_merge_check_thread_cb,
@@ -1158,7 +1158,7 @@ int update_subgroup_trigger_merge_check(struct update_subgroup *subgrp,
SUBGRP_INCR_STAT(subgrp, merge_checks_triggered);
- return 1;
+ return true;
}
/*
@@ -1212,8 +1212,8 @@ static int update_subgroup_copy_packets(struct update_subgroup *dest,
return count;
}
-static int updgrp_prefix_list_update(struct update_group *updgrp,
- const char *name)
+static bool updgrp_prefix_list_update(struct update_group *updgrp,
+ const char *name)
{
struct peer *peer;
struct bgp_filter *filter;
@@ -1225,13 +1225,13 @@ static int updgrp_prefix_list_update(struct update_group *updgrp,
&& (strcmp(name, PREFIX_LIST_OUT_NAME(filter)) == 0)) {
PREFIX_LIST_OUT(filter) = prefix_list_lookup(
UPDGRP_AFI(updgrp), PREFIX_LIST_OUT_NAME(filter));
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-static int updgrp_filter_list_update(struct update_group *updgrp,
- const char *name)
+static bool updgrp_filter_list_update(struct update_group *updgrp,
+ const char *name)
{
struct peer *peer;
struct bgp_filter *filter;
@@ -1243,13 +1243,13 @@ static int updgrp_filter_list_update(struct update_group *updgrp,
&& (strcmp(name, FILTER_LIST_OUT_NAME(filter)) == 0)) {
FILTER_LIST_OUT(filter) =
as_list_lookup(FILTER_LIST_OUT_NAME(filter));
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-static int updgrp_distribute_list_update(struct update_group *updgrp,
- const char *name)
+static bool updgrp_distribute_list_update(struct update_group *updgrp,
+ const char *name)
{
struct peer *peer;
struct bgp_filter *filter;
@@ -1261,9 +1261,9 @@ static int updgrp_distribute_list_update(struct update_group *updgrp,
&& (strcmp(name, DISTRIBUTE_OUT_NAME(filter)) == 0)) {
DISTRIBUTE_OUT(filter) = access_list_lookup(
UPDGRP_AFI(updgrp), DISTRIBUTE_OUT_NAME(filter));
- return 1;
+ return true;
}
- return 0;
+ return false;
}
static int updgrp_route_map_update(struct update_group *updgrp,
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index fe654bb3e..403ca139f 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -373,9 +373,9 @@ extern void update_subgroup_remove_peer(struct update_subgroup *,
struct peer_af *);
extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
-extern int update_subgroup_check_merge(struct update_subgroup *, const char *);
-extern int update_subgroup_trigger_merge_check(struct update_subgroup *,
- int force);
+extern bool update_subgroup_check_merge(struct update_subgroup *, const char *);
+extern bool update_subgroup_trigger_merge_check(struct update_subgroup *,
+ int force);
extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
const char *pname, int route_update,
int start_event);
@@ -404,13 +404,13 @@ extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
struct bpacket *bpacket_queue_last(struct bpacket_queue *q);
unsigned int bpacket_queue_length(struct bpacket_queue *q);
unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q);
-int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
+bool bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
extern void bpacket_queue_advance_peer(struct peer_af *paf);
extern void bpacket_queue_remove_peer(struct peer_af *paf);
extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf);
unsigned int bpacket_queue_virtual_length(struct peer_af *paf);
extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty);
-int subgroup_packets_to_build(struct update_subgroup *subgrp);
+bool subgroup_packets_to_build(struct update_subgroup *subgrp);
extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s);
extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 4dc9dfa39..6553211b0 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -226,11 +226,11 @@ unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q)
return q->hwm_count - 1;
}
-int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q)
+bool bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q)
{
if (q->curr_count >= bgp->default_subgroup_pkt_queue_max)
- return 1;
- return 0;
+ return true;
+ return false;
}
void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf)
@@ -656,22 +656,22 @@ static void bpacket_attr_vec_arr_update(struct bpacket_attr_vec_arr *vecarr,
/*
* Return if there are packets to build for this subgroup.
*/
-int subgroup_packets_to_build(struct update_subgroup *subgrp)
+bool subgroup_packets_to_build(struct update_subgroup *subgrp)
{
struct bgp_advertise *adv;
if (!subgrp)
- return 0;
+ return false;
adv = bgp_adv_fifo_first(&subgrp->sync->withdraw);
if (adv)
- return 1;
+ return true;
adv = bgp_adv_fifo_first(&subgrp->sync->update);
if (adv)
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Make BGP update packet. */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index fc89881ca..3db9866a9 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -533,7 +533,7 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
return *idx;
}
-static int peer_address_self_check(struct bgp *bgp, union sockunion *su)
+static bool peer_address_self_check(struct bgp *bgp, union sockunion *su)
{
struct interface *ifp = NULL;
@@ -545,9 +545,9 @@ static int peer_address_self_check(struct bgp *bgp, union sockunion *su)
bgp->vrf_id);
if (ifp)
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Utility function for looking up peer from VTY. */
@@ -11627,7 +11627,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
json_object_object_add(
json_neigh, "gracefulRestartInfo", json_grace);
} else {
- vty_out(vty, " Graceful restart informations:\n");
+ vty_out(vty, " Graceful restart information:\n");
if ((p->status == Established)
&& CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
@@ -14086,7 +14086,8 @@ 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)
+static bool peergroup_af_addpath_check(struct peer *peer, afi_t afi,
+ safi_t safi)
{
enum bgp_addpath_strat type, g_type;
@@ -14097,15 +14098,15 @@ static int peergroup_af_addpath_check(struct peer *peer, afi_t afi, safi_t safi)
g_type = peer->group->conf->addpath_type[afi][safi];
if (type != g_type)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* This is part of the address-family block (unicast only) */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index f3ab60849..3daef2006 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -66,19 +66,19 @@
struct zclient *zclient = NULL;
/* Can we install into zebra? */
-static inline int bgp_install_info_to_zebra(struct bgp *bgp)
+static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
{
if (zclient->sock <= 0)
- return 0;
+ return false;
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
zlog_debug(
"%s: No zebra instance to talk to, not installing information",
__func__);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
int zclient_num_connects;
@@ -928,8 +928,8 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
return nexthop;
}
-static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
- struct bgp_path_info *path)
+static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p,
+ struct bgp_path_info *path)
{
route_map_result_t ret;
@@ -937,7 +937,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
bgp_attr_flush(path->attr);
if (ret != RMAP_DENYMATCH)
- return 1;
+ return true;
if (bgp_debug_zebra(p)) {
if (p->family == AF_INET) {
@@ -965,7 +965,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
buf[1], sizeof(buf[1])));
}
}
- return 0;
+ return false;
}
static struct thread *bgp_tm_thread_connect;
@@ -1058,12 +1058,10 @@ int bgp_zebra_get_table_range(uint32_t chunk_size,
return 0;
}
-static int update_ipv4nh_for_route_install(int nh_othervrf,
- struct bgp *nh_bgp,
- struct in_addr *nexthop,
- struct attr *attr,
- bool is_evpn,
- struct zapi_nexthop *api_nh)
+static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
+ struct in_addr *nexthop,
+ struct attr *attr, bool is_evpn,
+ struct zapi_nexthop *api_nh)
{
api_nh->gate.ipv4 = *nexthop;
api_nh->vrf_id = nh_bgp->vrf_id;
@@ -1083,15 +1081,16 @@ static int update_ipv4nh_for_route_install(int nh_othervrf,
} else
api_nh->type = NEXTHOP_TYPE_IPV4;
- return 1;
+ return true;
}
-static int
-update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
- struct in6_addr *nexthop,
- ifindex_t ifindex, struct bgp_path_info *pi,
- struct bgp_path_info *best_pi, bool is_evpn,
- struct zapi_nexthop *api_nh)
+static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
+ struct in6_addr *nexthop,
+ ifindex_t ifindex,
+ struct bgp_path_info *pi,
+ struct bgp_path_info *best_pi,
+ bool is_evpn,
+ struct zapi_nexthop *api_nh)
{
struct attr *attr;
@@ -1108,7 +1107,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
api_nh->ifindex = attr->nh_ifindex;
} else if (IN6_IS_ADDR_LINKLOCAL(nexthop)) {
if (ifindex == 0)
- return 0;
+ return false;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
api_nh->ifindex = ifindex;
} else {
@@ -1136,7 +1135,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
}
if (ifindex == 0)
- return 0;
+ return false;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
api_nh->ifindex = ifindex;
} else {
@@ -1146,10 +1145,10 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
}
api_nh->gate.ipv6 = *nexthop;
- return 1;
+ return true;
}
-void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
+void bgp_zebra_announce(struct bgp_node *rn, const struct prefix *p,
struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
safi_t safi)
{
@@ -1660,11 +1659,11 @@ int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type,
}
/* Redistribute with route-map specification. */
-int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
- struct route_map *route_map)
+bool bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
+ struct route_map *route_map)
{
if (red->rmap.name && (strcmp(red->rmap.name, name) == 0))
- return 0;
+ return false;
XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
/* Decrement the count for existing routemap and
@@ -1675,18 +1674,18 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
red->rmap.map = route_map;
route_map_counter_increment(red->rmap.map);
- return 1;
+ return true;
}
/* Redistribute with metric specification. */
-int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
- afi_t afi, int type, uint32_t metric)
+bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
+ afi_t afi, int type, uint32_t metric)
{
struct bgp_node *rn;
struct bgp_path_info *pi;
if (red->redist_metric_flag && red->redist_metric == metric)
- return 0;
+ return false;
red->redist_metric_flag = 1;
red->redist_metric = metric;
@@ -1713,7 +1712,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
}
}
- return 1;
+ return true;
}
/* Unset redistribution. */
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 5a02e2fbf..b5b451092 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -32,7 +32,7 @@ extern void bgp_zebra_destroy(void);
extern int bgp_zebra_get_table_range(uint32_t chunk_size,
uint32_t *start, uint32_t *end);
extern int bgp_if_update_all(void);
-extern void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
+extern void bgp_zebra_announce(struct bgp_node *rn, const struct prefix *p,
struct bgp_path_info *path, struct bgp *bgp,
afi_t afi, safi_t safi);
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
@@ -53,10 +53,10 @@ extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short,
bool changed);
extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short);
-extern int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
- struct route_map *route_map);
-extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
- int, uint32_t);
+extern bool bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
+ struct route_map *route_map);
+extern bool bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *,
+ afi_t, int, uint32_t);
extern int bgp_redistribute_unset(struct bgp *, afi_t, int, unsigned short);
extern int bgp_redistribute_unreg(struct bgp *, afi_t, int, unsigned short);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 267d67e46..945277010 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -320,13 +320,12 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
}
}
-int bgp_router_id_static_set(struct bgp *bgp, struct in_addr id)
+void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id)
{
bgp->router_id_static = id;
bgp_router_id_set(bgp,
id.s_addr != INADDR_ANY ? &id : &bgp->router_id_zebra,
true /* is config */);
- return 0;
}
/* BGP's cluster-id control. */
@@ -393,25 +392,21 @@ time_t bgp_clock(void)
}
/* BGP timer configuration. */
-int bgp_timers_set(struct bgp *bgp, uint32_t keepalive, uint32_t holdtime,
- uint32_t connect_retry)
+void bgp_timers_set(struct bgp *bgp, uint32_t keepalive, uint32_t holdtime,
+ uint32_t connect_retry)
{
bgp->default_keepalive =
(keepalive < holdtime / 3 ? keepalive : holdtime / 3);
bgp->default_holdtime = holdtime;
bgp->default_connect_retry = connect_retry;
-
- return 0;
}
/* mostly for completeness - CLI uses its own defaults */
-int bgp_timers_unset(struct bgp *bgp)
+void bgp_timers_unset(struct bgp *bgp)
{
bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
bgp->default_connect_retry = BGP_DEFAULT_CONNECT_RETRY;
-
- return 0;
}
/* BGP confederation configuration. */
@@ -499,18 +494,18 @@ int bgp_confederation_id_unset(struct bgp *bgp)
}
/* Is an AS part of the confed or not? */
-int bgp_confederation_peers_check(struct bgp *bgp, as_t as)
+bool bgp_confederation_peers_check(struct bgp *bgp, as_t as)
{
int i;
if (!bgp)
- return 0;
+ return false;
for (i = 0; i < bgp->confed_peers_cnt; i++)
if (bgp->confed_peers[i] == as)
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Add an AS to the confederation set. */
@@ -1415,8 +1410,8 @@ static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer,
return 0;
}
-static int bgp_peer_conf_if_to_su_update_v6(struct peer *peer,
- struct interface *ifp)
+static bool bgp_peer_conf_if_to_su_update_v6(struct peer *peer,
+ struct interface *ifp)
{
struct nbr_connected *ifc_nbr;
@@ -1430,10 +1425,10 @@ static int bgp_peer_conf_if_to_su_update_v6(struct peer *peer,
peer->su.sin6.sin6_len = sizeof(struct sockaddr_in6);
#endif
peer->su.sin6.sin6_scope_id = ifp->ifindex;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/*
@@ -2084,18 +2079,18 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
return ret;
}
-static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
- safi_t safi)
+static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
+ safi_t safi)
{
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
__func__, peer->host);
- return 1;
+ return true;
}
/* Nothing to do if we've already deactivated this peer */
if (!peer->afc[afi][safi])
- return 0;
+ return false;
/* De-activate the address family configuration. */
peer->afc[afi][safi] = 0;
@@ -2104,7 +2099,7 @@ static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
flog_err(EC_BGP_PEER_DELETE,
"couldn't delete af structure for peer %s(%s, %s)",
peer->host, afi2str(afi), safi2str(safi));
- return 1;
+ return true;
}
if (peer->status == Established) {
@@ -2130,7 +2125,7 @@ static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
}
}
- return 0;
+ return false;
}
int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
@@ -2547,15 +2542,14 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
return 0;
}
-int peer_notify_unconfig(struct peer *peer)
+void peer_notify_unconfig(struct peer *peer)
{
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
- return 0;
}
-int peer_group_notify_unconfig(struct peer_group *group)
+void peer_group_notify_unconfig(struct peer_group *group)
{
struct peer *peer, *other;
struct listnode *node, *nnode;
@@ -2568,7 +2562,6 @@ int peer_group_notify_unconfig(struct peer_group *group)
} else
peer_notify_unconfig(peer);
}
- return 0;
}
int peer_group_delete(struct peer_group *group)
@@ -3771,10 +3764,10 @@ static void peer_drop_dynamic_neighbor(struct peer *peer)
}
/* If peer is configured at least one address family return 1. */
-int peer_active(struct peer *peer)
+bool peer_active(struct peer *peer)
{
if (BGP_PEER_SU_UNSPEC(peer))
- return 0;
+ return false;
if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
@@ -3786,12 +3779,12 @@ int peer_active(struct peer *peer)
|| peer->afc[AFI_IP6][SAFI_ENCAP]
|| peer->afc[AFI_IP6][SAFI_FLOWSPEC]
|| peer->afc[AFI_L2VPN][SAFI_EVPN])
- return 1;
- return 0;
+ return true;
+ return false;
}
/* If peer is negotiated at least one address family return 1. */
-int peer_active_nego(struct peer *peer)
+bool peer_active_nego(struct peer *peer)
{
if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
|| peer->afc_nego[AFI_IP][SAFI_MULTICAST]
@@ -3806,8 +3799,8 @@ int peer_active_nego(struct peer *peer)
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]
|| peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC]
|| peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
- return 1;
- return 0;
+ return true;
+ return false;
}
void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
@@ -4308,18 +4301,16 @@ int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
}
-int peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
+void peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
{
XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
peer->tx_shutdown_message =
msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL;
- return 0;
}
-int peer_tx_shutdown_message_unset(struct peer *peer)
+void peer_tx_shutdown_message_unset(struct peer *peer)
{
XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
- return 0;
}
@@ -4426,20 +4417,16 @@ int peer_ebgp_multihop_unset(struct peer *peer)
}
/* Neighbor description. */
-int peer_description_set(struct peer *peer, const char *desc)
+void peer_description_set(struct peer *peer, const char *desc)
{
XFREE(MTYPE_PEER_DESC, peer->desc);
peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
-
- return 0;
}
-int peer_description_unset(struct peer *peer)
+void peer_description_unset(struct peer *peer)
{
XFREE(MTYPE_PEER_DESC, peer->desc);
-
- return 0;
}
/* Neighbor update-source. */
@@ -4789,16 +4776,14 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
return 0;
}
-int peer_port_set(struct peer *peer, uint16_t port)
+void peer_port_set(struct peer *peer, uint16_t port)
{
peer->port = port;
- return 0;
}
-int peer_port_unset(struct peer *peer)
+void peer_port_unset(struct peer *peer)
{
peer->port = BGP_PORT_DEFAULT;
- return 0;
}
/*
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 1ada056a9..2b67a39ef 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -838,6 +838,37 @@ struct bgp_peer_gr {
bgp_peer_gr_action_ptr action_fun;
};
+/* BGP finite state machine events. */
+enum bgp_fsm_events {
+ BGP_Start = 1,
+ BGP_Stop,
+ TCP_connection_open,
+ TCP_connection_closed,
+ TCP_connection_open_failed,
+ TCP_fatal_error,
+ ConnectRetry_timer_expired,
+ Hold_Timer_expired,
+ KeepAlive_timer_expired,
+ Receive_OPEN_message,
+ Receive_KEEPALIVE_message,
+ Receive_UPDATE_message,
+ Receive_NOTIFICATION_message,
+ Clearing_Completed,
+ BGP_EVENTS_MAX,
+};
+
+/* BGP finite state machine status. */
+enum bgp_fsm_status {
+ Idle = 1,
+ Connect,
+ Active,
+ OpenSent,
+ OpenConfirm,
+ Established,
+ Clearing,
+ Deleted,
+ BGP_STATUS_MAX,
+};
/* BGP neighbor structure. */
struct peer {
@@ -896,15 +927,15 @@ struct peer {
struct peer *doppelganger;
/* Status of the peer. */
- int status;
- int ostatus;
+ enum bgp_fsm_status status;
+ enum bgp_fsm_status ostatus;
/* FSM events, stored for debug purposes.
* Note: uchar used for reduced memory usage.
*/
- unsigned char cur_event;
- unsigned char last_event;
- unsigned char last_major_event;
+ enum bgp_fsm_events cur_event;
+ enum bgp_fsm_events last_event;
+ enum bgp_fsm_events last_major_event;
/* Peer index, used for dumping TABLE_DUMP_V2 format */
uint16_t table_dump_index;
@@ -1499,6 +1530,12 @@ struct bgp_nlri {
#define BGP_NOTIFY_CEASE 6
#define BGP_NOTIFY_CAPABILITY_ERR 7
+/* Subcodes for BGP Finite State Machine Error */
+#define BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC 0
+#define BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT 1
+#define BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM 2
+#define BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED 3
+
#define BGP_NOTIFY_SUBCODE_UNSPECIFIC 0
/* BGP_NOTIFY_HEADER_ERR sub codes. */
@@ -1544,34 +1581,6 @@ struct bgp_nlri {
#define BGP_NOTIFY_CAPABILITY_INVALID_LENGTH 2
#define BGP_NOTIFY_CAPABILITY_MALFORMED_CODE 3
-/* BGP finite state machine status. */
-#define Idle 1
-#define Connect 2
-#define Active 3
-#define OpenSent 4
-#define OpenConfirm 5
-#define Established 6
-#define Clearing 7
-#define Deleted 8
-#define BGP_STATUS_MAX 9
-
-/* BGP finite state machine events. */
-#define BGP_Start 1
-#define BGP_Stop 2
-#define TCP_connection_open 3
-#define TCP_connection_closed 4
-#define TCP_connection_open_failed 5
-#define TCP_fatal_error 6
-#define ConnectRetry_timer_expired 7
-#define Hold_Timer_expired 8
-#define KeepAlive_timer_expired 9
-#define Receive_OPEN_message 10
-#define Receive_KEEPALIVE_message 11
-#define Receive_UPDATE_message 12
-#define Receive_NOTIFICATION_message 13
-#define Clearing_Completed 14
-#define BGP_EVENTS_MAX 15
-
/* BGP timers default value. */
#define BGP_INIT_START_TIMER 1
/* The following 3 are RFC defaults that are overridden in bgp_vty.c with
@@ -1733,8 +1742,8 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *);
extern bgp_peer_sort_t peer_sort(struct peer *peer);
extern bgp_peer_sort_t peer_sort_lookup(struct peer *peer);
-extern int peer_active(struct peer *);
-extern int peer_active_nego(struct peer *);
+extern bool peer_active(struct peer *);
+extern bool peer_active_nego(struct peer *);
extern void bgp_recalculate_all_bestpaths(struct bgp *bgp);
extern struct peer *peer_create(union sockunion *, const char *, struct bgp *,
as_t, as_t, int, afi_t, safi_t,
@@ -1768,21 +1777,21 @@ extern int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf,
vrf_id_t old_vrf_id, bool create);
extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *);
-extern int bgp_router_id_static_set(struct bgp *, struct in_addr);
+extern void bgp_router_id_static_set(struct bgp *, struct in_addr);
extern int bgp_cluster_id_set(struct bgp *, struct in_addr *);
extern int bgp_cluster_id_unset(struct bgp *);
extern int bgp_confederation_id_set(struct bgp *, as_t);
extern int bgp_confederation_id_unset(struct bgp *);
-extern int bgp_confederation_peers_check(struct bgp *, as_t);
+extern bool bgp_confederation_peers_check(struct bgp *, as_t);
extern int bgp_confederation_peers_add(struct bgp *, as_t);
extern int bgp_confederation_peers_remove(struct bgp *, as_t);
-extern int bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime,
- uint32_t connect_retry);
-extern int bgp_timers_unset(struct bgp *);
+extern void bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime,
+ uint32_t connect_retry);
+extern void bgp_timers_unset(struct bgp *);
extern int bgp_default_local_preference_set(struct bgp *, uint32_t);
extern int bgp_default_local_preference_unset(struct bgp *);
@@ -1793,19 +1802,19 @@ extern int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp);
extern int bgp_listen_limit_set(struct bgp *, int);
extern int bgp_listen_limit_unset(struct bgp *);
-extern int bgp_update_delay_active(struct bgp *);
-extern int bgp_update_delay_configured(struct bgp *);
+extern bool bgp_update_delay_active(struct bgp *);
+extern bool bgp_update_delay_configured(struct bgp *);
extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
extern void peer_as_change(struct peer *, as_t, int);
extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
int, afi_t, safi_t);
extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int);
extern int peer_delete(struct peer *peer);
-extern int peer_notify_unconfig(struct peer *peer);
+extern void peer_notify_unconfig(struct peer *peer);
extern int peer_group_delete(struct peer_group *);
extern int peer_group_remote_as_delete(struct peer_group *);
extern int peer_group_listen_range_add(struct peer_group *, struct prefix *);
-extern int peer_group_notify_unconfig(struct peer_group *group);
+extern void peer_group_notify_unconfig(struct peer_group *group);
extern int peer_activate(struct peer *, afi_t, safi_t);
extern int peer_deactivate(struct peer *, afi_t, safi_t);
@@ -1830,8 +1839,8 @@ extern int peer_ebgp_multihop_set(struct peer *, int);
extern int peer_ebgp_multihop_unset(struct peer *);
extern int is_ebgp_multihop_configured(struct peer *peer);
-extern int peer_description_set(struct peer *, const char *);
-extern int peer_description_unset(struct peer *);
+extern void peer_description_set(struct peer *, const char *);
+extern void peer_description_unset(struct peer *);
extern int peer_update_source_if_set(struct peer *, const char *);
extern int peer_update_source_addr_set(struct peer *, const union sockunion *);
@@ -1842,8 +1851,8 @@ extern int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
struct route_map *route_map);
extern int peer_default_originate_unset(struct peer *, afi_t, safi_t);
-extern int peer_port_set(struct peer *, uint16_t);
-extern int peer_port_unset(struct peer *);
+extern void peer_port_set(struct peer *, uint16_t);
+extern void peer_port_unset(struct peer *);
extern int peer_weight_set(struct peer *, afi_t, safi_t, uint16_t);
extern int peer_weight_unset(struct peer *, afi_t, safi_t);
@@ -1900,8 +1909,8 @@ extern int peer_clear_soft(struct peer *, afi_t, safi_t, enum bgp_clear_type);
extern int peer_ttl_security_hops_set(struct peer *, int);
extern int peer_ttl_security_hops_unset(struct peer *);
-extern int peer_tx_shutdown_message_set(struct peer *, const char *msg);
-extern int peer_tx_shutdown_message_unset(struct peer *);
+extern void peer_tx_shutdown_message_set(struct peer *, const char *msg);
+extern void peer_tx_shutdown_message_unset(struct peer *);
extern int bgp_route_map_update_timer(struct thread *thread);
extern void bgp_route_map_terminate(void);
diff --git a/bgpd/rfapi/rfapi_backend.h b/bgpd/rfapi/rfapi_backend.h
index 96e464d2a..ae1f7915f 100644
--- a/bgpd/rfapi/rfapi_backend.h
+++ b/bgpd/rfapi/rfapi_backend.h
@@ -56,7 +56,7 @@ extern void vnc_zebra_withdraw(struct prefix *p,
struct bgp_path_info *old_select);
-extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
+extern void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
struct bgp_path_info *bpi, safi_t safi);
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 2f274015f..5cb4fd5a1 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -1040,7 +1040,7 @@ int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, uint16_t *tag_id)
for (i = 0; i < ecom->size; ++i) {
as_t as = 0;
int encode = 0;
- uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
+ const uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
/* High-order octet of type. */
encode = *p++;
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 58fdc7c13..b18c9e07b 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -393,7 +393,7 @@ int rfapiStream2Vty(void *stream, /* input */
}
/* called from bgpd/bgp_vty.c'route_vty_out() */
-void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
+void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
struct bgp_path_info *bpi, safi_t safi)
{
char *s;
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index 352f5e832..3d34d696b 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -1189,7 +1189,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
}
if (rfg->label > MPLS_LABEL_MAX) {
vnc_zlog_debug_verbose(
- "%s: VRF \"%s\" is missing defaul label configuration.\n",
+ "%s: VRF \"%s\" is missing default label configuration.\n",
__func__, rfg->name);
return;
}
diff --git a/configure.ac b/configure.ac
index fa332b7da..41d1911c3 100755
--- a/configure.ac
+++ b/configure.ac
@@ -122,7 +122,7 @@ AC_ARG_ENABLE([pkgsrcrcdir],
pkgsrcrcdir="$enableval",)
dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
AC_SUBST([pkgsrcrcdir])
-AM_CONDITIONAL([PKGSRC], [test "x$pkgsrcrcdir" != "x"])
+AM_CONDITIONAL([PKGSRC], [test "$pkgsrcrcdir" != ""])
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
moduledir="$withval"
@@ -197,7 +197,7 @@ AC_DEFUN([AC_C_FLAG], [{
CFLAGS="$ac_c_flag_save"
AC_LANG_POP([C])
])
- if test "${cachename}" = yes; then
+ if test "$cachename" = "yes"; then
m4_if([$3], [], [CFLAGS="$CFLAGS $1"], [$3])
else
:
@@ -242,8 +242,8 @@ CC="${CC% -std=c99}"
AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"])
dnl if the user has specified any CFLAGS, override our settings
-if test "x${enable_gcov}" = "xyes"; then
- if test "z$orig_cflags" = "z"; then
+if test "$enable_gcov" = "yes"; then
+ if test "$orig_cflags" = ""; then
AC_C_FLAG([-coverage])
AC_C_FLAG([-O0])
fi
@@ -251,7 +251,7 @@ if test "x${enable_gcov}" = "xyes"; then
LDFLAGS="${LDFLAGS} -lgcov"
fi
-if test "x${enable_clang_coverage}" = "xyes"; then
+if test "$enable_clang_coverage" = "yes"; then
AC_C_FLAG([-fprofile-instr-generate], [
AC_MSG_ERROR([$CC does not support -fprofile-instr-generate.])
])
@@ -260,13 +260,13 @@ if test "x${enable_clang_coverage}" = "xyes"; then
])
fi
-if test "x${enable_dev_build}" = "xyes"; then
+if test "$enable_dev_build" = "yes"; then
AC_DEFINE([DEV_BUILD], [1], [Build for development])
- if test "z$orig_cflags" = "z"; then
+ if test "$orig_cflags" = ""; then
AC_C_FLAG([-g3])
AC_C_FLAG([-O0])
fi
- if test "x${enable_lua}" = "xyes"; then
+ if test "$enable_lua" = "yes"; then
AX_PROG_LUA([5.3])
AX_LUA_HEADERS
AX_LUA_LIBS([
@@ -275,15 +275,15 @@ if test "x${enable_dev_build}" = "xyes"; then
])
fi
else
- if test "x${enable_lua}" = "xyes"; then
+ if test "$enable_lua" = "yes"; then
AC_MSG_ERROR([Lua is not meant to be built/used outside of development at this time])
fi
- if test "z$orig_cflags" = "z"; then
+ if test "$orig_cflags" = ""; then
AC_C_FLAG([-g])
AC_C_FLAG([-O2])
fi
fi
-AM_CONDITIONAL([DEV_BUILD], [test "x$enable_dev_build" = "xyes"])
+AM_CONDITIONAL([DEV_BUILD], [test "$enable_dev_build" = "yes"])
dnl always want these CFLAGS
AC_C_FLAG([-fno-omit-frame-pointer])
@@ -295,7 +295,7 @@ AC_C_FLAG([-Wmissing-declarations])
AC_C_FLAG([-Wpointer-arith])
AC_C_FLAG([-Wbad-function-cast])
AC_C_FLAG([-Wwrite-strings])
-if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then
+if test "$enable_gcc_ultra_verbose" = "yes" ; then
AC_C_FLAG([-Wcast-qual])
AC_C_FLAG([-Wstrict-prototypes])
AC_C_FLAG([-Wmissing-noreturn])
@@ -318,7 +318,7 @@ dnl for some reason the string consts get 'promoted' to char *,
dnl triggering a const to non-const conversion warning.
AC_C_FLAG([-diag-disable 3179])
-if test x"${enable_werror}" = x"yes" ; then
+if test "$enable_werror" = "yes" ; then
WERROR="-Werror"
fi
AC_SUBST([WERROR])
@@ -369,7 +369,7 @@ AX_PTHREAD([
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
+if test "$frr_cv_pthread_condattr_setclock" = "yes"; then
AC_DEFINE([HAVE_PTHREAD_CONDATTR_SETCLOCK], [1], [Have pthread.h pthread_condattr_setclock])
fi
@@ -400,7 +400,7 @@ if test "$enable_shared" != "yes"; then
AC_MSG_ERROR([FRR cannot be built with --disable-shared. If you want statically linked daemons, use --enable-shared --enable-static --enable-static-bin])
fi
AC_SUBST([AC_LDFLAGS])
-AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"])
+AM_CONDITIONAL([STATIC_BIN], [test "$enable_static_bin" = "yes"])
dnl $AR and $RANLIB are set by LT_INIT above
AC_MSG_CHECKING([whether $AR supports D option])
@@ -451,7 +451,7 @@ AC_ARG_WITH([pkg-extra-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" ])
+ [ test "$withval" != "no" && with_pkg_git_version="yes" ])
AC_ARG_WITH([clippy],
AS_HELP_STRING([--with-clippy=PATH], [use external clippy helper program]))
AC_ARG_WITH([vtysh_pager],
@@ -602,23 +602,23 @@ AC_ARG_WITH([crypto],
AS_HELP_STRING([--with-crypto=<internal|openssl>], [choose between different implementations of cryptographic functions(default value is --with-crypto=internal)]))
#if openssl, else use the internal
-AS_IF([test x"${with_crypto}" = x"openssl"], [
+AS_IF([test "$with_crypto" = "openssl"], [
AC_CHECK_LIB([crypto], [EVP_DigestInit], [LIBS="$LIBS -lcrypto"], [], [])
-if test $ac_cv_lib_crypto_EVP_DigestInit = no; then
+if test "$ac_cv_lib_crypto_EVP_DigestInit" = "no"; then
AC_MSG_ERROR([build with openssl has been specified but openssl library was not found on your system])
else
AC_DEFINE([CRYPTO_OPENSSL], [1], [Compile with openssl support])
fi
-], [test x"${with_crypto}" = x"internal" || test x"${with_crypto}" = x"" ], [AC_DEFINE([CRYPTO_INTERNAL], [1], [Compile with internal cryptographic implementation])
+], [test "$with_crypto" = "internal" || test "$with_crypto" = "" ], [AC_DEFINE([CRYPTO_INTERNAL], [1], [Compile with internal cryptographic implementation])
], [AC_MSG_ERROR([Unknown value for --with-crypto])]
)
-AS_IF([test "${enable_clippy_only}" != "yes"], [
+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])
-if test "$ac_cv_lib_json_c_json_object_get" = no; then
+if test "$ac_cv_lib_json_c_json_object_get" = "no"; then
AC_CHECK_LIB([json], [json_object_get], [LIBS="$LIBS -ljson"])
- if test "$ac_cv_lib_json_json_object_get" = no; then
+ if test "$ac_cv_lib_json_json_object_get" = "no"; then
AC_MSG_ERROR([libjson is needed to compile])
fi
fi
@@ -630,8 +630,8 @@ AC_ARG_ENABLE([dev_build],
AC_ARG_ENABLE([lua],
AS_HELP_STRING([--enable-lua], [Build Lua scripting]))
-if test x"${enable_time_check}" != x"no" ; then
- if test x"${enable_time_check}" = x"yes" -o x"${enable_time_check}" = x ; then
+if test "$enable_time_check" != "no" ; then
+ if test "$enable_time_check" = "yes" -o "$enable_time_check" = "" ; then
AC_DEFINE([CONSUMED_TIME_CHECK], [5000000], [Consumed Time Check])
else
AC_DEFINE_UNQUOTED([CONSUMED_TIME_CHECK], [$enable_time_check], [Consumed Time Check])
@@ -650,7 +650,7 @@ case "${enable_systemd}" in
"no") ;;
"yes")
AC_CHECK_LIB([systemd], [sd_notify], [LIBS="$LIBS -lsystemd"])
- if test $ac_cv_lib_systemd_sd_notify = no; then
+ 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], [1], [Compile systemd support in])
@@ -659,11 +659,11 @@ case "${enable_systemd}" in
"*") ;;
esac
-if test "${enable_rr_semantics}" != "no" ; then
+if test "$enable_rr_semantics" != "no" ; then
AC_DEFINE([HAVE_V6_RR_SEMANTICS], [1], [Compile in v6 Route Replacement Semantics])
fi
-if test "${enable_datacenter}" = "yes" ; then
+if test "$enable_datacenter" = "yes" ; then
AC_DEFINE([HAVE_DATACENTER], [1], [Compile extensions for a DataCenter])
AC_MSG_WARN([The --enable-datacenter compile time option is deprecated. Please modify the init script to pass -F datacenter to the daemons instead.])
DFLT_NAME="datacenter"
@@ -671,22 +671,22 @@ else
DFLT_NAME="traditional"
fi
-if test "${enable_fuzzing}" = "yes" ; then
+if test "$enable_fuzzing" = "yes" ; then
AC_DEFINE([HANDLE_ZAPI_FUZZING], [1], [Compile extensions to use with a fuzzer])
fi
-if test "${enable_netlink_fuzzing}" = "yes" ; then
+if test "$enable_netlink_fuzzing" = "yes" ; then
AC_DEFINE([HANDLE_NETLINK_FUZZING], [1], [Compile extensions to use with a fuzzer for netlink])
fi
-if test "${enable_cumulus}" = "yes" ; then
+if test "$enable_cumulus" = "yes" ; then
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])
-if test "${enable_shell_access}" = "yes"; then
+if test "$enable_shell_access" = "yes"; then
AC_DEFINE([HAVE_SHELL_ACCESS], [1], [Allow user to use ssh/telnet/bash, be aware this is considered insecure])
fi
@@ -702,15 +702,15 @@ AS_IF([test "$host" = "$build"], [
FRR_PYTHON_MODULES([pytest])
-if test "${enable_doc}" != "no"; then
+if test "$enable_doc" != "no"; then
FRR_PYTHON_MODULES([sphinx], , [
- if test "${enable_doc}" = "yes"; then
+ if test "$enable_doc" = "yes"; then
AC_MSG_ERROR([Documentation was explicitly requested with --enable-doc but sphinx is not available for $PYTHON. Please disable docs or install sphinx.])
fi
])
fi
-AM_CONDITIONAL([DOC], [test "${enable_doc}" != "no" -a "$frr_py_mod_sphinx" != "false"])
-AM_CONDITIONAL([DOC_HTML], [test "${enable_doc_html}" = "yes"])
+AM_CONDITIONAL([DOC], [test "$enable_doc" != "no" -a "$frr_py_mod_sphinx" != "false"])
+AM_CONDITIONAL([DOC_HTML], [test "$enable_doc_html" = "yes"])
FRR_PYTHON_MOD_EXEC([sphinx], [--version], [
PYSPHINX="-m sphinx"
@@ -731,35 +731,35 @@ fi
#
AC_MSG_CHECKING([if zebra should be configurable to send Route Advertisements])
-if test "${enable_rtadv}" != "no"; then
+if test "$enable_rtadv" != "no"; then
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_RTADV], [1], [Enable IPv6 Routing Advertisement support])
else
AC_MSG_RESULT([no])
fi
-if test x"${enable_user}" = x"no"; then
+if test "$enable_user" = "no"; then
enable_user=""
else
- if test x"${enable_user}" = x"yes" || test x"${enable_user}" = x""; then
+ if test "$enable_user" = "yes" || test "$enable_user" = ""; then
enable_user="frr"
fi
AC_DEFINE_UNQUOTED([FRR_USER], ["${enable_user}"], [frr User])
fi
-if test x"${enable_group}" = x"no"; then
+if test "$enable_group" = "no"; then
enable_group=""
else
- if test x"${enable_group}" = x"yes" || test x"${enable_group}" = x""; then
+ if test "$enable_group" = "yes" || test "$enable_group" = ""; then
enable_group="frr"
fi
AC_DEFINE_UNQUOTED([FRR_GROUP], ["${enable_group}"], [frr Group])
fi
-if test x"${enable_vty_group}" = x"yes" ; then
+if test "$enable_vty_group" = "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
+elif test "$enable_vty_group" != ""; then
+ if test "$enable_vty_group" != "no"; then
AC_DEFINE_UNQUOTED([VTY_GROUP], ["${enable_vty_group}"], [VTY Sockets Group])
fi
fi
@@ -784,7 +784,7 @@ case "${enable_multipath}" in
;;
"")
;;
- *)
+ *)
AC_MSG_FAILURE([Please specify digit to enable multipath ARG])
;;
esac
@@ -796,12 +796,12 @@ 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
dnl ------------------------------------
-if test "x${enable_numeric_version}" != "x" ; then
+if test "$enable_numeric_version" != "" ; then
VERSION="`echo ${VERSION} | tr -c -d '[[.0-9]]'`"
PACKAGE_VERSION="`echo ${PACKAGE_VERSION} | tr -c -d '[[.0-9]]'`"
fi
@@ -810,7 +810,7 @@ dnl -----------------------------------
dnl Add extra version string to package
dnl name, string and version fields.
dnl -----------------------------------
-if test "x${EXTRAVERSION}" != "x" ; then
+if test "$EXTRAVERSION" != "" ; then
VERSION="${VERSION}${EXTRAVERSION}"
PACKAGE_VERSION="${PACKAGE_VERSION}${EXTRAVERSION}"
AC_SUBST(PACKAGE_EXTRAVERSION, ["${EXTRAVERSION}"])
@@ -818,17 +818,17 @@ if test "x${EXTRAVERSION}" != "x" ; then
fi
AC_SUBST([EXTRAVERSION])
-if test "x$with_pkg_git_version" = "xyes"; then
+if test "$with_pkg_git_version" = "yes"; then
if test -d "${srcdir}/.git"; then
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
fi
-AM_CONDITIONAL([GIT_VERSION], [test "x$with_pkg_git_version" = "xyes"])
+AM_CONDITIONAL([GIT_VERSION], [test "$with_pkg_git_version" = "yes"])
AC_CHECK_TOOL([OBJCOPY], [objcopy], [:])
-if test "x${OBJCOPY}" != "x:"; then
+if test "$OBJCOPY" != ":"; then
AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [
frr_cv_interp=""
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [
@@ -1122,16 +1122,6 @@ case "$host_os" in
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
- openbsd6.0)
- ;;
- openbsd[6-9]*)
- AC_MSG_FAILURE([pimd cannot be enabled as PIM support has been removed from OpenBSD 6.1])
- ;;
- esac
- fi
;;
*)
AC_MSG_RESULT([BSD])
@@ -1141,7 +1131,7 @@ case "$host_os" in
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"])
AM_CONDITIONAL([LINUX], [${is_linux}])
AC_SYS_LARGEFILE
@@ -1149,7 +1139,7 @@ AC_SYS_LARGEFILE
dnl ------------------------
dnl Integrated REALMS option
dnl ------------------------
-if test "${enable_realms}" = "yes"; then
+if test "$enable_realms" = "yes"; then
case "$host_os" in
linux*)
AC_DEFINE([SUPPORT_REALMS], [1], [Realms support])
@@ -1175,7 +1165,7 @@ AC_CHECK_FUNCS([ \
dnl ##########################################################################
dnl LARGE if block spans a lot of "configure"!
-if test "${enable_clippy_only}" != "yes"; then
+if test "$enable_clippy_only" != "yes"; then
dnl ##########################################################################
#
@@ -1243,15 +1233,15 @@ case "${enable_vtysh}" in
LIBS="$prev_libs"
AC_CHECK_HEADER([readline/history.h])
- if test $ac_cv_header_readline_history_h = no;then
+ 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])
- if test $ac_cv_lib_readline_rl_completion_matches = no; then
+ if test "$ac_cv_lib_readline_rl_completion_matches" = "no"; then
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])
- if test "$frr_cv_append_history" = yes; then
+ if test "$frr_cv_append_history" = "yes"; then
AC_DEFINE([HAVE_APPEND_HISTORY], [1], [Have history.h append_history])
fi
;;
@@ -1366,10 +1356,10 @@ case "$host_os" in
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
+ if test "$ac_cv_header_net_bpf_h" = "no"; then
+ if test "$ac_cv_header_sys_dlpi_h" = "no"; then
AC_MSG_RESULT([none])
- if test "${enable_isisd}" = yes -o "${enable_fabricd}" = yes; then
+ if test "$enable_isisd" = "yes" -o "$enable_fabricd" = "yes"; then
AC_MSG_FAILURE([IS-IS support requested but no packet backend found])
fi
AC_MSG_WARN([*** IS-IS support will not be built ***])
@@ -1473,7 +1463,7 @@ AC_CHECK_HEADER([netinet/tcp.h],
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)],
[],
FRR_INCLUDES)
-if test $ac_cv_have_decl_TCP_MD5SIG = no; then
+if test "$ac_cv_have_decl_TCP_MD5SIG" = "no"; then
AC_CHECK_HEADER([linux/tcp.h],
[m4_define([MD5_INCLUDES],
FRR_INCLUDES
@@ -1490,7 +1480,7 @@ AC_CHECK_LIB([resolv], [res_init])
dnl ---------------------------
dnl check system has PCRE regexp
dnl ---------------------------
-if test "x$enable_pcreposix" = "xyes"; then
+if test "$enable_pcreposix" = "yes"; then
AC_CHECK_LIB([pcreposix], [regexec], [], [
AC_MSG_ERROR([--enable-pcreposix given but unable to find libpcreposix])
])
@@ -1498,7 +1488,7 @@ fi
AC_SUBST([HAVE_LIBPCREPOSIX])
dnl ##########################################################################
-dnl test "${enable_clippy_only}" != "yes"
+dnl test "$enable_clippy_only" != "yes"
fi
dnl END OF LARGE if block
dnl ##########################################################################
@@ -1547,7 +1537,7 @@ dnl --------------------
dnl Daemon disable check
dnl --------------------
-AS_IF([test "${enable_ldpd}" != "no"], [
+AS_IF([test "$enable_ldpd" != "no"], [
AC_DEFINE([HAVE_LDPD], [1], [ldpd])
])
@@ -1569,7 +1559,7 @@ else
esac
fi
-if test "$ac_cv_lib_json_c_json_object_get" = no -a "x$BFDD" = "xbfdd"; then
+if test "$ac_cv_lib_json_c_json_object_get" = "no" -a "$BFDD" = "bfdd"; then
AC_MSG_ERROR(["you must use json-c library to use bfdd"])
fi
@@ -1580,7 +1570,7 @@ case "$host_os" in
no)
;;
yes)
- if test "${enable_clippy_only}" != "yes"; then
+ if test "$enable_clippy_only" != "yes"; then
if test "$c_ares_found" != "true" ; then
AC_MSG_ERROR([nhrpd requires libcares. Please install c-ares and its -dev headers.])
fi
@@ -1595,34 +1585,34 @@ case "$host_os" in
esac
;;
*)
- if test "${enable_nhrpd}" = "yes"; then
+ if test "$enable_nhrpd" = "yes"; then
AC_MSG_ERROR([nhrpd requires kernel APIs that are only present on Linux.])
fi
;;
esac
-if test "${enable_watchfrr}" = "no";then
+if test "$enable_watchfrr" = "no";then
WATCHFRR=""
else
WATCHFRR="watchfrr"
fi
OSPFCLIENT=""
-if test "${enable_ospfapi}" != "no";then
+if test "$enable_ospfapi" != "no";then
AC_DEFINE([SUPPORT_OSPF_API], [1], [OSPFAPI])
- if test "${enable_ospfclient}" != "no";then
+ if test "$enable_ospfclient" != "no";then
OSPFCLIENT="ospfclient"
fi
fi
-if test "${enable_bgp_announce}" = "no";then
+if test "$enable_bgp_announce" = "no";then
AC_DEFINE([DISABLE_BGP_ANNOUNCE], [1], [Disable BGP installation to zebra])
else
AC_DEFINE([DISABLE_BGP_ANNOUNCE], [0], [Disable BGP installation to zebra])
fi
-if test "${enable_bgp_vnc}" != "no";then
+if test "$enable_bgp_vnc" != "no";then
AC_DEFINE([ENABLE_BGP_VNC], [1], [Enable BGP VNC support])
fi
@@ -1645,15 +1635,15 @@ esac
dnl ##########################################################################
dnl LARGE if block
-if test "${enable_clippy_only}" != "yes"; then
+if test "$enable_clippy_only" != "yes"; then
dnl ##########################################################################
dnl ------------------
dnl check Net-SNMP library
dnl ------------------
-if test "${enable_snmp}" != "" -a "${enable_snmp}" != "no"; then
+if test "$enable_snmp" != "" -a "$enable_snmp" != "no"; then
AC_PATH_TOOL([NETSNMP_CONFIG], [net-snmp-config], [no])
- if test x"$NETSNMP_CONFIG" = x"no"; then
+ if test "$NETSNMP_CONFIG" = "no"; then
AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config])
fi
SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`"
@@ -1726,7 +1716,7 @@ dnl confd
dnl ---------------
if test "$enable_confd" != "" -a "$enable_confd" != "no"; then
AC_CHECK_PROG([CONFD], [confd], [confd], [/bin/false], "${enable_confd}/bin")
- if test "x$CONFD" = "x/bin/false"; then
+ if test "$CONFD" = "/bin/false"; then
AC_MSG_ERROR([confd was not found on your system.])]
fi
CONFD_CFLAGS="-I${enable_confd}/include -L${enable_confd}/lib"
@@ -1769,12 +1759,12 @@ fi
dnl ------
dnl ZeroMQ
dnl ------
-if test "x$enable_zeromq" != "xno"; then
+if test "$enable_zeromq" != "no"; then
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
+ if test "$enable_zeromq" = "yes"; then
AC_MSG_ERROR([configuration specifies --enable-zeromq but libzmq was not found])
fi
])
@@ -1783,7 +1773,7 @@ fi
dnl ------------------------------------
dnl Enable RPKI and add librtr to libs
dnl ------------------------------------
-if test "${enable_rpki}" = "yes"; then
+if test "$enable_rpki" = "yes"; then
PKG_CHECK_MODULES([RTRLIB], [rtrlib >= 0.5.0],
[RPKI=true],
[RPKI=false
@@ -1791,6 +1781,42 @@ if test "${enable_rpki}" = "yes"; then
)
fi
+dnl ------------------------------------
+dnl pimd is not supported on OpenBSD and MacOS
+dnl ------------------------------------
+if test "$enable_pimd" != "no"; then
+AC_MSG_CHECKING([for pimd OS support])
+case "$host_os" in
+ darwin*)
+ AC_MSG_RESULT([no])
+ enable_pimd="no"
+ ;;
+ openbsd*)
+ AC_MSG_RESULT([no])
+ enable_pimd="no"
+ ;;
+ *)
+ AC_MSG_RESULT([yes])
+ ;;
+esac
+fi
+
+dnl -------------------------------------
+dnl VRRP is only supported on linux
+dnl -------------------------------------
+if test "$enable_vrrpd" != "no"; then
+AC_MSG_CHECKING([for VRRP OS support])
+case "$host_os" in
+ linux*)
+ AC_MSG_RESULT([yes])
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ enable_vrrpd="no"
+ ;;
+esac
+fi
+
dnl ------------------------------------------
dnl Check whether rtrlib was build with ssh support
dnl ------------------------------------------
@@ -1827,7 +1853,7 @@ AC_CACHE_CHECK([for dlinfo(RTLD_DI_ORIGIN)], [frr_cv_rtld_di_origin], [
frr_cv_rtld_di_origin=no
])
])
-if test "$frr_cv_rtld_di_origin" = yes; then
+if test "$frr_cv_rtld_di_origin" = "yes"; then
AC_DEFINE([HAVE_DLINFO_ORIGIN], [1], [Have dlinfo RTLD_DI_ORIGIN])
fi
@@ -1847,12 +1873,12 @@ AC_CACHE_CHECK([for dlinfo(RTLD_DI_LINKMAP)], [frr_cv_rtld_di_linkmap], [
frr_cv_rtld_di_linkmap=no
])
])
-if test "$frr_cv_rtld_di_linkmap" = yes; then
+if test "$frr_cv_rtld_di_linkmap" = "yes"; then
AC_DEFINE([HAVE_DLINFO_LINKMAP], [1], [Have dlinfo RTLD_DI_LINKMAP])
fi
dnl ##########################################################################
-dnl test "${enable_clippy_only}" != "yes"
+dnl test "$enable_clippy_only" != "yes"
fi
dnl END OF LARGE if block
dnl ##########################################################################
@@ -2052,7 +2078,7 @@ fi
dnl -------------------
dnl capabilities checks
dnl -------------------
-if test "${enable_capabilities}" != "no"; then
+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])
@@ -2060,11 +2086,11 @@ if test "${enable_capabilities}" != "no"; then
frr_ac_keepcaps="yes"],
AC_MSG_RESULT([no])
)
- if test x"${frr_ac_keepcaps}" = x"yes"; then
+ if test "$frr_ac_keepcaps" = "yes"; then
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],
+ if test "$ac_cv_header_sys_capability_h" = "yes"; then
+ AC_CHECK_LIB([cap], [cap_init],
[AC_DEFINE([HAVE_LCAPS], [1], [Capabilities])
LIBCAP="-lcap"
frr_ac_lcaps="yes"]
@@ -2081,14 +2107,14 @@ if test "${enable_capabilities}" != "no"; then
]
)
fi
- if test x"${frr_ac_scaps}" = x"yes" \
- -o x"${frr_ac_lcaps}" = x"yes"; then
+ if test "$frr_ac_scaps" = "yes" \
+ -o "$frr_ac_lcaps" = "yes"; then
AC_DEFINE([HAVE_CAPABILITIES], [1], [capabilities])
fi
case "$host_os" in
linux*)
- if test "${enable_clippy_only}" != "yes"; then
+ if test "$enable_clippy_only" != "yes"; then
if test "$frr_ac_lcaps" != "yes"; then
AC_MSG_ERROR([libcap and/or its headers were not found. Running FRR without libcap support built in causes a huge performance penalty.])
fi
@@ -2106,8 +2132,8 @@ AC_SUBST([LIBCAP])
dnl ---------------------------
dnl check for glibc 'backtrace'
-dnl ---------------------------
-if test x"${enable_backtrace}" != x"no" ; then
+dnl ---------------------------
+if test "$enable_backtrace" != "no" ; then
backtrace_ok=no
PKG_CHECK_MODULES([UNWIND], [libunwind], [
AC_DEFINE([HAVE_LIBUNWIND], [1], [libunwind])
@@ -2134,7 +2160,7 @@ if test x"${enable_backtrace}" != x"no" ; then
])
;;
esac
- if test "$backtrace_ok" = 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])
@@ -2144,7 +2170,7 @@ if test x"${enable_backtrace}" != x"no" ; then
fi
fi
- if test x"${enable_backtrace}" = x"yes" -a x"${backtrace_ok}" = x"no"; then
+ if test "$enable_backtrace" = "yes" -a "$backtrace_ok" = "no"; then
dnl user explicitly requested backtrace but we failed to find support
AC_MSG_FAILURE([failed to find backtrace or libunwind support])
fi
@@ -2178,7 +2204,7 @@ struct mallinfo ac_x; ac_x = mallinfo ();
frr_cv_mallinfo=no
])
])
-if test "$frr_cv_mallinfo" = yes; then
+if test "$frr_cv_mallinfo" = "yes"; then
AC_DEFINE([HAVE_MALLINFO], [1], [mallinfo])
fi
@@ -2221,7 +2247,7 @@ dnl configure date
dnl ----------
dev_version=`echo $VERSION | grep dev`
#don't expire deprecated code in non 'dev' branch
-if test "${dev_version}" = ""; then
+if test "$dev_version" = ""; then
CONFDATE=0
else
CONFDATE=`date '+%Y%m%d'`
@@ -2232,12 +2258,12 @@ dnl ------------------------------
dnl set paths for state directory
dnl ------------------------------
AC_MSG_CHECKING([directory to use for state file])
-if test "${prefix}" = "NONE"; then
+if test "$prefix" = "NONE"; then
frr_statedir_prefix="";
else
frr_statedir_prefix=${prefix}
fi
-if test "${localstatedir}" = '${prefix}/var'; then
+if test "$localstatedir" = '${prefix}/var'; then
for FRR_STATE_DIR in ${frr_statedir_prefix}/var/run dnl
${frr_statedir_prefix}/var/adm dnl
${frr_statedir_prefix}/etc dnl
@@ -2252,7 +2278,7 @@ if test "${localstatedir}" = '${prefix}/var'; then
else
frr_statedir=${localstatedir}
fi
-if test $frr_statedir = "/dev/null"; then
+if test "$frr_statedir" = "/dev/null"; then
AC_MSG_ERROR([STATE DIRECTORY NOT FOUND! FIX OR SPECIFY --localstatedir!])
fi
AC_MSG_RESULT([${frr_statedir}])
@@ -2265,8 +2291,8 @@ AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty director
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
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+test "$prefix" = "NONE" && prefix=$ac_default_prefix
+test "$exec_prefix" = "NONE" && exec_prefix='${prefix}'
dnl get the full path, recursing through variables...
vtysh_bin="$bindir/vtysh"
@@ -2298,44 +2324,44 @@ AC_DEFINE_UNQUOTED([YANG_MODELS_PATH], ["$CFG_YANGMODELS"], [path to YANG data m
AC_DEFINE_UNQUOTED([WATCHFRR_SH_PATH], ["${CFG_SBIN%/}/watchfrr.sh"], [path to watchfrr.sh])
dnl various features
-AM_CONDITIONAL([SUPPORT_REALMS], [test "${enable_realms}" = "yes"])
-AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno])
+AM_CONDITIONAL([SUPPORT_REALMS], [test "$enable_realms" = "yes"])
+AM_CONDITIONAL([ENABLE_BGP_VNC], [test "$enable_bgp_vnc" != "no"])
AM_CONDITIONAL([BGP_BMP], [$bgpd_bmp])
dnl northbound
AM_CONDITIONAL([SQLITE3], [$SQLITE3])
-AM_CONDITIONAL([CONFD], [test "x$enable_confd" != "x"])
-AM_CONDITIONAL([SYSREPO], [test "x$enable_sysrepo" = "xyes"])
-AM_CONDITIONAL([GRPC], [test "x$enable_grpc" = "xyes"])
-AM_CONDITIONAL([ZEROMQ], [test "x$ZEROMQ" = "xtrue"])
+AM_CONDITIONAL([CONFD], [test "$enable_confd" != ""])
+AM_CONDITIONAL([SYSREPO], [test "$enable_sysrepo" = "yes"])
+AM_CONDITIONAL([GRPC], [test "$enable_grpc" = "yes"])
+AM_CONDITIONAL([ZEROMQ], [test "$ZEROMQ" = "true"])
dnl plugins
-AM_CONDITIONAL([RPKI], [test "x$RPKI" = "xtrue"])
-AM_CONDITIONAL([SNMP], [test "x$SNMP_METHOD" = "xagentx"])
+AM_CONDITIONAL([RPKI], [test "$RPKI" = "true"])
+AM_CONDITIONAL([SNMP], [test "$SNMP_METHOD" = "agentx"])
AM_CONDITIONAL([IRDP], [$IRDP])
-AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"])
-AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$enable_protobuf" = "xyes"])
+AM_CONDITIONAL([FPM], [test "$enable_fpm" = "yes"])
+AM_CONDITIONAL([HAVE_PROTOBUF], [test "$enable_protobuf" = "yes"])
AM_CONDITIONAL([HAVE_PROTOBUF3], [$PROTO3])
dnl daemons
-AM_CONDITIONAL([VTYSH], [test "x$VTYSH" = "xvtysh"])
-AM_CONDITIONAL([ZEBRA], [test "${enable_zebra}" != "no"])
-AM_CONDITIONAL([BGPD], [test "x${enable_bgpd}" != "no"])
-AM_CONDITIONAL([RIPD], [test "${enable_ripd}" != "no"])
-AM_CONDITIONAL([OSPFD], [test "${enable_ospfd}" != "no"])
-AM_CONDITIONAL([LDPD], [test "${enable_ldpd}" != "no"])
-AM_CONDITIONAL([BFDD], [test "x$BFDD" = "xbfdd"])
-AM_CONDITIONAL([NHRPD], [test "x$NHRPD" = "xnhrpd"])
-AM_CONDITIONAL([EIGRPD], [test "${enable_eigrpd}" != "no"])
-AM_CONDITIONAL([WATCHFRR], [test "x$WATCHFRR" = "xwatchfrr"])
-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([VRRPD], [test "${enable_vrrpd}" != "no"])
+AM_CONDITIONAL([VTYSH], [test "$VTYSH" = "vtysh"])
+AM_CONDITIONAL([ZEBRA], [test "$enable_zebra" != "no"])
+AM_CONDITIONAL([BGPD], [test "$enable_bgpd" != "no"])
+AM_CONDITIONAL([RIPD], [test "$enable_ripd" != "no"])
+AM_CONDITIONAL([OSPFD], [test "$enable_ospfd" != "no"])
+AM_CONDITIONAL([LDPD], [test "$enable_ldpd" != "no"])
+AM_CONDITIONAL([BFDD], [test "$BFDD" = "bfdd"])
+AM_CONDITIONAL([NHRPD], [test "$NHRPD" = "nhrpd"])
+AM_CONDITIONAL([EIGRPD], [test "$enable_eigrpd" != "no"])
+AM_CONDITIONAL([WATCHFRR], [test "$WATCHFRR" = "watchfrr"])
+AM_CONDITIONAL([OSPFCLIENT], [test "$OSPFCLIENT" = "ospfclient"])
+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([VRRPD], [test "$enable_vrrpd" != "no"])
AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile])
@@ -2363,7 +2389,7 @@ AC_CONFIG_COMMANDS([lib/route_types.h], [
${PERL} "${ac_abs_top_srcdir}/lib/route_types.pl" \
< "${ac_abs_top_srcdir}/lib/route_types.txt" \
> "${dst}.tmp"
- test -f "${dst}" \
+ test -f "$dst" \
&& diff "${dst}.tmp" "${dst}" >/dev/null 2>/dev/null \
&& rm "${dst}.tmp" \
|| mv "${dst}.tmp" "${dst}"
@@ -2371,13 +2397,13 @@ AC_CONFIG_COMMANDS([lib/route_types.h], [
PERL="$PERL"
])
-AS_IF([test "x$with_pkg_git_version" = "xyes"], [
+AS_IF([test "$with_pkg_git_version" = "yes"], [
AC_CONFIG_COMMANDS([lib/gitversion.h], [
dst="${ac_abs_top_builddir}/lib/gitversion.h"
${PERL} "${ac_abs_top_srcdir}/lib/gitversion.pl" \
"${ac_abs_top_srcdir}" \
> "${dst}.tmp"
- test -f "${dst}" \
+ test -f "$dst" \
&& diff "${dst}.tmp" "${dst}" >/dev/null 2>/dev/null \
&& rm "${dst}.tmp" \
|| mv "${dst}.tmp" "${dst}"
@@ -2414,9 +2440,9 @@ zebra protobuf enabled : ${enable_protobuf:-no}
The above user and group must have read/write access to the state file
directory and to the config files in the config file directory."
-if test "${enable_doc}" != "no" -a "$frr_py_mod_sphinx" = false; then
+if test "$enable_doc" != "no" -a "$frr_py_mod_sphinx" = "false"; then
AC_MSG_WARN([sphinx is missing but required to build documentation])
fi
-if test "$frr_py_mod_pytest" = false; then
+if test "$frr_py_mod_pytest" = "false"; then
AC_MSG_WARN([pytest is missing, unit tests cannot be performed])
fi
diff --git a/doc/developer/building-frr-for-archlinux.rst b/doc/developer/building-frr-for-archlinux.rst
new file mode 100644
index 000000000..7ede35ad9
--- /dev/null
+++ b/doc/developer/building-frr-for-archlinux.rst
@@ -0,0 +1,129 @@
+Arch Linux
+================
+
+Installing Dependencies
+-----------------------
+
+.. code-block:: console
+
+ sudo pacman -Syu
+ sudo pacman -S \
+ git autoconf automake libtool make cmake pcre readline texinfo \
+ pkg-config pam json-c bison flex python-pytest \
+ c-ares python systemd python2-ipaddress python-sphinx \
+ systemd-libs net-snmp perl libcap
+
+.. include:: building-libyang.rst
+
+Protobuf
+^^^^^^^^
+
+.. code-block:: console
+
+ sudo pacman -S protobuf-c
+
+ZeroMQ
+^^^^^^
+
+.. code-block:: console
+
+ sudo pacman -S zeromq
+
+Building & Installing FRR
+-------------------------
+
+Add FRR user and groups
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+ sudo groupadd -r -g 92 frr
+ sudo groupadd -r -g 85 frrvty
+ sudo useradd --system -g frr --home-dir /var/run/frr/ \
+ -c "FRR suite" --shell /sbin/nologin frr
+ sudo usermod -a -G frrvty frr
+
+Compile
+^^^^^^^
+
+.. include:: include-compile.rst
+
+Install FRR configuration files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+ sudo install -m 775 -o frr -g frr -d /var/log/frr
+ sudo install -m 775 -o frr -g frrvty -d /etc/frr
+ sudo install -m 640 -o frr -g frrvty tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+ sudo install -m 640 -o frr -g frr tools/etc/frr/frr.conf /etc/frr/frr.conf
+ sudo install -m 640 -o frr -g frr tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+ sudo install -m 640 -o frr -g frr tools/etc/frr/daemons /etc/frr/daemons
+
+Tweak sysctls
+^^^^^^^^^^^^^
+
+Some sysctls need to be changed in order to enable IPv4/IPv6 forwarding and
+MPLS (if supported by your platform). If your platform does not support MPLS,
+skip the MPLS related configuration in this section.
+
+Edit :file:`/etc/sysctl.conf`[*Create the file if it doesn't exist*] and
+append the following values (ignore the other settings):
+
+::
+
+ # Enable packet forwarding for IPv4
+ net.ipv4.ip_forward=1
+
+ # Enable packet forwarding for IPv6
+ net.ipv6.conf.all.forwarding=1
+
+Reboot or use ``sysctl -p`` to apply the same config to the running system.
+
+Add MPLS kernel modules
+"""""""""""""""""""""""
+
+To
+enable, add the following lines to :file:`/etc/modules-load.d/modules.conf`:
+
+::
+
+ # Load MPLS Kernel Modules
+ mpls_router
+ mpls_iptunnel
+
+
+And load the kernel modules on the running system:
+
+.. code-block:: console
+
+ sudo modprobe mpls-router mpls-iptunnel
+
+Enable MPLS Forwarding
+""""""""""""""""""""""
+
+Edit :file:`/etc/sysctl.conf` and the following lines. Make sure to add a line
+equal to :file:`net.mpls.conf.eth0.input` for each interface used with MPLS.
+
+::
+
+ # Enable MPLS Label processing on all interfaces
+ net.mpls.conf.eth0.input=1
+ net.mpls.conf.eth1.input=1
+ net.mpls.conf.eth2.input=1
+ net.mpls.platform_labels=100000
+
+Install service files
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+ sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
+ sudo systemctl enable frr
+
+Start FRR
+^^^^^^^^^
+
+.. code-block:: shell
+
+ systemctl start frr
diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst
index 04c6b922c..b730a5ee3 100644
--- a/doc/developer/building-frr-for-centos6.rst
+++ b/doc/developer/building-frr-for-centos6.rst
@@ -116,7 +116,19 @@ Update rpm database & Install newer sphinx
sudo yum update
sudo yum install python27-sphinx
-.. include:: building-libyang.rst
+Install libyang and its dependencies:
+
+.. code-block:: shell
+
+ sudo yum install pcre-devel doxygen cmake
+ git clone https://github.com/CESNET/libyang.git
+ cd libyang
+ git checkout 090926a89d59a3c4000719505d563aaf6ac60f2
+ mkdir build ; cd build
+ cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr -D CMAKE_BUILD_TYPE:String="Release" ..
+ make build-rpm
+ sudo yum install ./rpms/RPMS/x86_64/libyang-0.16.111-0.x86_64.rpm ./rpms/RPMS/x86_64/libyang-devel-0.16.111-0.x86_64.rpm
+ cd ../..
Get FRR, compile it and install it (from Git)
---------------------------------------------
diff --git a/doc/developer/building.rst b/doc/developer/building.rst
index 859f61231..ef55954ac 100644
--- a/doc/developer/building.rst
+++ b/doc/developer/building.rst
@@ -26,3 +26,4 @@ Building FRR
building-frr-for-ubuntu1404
building-frr-for-ubuntu1604
building-frr-for-ubuntu1804
+ building-frr-for-archlinux
diff --git a/doc/user/ldpd.rst b/doc/user/ldpd.rst
index 977195d6a..2df4ba300 100644
--- a/doc/user/ldpd.rst
+++ b/doc/user/ldpd.rst
@@ -108,6 +108,11 @@ LDP Configuration
The following command located under MPLS router node configures the MPLS
router-id of the local device.
+.. index:: [no] ordered-control
+.. clicmd:: [no] ordered-control
+
+ Configure LDP Ordered Label Distribution Control.
+
.. index:: [no] address-family [ipv4 | ipv6]
.. clicmd:: [no] address-family [ipv4 | ipv6]
diff --git a/doc/user/nhrpd.rst b/doc/user/nhrpd.rst
index 95ef9cb7e..8d3bea7c9 100644
--- a/doc/user/nhrpd.rst
+++ b/doc/user/nhrpd.rst
@@ -199,6 +199,31 @@ NHRP Events
Configure the Unix path for the event socket.
+.. _show-nhrp:
+
+Show NHRP
+==========
+
+.. index:: show [ip|ipv6] nhrp cache [json]
+.. clicmd:: show [ip|ipv6] nhrp cache [json]
+
+ Dump the cache entries.
+
+.. index:: show [ip|ipv6] nhrp opennhrp [json]
+.. clicmd:: show [ip|ipv6] nhrp opennhrp [json]
+
+ Dump the cache entries with opennhrp format.
+
+.. index:: show [ip|ipv6] nhrp nhs [json]
+.. clicmd:: show [ip|ipv6] nhrp nhs [json]
+
+ Dump the hub context.
+
+.. index:: show dmvpn [json]
+.. clicmd:: show dmvpn [json]
+
+ Dump the security contexts.
+
Configuration Example
=====================
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index b72ceb8d3..c9934d1c6 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -300,10 +300,16 @@ BGP
:t:`The Generalized TTL Security Mechanism (GTSM). V. Gill, J. Heasley, D. Meyer, P. Savola, C. Pingnataro. October 2007.`
- :rfc:`5575`
:t:`Dissemination of Flow Specification Rules. P. Marques, N. Sheth, R. Raszuk, B. Greene, J. Mauch, D. McPherson. August 2009`
+- :rfc:`6608`
+ :t:`Subcodes for BGP Finite State Machine Error. J. Dong, M. Chen, Huawei Technologies, A. Suryanarayana, Cisco Systems. May 2012.`
- :rfc:`6810`
:t:`The Resource Public Key Infrastructure (RPKI) to Router Protocol. R. Bush, R. Austein. January 2013.`
- :rfc:`6811`
:t:`BGP Prefix Origin Validation. P. Mohapatra, J. Scudder, D. Ward, R. Bush, R. Austein. January 2013.`
+- :rfc:`7606`
+ :t:`Revised Error Handling for BGP UPDATE Messages. E. Chen, J. Scudder, P. Mohapatra, K. Patel. August 2015.`
+- :rfc:`7607`
+ :t:`Codification of AS 0 Processing. W. Kumari, R. Bush, H. Schiller, K. Patel. August 2015.`
- :rfc:`7611`
:t:`BGP ACCEPT_OWN Community Attribute. J. Uttaro, P. Mohapatra, D. Smith, R. Raszuk, J. Scudder. August 2015.`
- :rfc:`7999`
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 36c8b44aa..f480c6bdc 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -66,6 +66,14 @@ Certain signals have special meanings to *pimd*.
prefix of group ranges covered. This command is vrf aware, to configure for
a vrf, enter the vrf submode.
+.. index:: ip pim register-accept-list PLIST
+.. clicmd:: ip pim register-accept-list PLIST
+
+ When pim receives a register packet the source of the packet will be compared
+ to the prefix-list specified, PLIST, and if a permit is received normal
+ processing continues. If a deny is returned for the source address of the
+ register packet a register stop message is sent to the source.
+
.. index:: ip pim spt-switchover infinity-and-beyond
.. clicmd:: ip pim spt-switchover infinity-and-beyond
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 472e2c53f..f557cbe02 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -151,10 +151,15 @@ Route Map Match Command
Matches the specified `prefix-len`. This is a Zebra specific command.
-.. index:: match ip next-hop IPV4_ADDR
-.. clicmd:: match ip next-hop IPV4_ADDR
+.. index:: match ip next-hop address IPV4_ADDR
+.. clicmd:: match ip next-hop address IPV4_ADDR
- Matches the specified `ipv4_addr`.
+ This is a BGP specific match command. Matches the specified `ipv4_addr`.
+
+.. index:: match ipv6 next-hop IPV6_ADDR
+.. clicmd:: match ipv6 next-hop IPV6_ADDR
+
+ This is a BGP specific match command. Matches the specified `ipv6_addr`.
.. index:: match as-path AS_PATH
.. clicmd:: match as-path AS_PATH
diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst
index 111e9dc9e..199685cdf 100644
--- a/doc/user/sharp.rst
+++ b/doc/user/sharp.rst
@@ -86,3 +86,20 @@ keyword. At present, no sharp commands will be preserved in the config.
Allow end user to dump associated data with the nexthop tracking that
may have been turned on.
+
+.. index:: sharp lsp
+.. clicmd:: sharp lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
+
+ Install an LSP using the specified in-label, with nexthops as
+ listed in nexthop-group ``NAME``. The LSP is installed as type
+ ZEBRA_LSP_SHARP. If ``prefix`` is specified, an existing route with
+ type ``TYPE`` (and optional ``instance`` id) will be updated to use
+ the LSP.
+
+.. index:: sharp remove lsp
+.. clicmd:: sharp remove lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
+
+ Remove a SHARPD LSP that uses the specified in-label, where the
+ nexthops are specified in nexthop-group ``NAME``. If ``prefix`` is
+ specified, remove label bindings from the route of type ``TYPE``
+ also.
diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c
index e916a5088..19695e7ab 100644
--- a/isisd/isis_bpf.c
+++ b/isisd/isis_bpf.c
@@ -73,7 +73,7 @@ static const uint8_t ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05};
static const uint8_t ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04};
#endif
-static char sock_buff[8192];
+static char sock_buff[16384];
static int open_bpf_dev(struct isis_circuit *circuit)
{
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 3144b3c28..fc70a344c 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -1398,8 +1398,8 @@ void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode,
if (strmatch(l1, l2))
vty_out(vty, " isis metric %s\n", l1);
else {
- vty_out(vty, " isis metric %s level-1\n", l1);
- vty_out(vty, " isis metric %s level-2\n", l2);
+ vty_out(vty, " isis metric level-1 %s\n", l1);
+ vty_out(vty, " isis metric level-2 %s\n", l2);
}
}
diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c
index ea16f4af7..5c15d1d29 100644
--- a/isisd/isis_dlpi.c
+++ b/isisd/isis_dlpi.c
@@ -62,7 +62,7 @@ static const uint8_t ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05};
static const uint8_t ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04};
#endif
-static uint8_t sock_buff[8192];
+static uint8_t sock_buff[16384];
static unsigned short pf_filter[] = {
ENF_PUSHWORD + 0, /* Get the SSAP/DSAP values */
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 5fa33f550..96b76da92 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -562,20 +562,12 @@ void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...)
void vty_out_timestr(struct vty *vty, time_t uptime)
{
- struct tm tm;
time_t difftime = time(NULL);
+ char buf[MONOTIME_STRLEN];
+
difftime -= uptime;
- gmtime_r(&difftime, &tm);
-
- if (difftime < ONE_DAY_SECOND)
- vty_out(vty, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (difftime < ONE_WEEK_SECOND)
- vty_out(vty, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- vty_out(vty, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
- vty_out(vty, " ago");
+ frrtime_to_interval(difftime, buf, sizeof(buf));
+
+ vty_out(vty, "%s ago", buf);
}
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index cc22aa5ff..915351262 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -1652,7 +1652,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
if (length != expected_length) {
flog_err(EC_ISIS_PACKET,
- "Exepected fixed header length = %" PRIu8
+ "Expected fixed header length = %" PRIu8
" but got %" PRIu8,
expected_length, length);
return ISIS_ERROR;
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index df6280e5c..5b0b70920 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -2266,7 +2266,7 @@ static int unpack_tlv_spine_leaf(enum isis_tlv_context context,
sbuf_push(log, indent, "Unpacking Spine Leaf Extension TLV...\n");
if (tlv_len < 2) {
- sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
+ sbuf_push(log, indent, "WARNING: Unexpected TLV size\n");
stream_forward_getp(s, tlv_len);
return 0;
}
@@ -2382,7 +2382,7 @@ static int unpack_tlv_threeway_adj(enum isis_tlv_context context,
sbuf_push(log, indent, "Unpacking P2P Three-Way Adjacency TLV...\n");
if (tlv_len != 5 && tlv_len != 15) {
- sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
+ sbuf_push(log, indent, "WARNING: Unexpected TLV size\n");
stream_forward_getp(s, tlv_len);
return 0;
}
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
index 88f7337a9..09b8d2825 100644
--- a/isisd/isis_vty_fabricd.c
+++ b/isisd/isis_vty_fabricd.c
@@ -115,6 +115,7 @@ DEFUN (no_triggered_csnp,
static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp)
{
char lspid[255];
+ char buf[MONOTIME_STRLEN];
lspid_print(lsp->hdr.lsp_id, lspid, true, true);
vty_out(vty, "Flooding information for %s\n", lspid);
@@ -129,21 +130,10 @@ static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp)
lsp->flooding_interface : "(null)");
time_t uptime = time(NULL) - lsp->flooding_time;
- struct tm tm;
- gmtime_r(&uptime, &tm);
+ frrtime_to_interval(uptime, buf, sizeof(buf));
- if (uptime < ONE_DAY_SECOND)
- vty_out(vty, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out(vty, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- vty_out(vty, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7),
- tm.tm_hour);
- vty_out(vty, " ago)\n");
+ vty_out(vty, "%s ago)\n", buf);
if (lsp->flooding_circuit_scoped) {
vty_out(vty, " Received as circuit-scoped LSP, so not "
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 5f9403132..64c12e0df 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -61,6 +61,8 @@ static void lde_label_list_init(void);
static int lde_get_label_chunk(void);
static void on_get_label_chunk_response(uint32_t start, uint32_t end);
static uint32_t lde_get_next_label(void);
+static bool lde_fec_connected(const struct fec_node *);
+static bool lde_fec_outside_mpls_network(const struct fec_node *);
RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare)
@@ -658,18 +660,31 @@ lde_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen)
return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen);
}
+static bool lde_fec_connected(const struct fec_node *fn)
+{
+ struct fec_nh *fnh;
+
+ LIST_FOREACH(fnh, &fn->nexthops, entry)
+ if (fnh->flags & F_FEC_NH_CONNECTED)
+ return true;
+
+ return false;
+}
+
+static bool lde_fec_outside_mpls_network(const struct fec_node *fn)
+{
+ struct fec_nh *fnh;
+
+ LIST_FOREACH(fnh, &fn->nexthops, entry)
+ if (!(fnh->flags & F_FEC_NH_NO_LDP))
+ return false;
+
+ return true;
+}
+
uint32_t
lde_update_label(struct fec_node *fn)
{
- struct fec_nh *fnh;
- int connected = 0;
-
- LIST_FOREACH(fnh, &fn->nexthops, entry) {
- if (fnh->flags & F_FEC_NH_CONNECTED) {
- connected = 1;
- break;
- }
- }
/* should we allocate a label for this fec? */
switch (fn->fec.type) {
@@ -695,7 +710,14 @@ lde_update_label(struct fec_node *fn)
break;
}
- if (connected) {
+ /*
+ * If connected interface act as egress for fec.
+ * If LDP is not configured on an interface but there
+ * are other NHs with interfaces configured with LDP
+ * then don't act as an egress for the fec, otherwise
+ * act as an egress for the fec
+ */
+ if (lde_fec_connected(fn) || lde_fec_outside_mpls_network(fn)) {
/* choose implicit or explicit-null depending on configuration */
switch (fn->fec.type) {
case FEC_TYPE_IPV4:
@@ -735,6 +757,13 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
struct zapi_pw zpw;
struct l2vpn_pw *pw;
+ /*
+ * Ordered Control: don't program label into HW until a
+ * labelmap msg has been received from upstream router
+ */
+ if (fnh->flags & F_FEC_NH_DEFER)
+ return;
+
switch (fn->fec.type) {
case FEC_TYPE_IPV4:
memset(&kr, 0, sizeof(kr));
@@ -901,6 +930,27 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
struct lde_req *lre;
struct map map;
struct l2vpn_pw *pw;
+ struct fec_nh *fnh;
+ bool allow = false;
+
+ /*
+ * Ordered Control: do not send a labelmap msg until
+ * a labelmap message is received from downstream router
+ * and don't send labelmap back to downstream router
+ */
+ if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ LIST_FOREACH(fnh, &fn->nexthops, entry) {
+ if (fnh->flags & F_FEC_NH_DEFER)
+ continue;
+
+ if (lde_address_find(ln, fnh->af, &fnh->nexthop))
+ return;
+ allow = true;
+ break;
+ }
+ if (!allow)
+ return;
+ }
/*
* We shouldn't send a new label mapping if we have a pending
@@ -1241,6 +1291,7 @@ lde_nbr_del(struct lde_nbr *ln)
struct fec_node *fn;
struct fec_nh *fnh;
struct l2vpn_pw *pw;
+ struct lde_nbr *lnbr;
if (ln == NULL)
return;
@@ -1256,6 +1307,25 @@ lde_nbr_del(struct lde_nbr *ln)
if (!lde_address_find(ln, fnh->af,
&fnh->nexthop))
continue;
+
+ /*
+ * Ordered Control: must mark any non-connected
+ * NH to wait until we receive a labelmap msg
+ * before installing in kernel and sending to
+ * peer, must do this as NHs are not removed
+ * when lsps go down. Also send label withdraw
+ * to other neighbors for all fecs from neighbor
+ * going down
+ */
+ if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ fnh->flags |= F_FEC_NH_DEFER;
+
+ RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) {
+ if (ln->peerid == lnbr->peerid)
+ continue;
+ lde_send_labelwithdraw(lnbr, fn, NULL, NULL);
+ }
+ }
break;
case FEC_TYPE_PWID:
if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
diff --git a/ldpd/lde.h b/ldpd/lde.h
index ce466c16b..a099f8d28 100644
--- a/ldpd/lde.h
+++ b/ldpd/lde.h
@@ -114,6 +114,8 @@ struct fec_nh {
};
#define F_FEC_NH_NEW 0x01
#define F_FEC_NH_CONNECTED 0x02
+#define F_FEC_NH_DEFER 0x04 /* running ordered control */
+#define F_FEC_NH_NO_LDP 0x08 /* no ldp on this interface */
struct fec_node {
struct fec fec;
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index eb1a6d943..8f524e0aa 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -20,6 +20,7 @@
#include <zebra.h>
#include "ldpd.h"
+#include "ldpe.h"
#include "lde.h"
#include "log.h"
@@ -325,6 +326,7 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
{
struct fec_node *fn;
struct fec_nh *fnh;
+ struct iface *iface;
fn = (struct fec_node *)fec_find(&ft, fec);
if (fn == NULL)
@@ -333,9 +335,21 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
fn->data = data;
fnh = fec_nh_find(fn, af, nexthop, ifindex, route_type, route_instance);
- if (fnh == NULL)
+ if (fnh == NULL) {
fnh = fec_nh_add(fn, af, nexthop, ifindex, route_type,
route_instance);
+ /*
+ * Ordered Control: if not a connected route and not a route
+ * learned over an interface not running LDP and not a PW
+ * then mark to wait until we receive labelmap msg before
+ * installing in kernel and sending to peer
+ */
+ iface = if_lookup(ldeconf, ifindex);
+ if ((ldeconf->flags & F_LDPD_ORDERED_CONTROL) &&
+ !connected && iface != NULL && fec->type != FEC_TYPE_PWID)
+ fnh->flags |= F_FEC_NH_DEFER;
+ }
+
fnh->flags |= F_FEC_NH_NEW;
if (connected)
fnh->flags |= F_FEC_NH_CONNECTED;
@@ -374,15 +388,25 @@ lde_kernel_update(struct fec *fec)
struct fec_nh *fnh, *safe;
struct lde_nbr *ln;
struct lde_map *me;
+ struct iface *iface;
fn = (struct fec_node *)fec_find(&ft, fec);
if (fn == NULL)
return;
LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) {
- if (fnh->flags & F_FEC_NH_NEW)
+ if (fnh->flags & F_FEC_NH_NEW) {
fnh->flags &= ~F_FEC_NH_NEW;
- else {
+ /*
+ * if LDP configured on interface or a static route
+ * clear flag else treat fec as a connected route
+ */
+ iface = if_lookup(ldeconf,fnh->ifindex);
+ if (iface || fnh->route_type == ZEBRA_ROUTE_STATIC)
+ fnh->flags &=~F_FEC_NH_NO_LDP;
+ else
+ fnh->flags |= F_FEC_NH_NO_LDP;
+ } else {
lde_send_delete_klabel(fn, fnh);
fec_nh_del(fnh);
}
@@ -445,6 +469,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
struct lde_req *lre;
struct lde_map *me;
struct l2vpn_pw *pw;
+ bool send_map = false;
lde_map2fec(map, ln->id, &fec);
@@ -525,6 +550,15 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
continue;
+ /*
+ * Ordered Control: labelmap msg received from
+ * NH so clear flag and send labelmap msg to
+ * peer
+ */
+ if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ send_map = true;
+ fnh->flags &= ~F_FEC_NH_DEFER;
+ }
fnh->remote_label = map->label;
lde_send_change_klabel(fn, fnh);
break;
@@ -558,6 +592,15 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
* loop detection. LMp.28 - LMp.30 are unnecessary because we are
* merging capable.
*/
+
+ /*
+ * Ordered Control: just received a labelmap for this fec from NH so
+ * need to send labelmap to all peers
+ * LMp.20 - LMp21 Execute procedure to send Label Mapping
+ */
+ if (send_map && fn->local_label != NO_LABEL)
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelmapping(ln, fn, 1);
}
void
@@ -757,6 +800,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
struct fec_nh *fnh;
struct lde_map *me;
struct l2vpn_pw *pw;
+ struct lde_nbr *lnbr;
/* wildcard label withdraw */
if (map->type == MAP_TYPE_WILDCARD ||
@@ -803,6 +847,26 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
if (me && (map->label == NO_LABEL || map->label == me->map.label))
/* LWd.4: remove record of previously received lbl mapping */
lde_map_del(ln, me, 0);
+
+ /* Ordered Control: additional withdraw steps */
+ if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ /* LWd.8: for each neighbor other that src of withdraw msg */
+ RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) {
+ if (ln->peerid == lnbr->peerid)
+ continue;
+
+ /* LWd.9: check if previously sent a label mapping */
+ me = (struct lde_map *)fec_find(&lnbr->sent_map,
+ &fn->fec);
+ /*
+ * LWd.10: does label sent to peer "map" to withdraw
+ * label
+ */
+ if (me)
+ /* LWd.11: send label withdraw */
+ lde_send_labelwithdraw(lnbr, fn, NULL, NULL);
+ }
+ }
}
void
@@ -813,6 +877,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
struct fec_nh *fnh;
struct lde_map *me;
struct l2vpn_pw *pw;
+ struct lde_nbr *lnbr;
/* LWd.2: send label release */
lde_send_labelrelease(ln, NULL, map, map->label);
@@ -859,6 +924,26 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
* label mapping
*/
lde_map_del(ln, me, 0);
+
+ /* Ordered Control: additional withdraw steps */
+ if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ /* LWd.8: for each neighbor other that src of withdraw msg */
+ RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) {
+ if (ln->peerid == lnbr->peerid)
+ continue;
+
+ /* LWd.9: check if previously sent a label mapping */
+ me = (struct lde_map *)fec_find(&lnbr->sent_map,
+ &fn->fec);
+ /*
+ * LWd.10: does label sent to peer "map" to withdraw
+ * label
+ */
+ if (me)
+ /* LWd.11: send label withdraw */
+ lde_send_labelwithdraw(lnbr, fn, NULL, NULL);
+ }
+ }
}
}
diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h
index 5e9df4aaf..af5f1d561 100644
--- a/ldpd/ldp_vty.h
+++ b/ldpd/ldp_vty.h
@@ -52,6 +52,7 @@ int ldp_vty_label_expnull(struct vty *, const char *, const char *);
int ldp_vty_label_accept(struct vty *, const char *, const char *, const char *);
int ldp_vty_ttl_security(struct vty *, const char *);
int ldp_vty_router_id(struct vty *, const char *, struct in_addr);
+int ldp_vty_ordered_control(struct vty *, const char *);
int ldp_vty_ds_cisco_interop(struct vty *, const char *);
int ldp_vty_trans_pref_ipv4(struct vty *, const char *);
int ldp_vty_neighbor_password(struct vty *, const char *, struct in_addr, const char *);
diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c
index c24e1917c..c10c6ae35 100644
--- a/ldpd/ldp_vty_cmds.c
+++ b/ldpd/ldp_vty_cmds.c
@@ -221,6 +221,15 @@ DEFPY (ldp_router_id,
return (ldp_vty_router_id(vty, no, address));
}
+DEFPY (ldp_ordered_control,
+ ldp_ordered_control_cmd,
+ "[no] ordered-control",
+ NO_STR
+ "Configure LDP ordered label distribution control mode\n")
+{
+ return (ldp_vty_ordered_control(vty, no));
+}
+
DEFPY (ldp_discovery_targeted_hello_accept,
ldp_discovery_targeted_hello_accept_cmd,
"[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]",
@@ -807,6 +816,7 @@ ldp_vty_init (void)
install_element(LDP_NODE, &ldp_neighbor_session_holdtime_cmd);
install_element(LDP_NODE, &ldp_neighbor_ttl_security_cmd);
install_element(LDP_NODE, &ldp_router_id_cmd);
+ install_element(LDP_NODE, &ldp_ordered_control_cmd);
install_element(LDP_IPV4_NODE, &ldp_discovery_link_holdtime_cmd);
install_element(LDP_IPV4_NODE, &ldp_discovery_targeted_holdtime_cmd);
diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c
index 816fcc64b..05b896256 100644
--- a/ldpd/ldp_vty_conf.c
+++ b/ldpd/ldp_vty_conf.c
@@ -278,6 +278,9 @@ ldp_config_write(struct vty *vty)
if (ldpd_conf->flags & F_LDPD_DS_CISCO_INTEROP)
vty_out (vty, " dual-stack cisco-interop\n");
+ if (ldpd_conf->flags & F_LDPD_ORDERED_CONTROL)
+ vty_out (vty, " ordered-control\n");
+
RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) {
if (nbrp->flags & F_NBRP_KEEPALIVE)
vty_out (vty, " neighbor %s session holdtime %u\n",
@@ -997,6 +1000,19 @@ ldp_vty_router_id(struct vty *vty, const char *negate, struct in_addr address)
}
int
+ldp_vty_ordered_control(struct vty *vty, const char *negate)
+{
+ if (negate)
+ vty_conf->flags &= ~F_LDPD_ORDERED_CONTROL;
+ else
+ vty_conf->flags |= F_LDPD_ORDERED_CONTROL;
+
+ ldp_config_apply(vty, vty_conf);
+
+ return (CMD_SUCCESS);
+}
+
+int
ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate)
{
if (negate)
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index 78b1c3e54..0f9f055d0 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -1285,6 +1285,14 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
conf->rtr_id = xconf->rtr_id;
}
+ /*
+ * Configuration of ordered-control or independent-control
+ * requires resetting all neighborships.
+ */
+ if ((conf->flags & F_LDPD_ORDERED_CONTROL) !=
+ (xconf->flags & F_LDPD_ORDERED_CONTROL))
+ ldpe_reset_nbrs(AF_UNSPEC);
+
conf->lhello_holdtime = xconf->lhello_holdtime;
conf->lhello_interval = xconf->lhello_interval;
conf->thello_holdtime = xconf->thello_holdtime;
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index 006780f03..a736b4ca3 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -511,6 +511,8 @@ DECLARE_QOBJ_TYPE(ldpd_conf)
#define F_LDPD_NO_FIB_UPDATE 0x0001
#define F_LDPD_DS_CISCO_INTEROP 0x0002
#define F_LDPD_ENABLED 0x0004
+#define F_LDPD_ORDERED_CONTROL 0x0008
+
struct ldpd_af_global {
struct thread *disc_ev;
diff --git a/lib/agg_table.h b/lib/agg_table.h
index 40ffe8c75..f95fed675 100644
--- a/lib/agg_table.h
+++ b/lib/agg_table.h
@@ -86,13 +86,13 @@ static inline struct agg_node *agg_route_next(struct agg_node *node)
}
static inline struct agg_node *agg_node_get(struct agg_table *table,
- struct prefix *p)
+ const struct prefix *p)
{
return agg_node_from_rnode(route_node_get(table->route_table, p));
}
static inline struct agg_node *
-agg_node_lookup(const struct agg_table *const table, struct prefix *p)
+agg_node_lookup(const struct agg_table *const table, const struct prefix *p)
{
return agg_node_from_rnode(route_node_lookup(table->route_table, p));
}
@@ -109,7 +109,7 @@ static inline struct agg_node *agg_route_next_until(struct agg_node *node,
}
static inline struct agg_node *agg_node_match(struct agg_table *table,
- struct prefix *p)
+ const struct prefix *p)
{
return agg_node_from_rnode(route_node_match(table->route_table, p));
}
diff --git a/lib/lib_vty.c b/lib/lib_vty.c
index 787da08e2..9c927ca4a 100644
--- a/lib/lib_vty.c
+++ b/lib/lib_vty.c
@@ -93,7 +93,7 @@ static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt)
#endif
);
} else {
- if (mt->n_alloc != 0) {
+ if (mt->n_max != 0) {
char size[32];
snprintf(size, sizeof(size), "%6zu", mt->size);
#ifdef HAVE_MALLOC_USABLE_SIZE
diff --git a/lib/libfrr.h b/lib/libfrr.h
index f964c9e2a..9d91ea915 100644
--- a/lib/libfrr.h
+++ b/lib/libfrr.h
@@ -128,7 +128,8 @@ extern void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv);
extern void frr_opt_add(const char *optstr, const struct option *longopts,
const char *helpstr);
extern int frr_getopt(int argc, char *const argv[], int *longindex);
-extern void frr_help_exit(int status);
+
+extern __attribute__((__noreturn__)) void frr_help_exit(int status);
extern struct thread_master *frr_init(void);
extern const char *frr_get_progname(void);
diff --git a/lib/memory.h b/lib/memory.h
index 44ea19b55..e4e05faa4 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -179,7 +179,8 @@ extern int qmem_walk(qmem_walk_fn *func, void *arg);
extern int log_memstats(FILE *fp, const char *);
#define log_memstats_stderr(prefix) log_memstats(stderr, prefix)
-extern void memory_oom(size_t size, const char *name);
+extern __attribute__((__noreturn__)) void memory_oom(size_t size,
+ const char *name);
#ifdef __cplusplus
}
diff --git a/lib/mlag.c b/lib/mlag.c
index 733dd41ea..653fbe8fe 100644
--- a/lib/mlag.c
+++ b/lib/mlag.c
@@ -85,9 +85,12 @@ int mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg,
size_t *length)
{
#define LIB_MLAG_HDR_LENGTH 8
+ if (s == NULL || msg == NULL)
+ return -1;
+
*length = stream_get_endp(s);
- if (s == NULL || msg == NULL || *length < LIB_MLAG_HDR_LENGTH)
+ if (*length < LIB_MLAG_HDR_LENGTH)
return -1;
*length -= LIB_MLAG_HDR_LENGTH;
diff --git a/lib/monotime.h b/lib/monotime.h
index e246f177d..dda763784 100644
--- a/lib/monotime.h
+++ b/lib/monotime.h
@@ -112,6 +112,26 @@ static inline char *time_to_string(time_t ts, char *buf)
return ctime_r(&tbuf, buf);
}
+/* Convert interval to human-friendly string, used in cli output e.g. */
+static inline const char *frrtime_to_interval(time_t t, char *buf,
+ size_t buflen)
+{
+ struct tm tm;
+
+ gmtime_r(&t, &tm);
+
+ if (t < ONE_DAY_SECOND)
+ snprintf(buf, buflen, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
+ tm.tm_sec);
+ else if (t < ONE_WEEK_SECOND)
+ snprintf(buf, buflen, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
+ tm.tm_min);
+ else
+ snprintf(buf, buflen, "%02dw%dd%02dh", tm.tm_yday / 7,
+ tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
+ return buf;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/ntop.c b/lib/ntop.c
index 066e10e3e..ccbf8793d 100644
--- a/lib/ntop.c
+++ b/lib/ntop.c
@@ -165,7 +165,7 @@ inet4:
return dst;
}
-#ifndef INET_NTOP_NO_OVERRIDE
+#if !defined(INET_NTOP_NO_OVERRIDE) && !defined(__APPLE__)
/* we want to override libc inet_ntop, but make sure it shows up in backtraces
* as frr_inet_ntop (to avoid confusion while debugging)
*/
diff --git a/lib/prefix.h b/lib/prefix.h
index b01f7d1fd..51b3dacb8 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -531,7 +531,7 @@ static inline int is_host_route(struct prefix *p)
return 0;
}
-static inline int is_default_host_route(struct prefix *p)
+static inline int is_default_host_route(const struct prefix *p)
{
if (p->family == AF_INET) {
return (p->u.prefix4.s_addr == INADDR_ANY &&
diff --git a/lib/stream.h b/lib/stream.h
index 36c65afa3..425f0c5ed 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -354,9 +354,10 @@ extern void stream_fifo_free(struct stream_fifo *fifo);
* bit), for 64-bit values (you need to cast them anyway), and neither for
* encoding (because it's downcasted.)
*/
-static inline uint8_t *ptr_get_be32(uint8_t *ptr, uint32_t *out)
+static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out)
{
uint32_t tmp;
+
memcpy(&tmp, ptr, sizeof(tmp));
*out = ntohl(tmp);
return ptr + 4;
diff --git a/lib/zclient.c b/lib/zclient.c
index eac6c7081..93c5fe39a 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -690,8 +690,9 @@ static int zclient_connect(struct thread *t)
return zclient_start(zclient);
}
-int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
- bool exact_match, vrf_id_t vrf_id)
+int zclient_send_rnh(struct zclient *zclient, int command,
+ const struct prefix *p, bool exact_match,
+ vrf_id_t vrf_id)
{
struct stream *s;
diff --git a/lib/zclient.h b/lib/zclient.h
index e6f4c747e..f18511dc8 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -738,7 +738,7 @@ extern void zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_statu
extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *);
extern int zclient_send_rnh(struct zclient *zclient, int command,
- struct prefix *p, bool exact_match,
+ const struct prefix *p, bool exact_match,
vrf_id_t vrf_id);
int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
uint32_t api_flags);
diff --git a/m4/ax_python.m4 b/m4/ax_python.m4
index 69809184e..d293da525 100644
--- a/m4/ax_python.m4
+++ b/m4/ax_python.m4
@@ -3,7 +3,7 @@ dnl 2019 David Lamparter for NetDEF, Inc.
dnl SPDX-License-Identifier: GPL-2.0-or-later
dnl the _ at the beginning will be cut off (to support the empty version string)
-m4_define_default([_FRR_PY_VERS], [_3 _ _2 _3.7 _3.6 _3.5 _3.4 _3.3 _3.2 _2.7])
+m4_define_default([_FRR_PY_VERS], [_3 _ _2 _3.8 _3.7 _3.6 _3.5 _3.4 _3.3 _3.2 _2.7])
dnl check basic interpreter properties (py2/py3)
dnl doubles as simple check whether the interpreter actually works
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index 8fd8280c5..cf338a087 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -65,11 +65,12 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
struct nhrp_cache *c;
struct interface *ifp;
struct zbuf payload;
- union sockunion addr;
+ union sockunion addr, lladdr;
size_t len;
- char buf[SU_ADDRSTRLEN];
+ char buf[4][SU_ADDRSTRLEN];
int state;
+ memset(&lladdr, 0, sizeof(lladdr));
ndm = znl_pull(zb, sizeof(*ndm));
if (!ndm)
return;
@@ -82,6 +83,10 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
sockunion_set(&addr, ndm->ndm_family,
zbuf_pulln(&payload, len), len);
break;
+ case NDA_LLADDR:
+ sockunion_set(&lladdr, ndm->ndm_family,
+ zbuf_pulln(&payload, len), len);
+ break;
}
}
@@ -93,20 +98,34 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
if (!c)
return;
- if (msg->nlmsg_type == RTM_GETNEIGH) {
- debugf(NHRP_DEBUG_KERNEL, "Netlink: who-has %s dev %s",
- sockunion2str(&addr, buf, sizeof(buf)), ifp->name);
+ debugf(NHRP_DEBUG_KERNEL,
+ "Netlink: %s %s dev %s lladdr %s nud 0x%x cache used %u type %u",
+ (msg->nlmsg_type == RTM_GETNEIGH)
+ ? "who-has"
+ : (msg->nlmsg_type == RTM_NEWNEIGH) ? "new-neigh"
+ : "del-neigh",
+ sockunion2str(&addr, buf[0], sizeof(buf[0])), ifp->name,
+ sockunion2str(&lladdr, buf[1], sizeof(buf[1])), ndm->ndm_state,
+ c->used, c->cur.type);
+ if (msg->nlmsg_type == RTM_GETNEIGH) {
if (c->cur.type >= NHRP_CACHE_CACHED) {
nhrp_cache_set_used(c, 1);
- netlink_update_binding(ifp, &addr,
- &c->cur.peer->vc->remote.nbma);
+ debugf(NHRP_DEBUG_KERNEL,
+ "Netlink: update binding for %s dev %s from c %s peer.vc.nbma %s to lladdr %s",
+ sockunion2str(&addr, buf[0], sizeof(buf[0])),
+ ifp->name,
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[1],
+ sizeof(buf[1])),
+ sockunion2str(&c->cur.peer->vc->remote.nbma,
+ buf[2], sizeof(buf[2])),
+ sockunion2str(&lladdr, buf[3], sizeof(buf[3])));
+ /* In case of shortcuts, nbma is given by lladdr, not
+ * vc->remote.nbma.
+ */
+ netlink_update_binding(ifp, &addr, &lladdr);
}
} else {
- debugf(NHRP_DEBUG_KERNEL, "Netlink: update %s dev %s nud %x",
- sockunion2str(&addr, buf, sizeof(buf)), ifp->name,
- ndm->ndm_state);
-
state = (msg->nlmsg_type == RTM_NEWNEIGH) ? ndm->ndm_state
: NUD_FAILED;
nhrp_cache_set_used(c, state == NUD_REACHABLE);
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index 81f7d9942..42f6a88f9 100644
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -119,12 +119,43 @@ static void nhrp_cache_update_route(struct nhrp_cache *c)
{
struct prefix pfx;
struct nhrp_peer *p = c->cur.peer;
+ char buf[3][SU_ADDRSTRLEN];
+ struct nhrp_interface *nifp;
sockunion2hostprefix(&c->remote_addr, &pfx);
if (p && nhrp_peer_check(p, 1)) {
- netlink_update_binding(p->ifp, &c->remote_addr,
- &p->vc->remote.nbma);
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
+ /* remote_nbma_natoa is already set. Therefore, binding
+ * should be updated to this value and not vc's remote
+ * nbma.
+ */
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (remote_nbma_natoa set): Update binding for %s dev %s from (deleted) peer.vc.nbma %s to %s",
+ sockunion2str(&c->remote_addr, buf[0],
+ sizeof(buf[0])),
+ p->ifp->name,
+ sockunion2str(&p->vc->remote.nbma, buf[1],
+ sizeof(buf[1])),
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
+ sizeof(buf[2])));
+
+ netlink_update_binding(p->ifp, &c->remote_addr,
+ &c->cur.remote_nbma_natoa);
+ } else {
+ /* update binding to peer->vc->remote->nbma */
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (remote_nbma_natoa unspec): Update binding for %s dev %s from (deleted) to peer.vc.nbma %s",
+ sockunion2str(&c->remote_addr, buf[0],
+ sizeof(buf[0])),
+ p->ifp->name,
+ sockunion2str(&p->vc->remote.nbma, buf[1],
+ sizeof(buf[1])));
+
+ netlink_update_binding(p->ifp, &c->remote_addr,
+ &p->vc->remote.nbma);
+ }
+
nhrp_route_announce(1, c->cur.type, &pfx, c->ifp, NULL,
c->cur.mtu);
if (c->cur.type >= NHRP_CACHE_DYNAMIC) {
@@ -139,6 +170,17 @@ static void nhrp_cache_update_route(struct nhrp_cache *c)
c->route_installed = 1;
}
} else {
+ /* debug the reason for peer check fail */
+ if (p) {
+ nifp = p->ifp->info;
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (peer check failed: online?%d requested?%d ipsec?%d)",
+ p->online, p->requested,
+ nifp->ipsec_profile ? 1 : 0);
+ } else
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (peer check failed: no p)");
+
if (c->nhrp_route_installed) {
nhrp_route_update_nhrp(&pfx, NULL);
c->nhrp_route_installed = 0;
@@ -207,10 +249,10 @@ static void nhrp_cache_update_timers(struct nhrp_cache *c)
static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg)
{
struct nhrp_cache *c = container_of(r, struct nhrp_cache, eventid);
- char buf[SU_ADDRSTRLEN];
+ char buf[3][SU_ADDRSTRLEN];
debugf(NHRP_DEBUG_COMMON, "cache: %s %s: %s", c->ifp->name,
- sockunion2str(&c->remote_addr, buf, sizeof(buf)),
+ sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
(const char *)arg);
nhrp_reqid_free(&nhrp_event_reqid, r);
@@ -230,6 +272,26 @@ static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg)
if (c->cur.peer)
nhrp_peer_notify_add(c->cur.peer, &c->peer_notifier,
nhrp_cache_peer_notifier);
+
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
+ debugf(NHRP_DEBUG_COMMON,
+ "cache: update binding for %s dev %s from (deleted) peer.vc.nbma %s to %s",
+ sockunion2str(&c->remote_addr, buf[0],
+ sizeof(buf[0])),
+ c->ifp->name,
+ (c->cur.peer ? sockunion2str(
+ &c->cur.peer->vc->remote.nbma, buf[1],
+ sizeof(buf[1]))
+ : "(no peer)"),
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
+ sizeof(buf[2])));
+
+ if (c->cur.peer)
+ netlink_update_binding(
+ c->cur.peer->ifp, &c->remote_addr,
+ &c->cur.remote_nbma_natoa);
+ }
+
nhrp_cache_update_route(c);
notifier_call(&c->notifier_list, NOTIFY_CACHE_BINDING_CHANGE);
} else {
@@ -273,6 +335,8 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
int holding_time, struct nhrp_peer *p,
uint32_t mtu, union sockunion *nbma_oa)
{
+ char buf[2][SU_ADDRSTRLEN];
+
if (c->cur.type > type || c->new.type > type) {
nhrp_peer_unref(p);
return 0;
@@ -293,17 +357,31 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
break;
}
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[0], sizeof(buf[0]));
+ if (nbma_oa)
+ sockunion2str(nbma_oa, buf[1], sizeof(buf[1]));
+
nhrp_cache_reset_new(c);
if (c->cur.type == type && c->cur.peer == p && c->cur.mtu == mtu) {
+ debugf(NHRP_DEBUG_COMMON,
+ "cache: same type %u, updating expiry and changing nbma addr from %s to %s",
+ type, buf[0], nbma_oa ? buf[1] : "(NULL)");
if (holding_time > 0)
c->cur.expires = monotime(NULL) + holding_time;
+
if (nbma_oa)
c->cur.remote_nbma_natoa = *nbma_oa;
else
memset(&c->cur.remote_nbma_natoa, 0,
sizeof(c->cur.remote_nbma_natoa));
+
nhrp_peer_unref(p);
} else {
+ debugf(NHRP_DEBUG_COMMON,
+ "cache: new type %u/%u, or peer %s, or mtu %u/%u, nbma %s --> %s (map %d)",
+ c->cur.type, type, (c->cur.peer == p) ? "same" : "diff",
+ c->cur.mtu, mtu, buf[0], nbma_oa ? buf[1] : "(NULL)",
+ c->map);
c->new.type = type;
c->new.peer = p;
c->new.mtu = mtu;
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index 5ca477fb5..2dc019ce6 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -314,23 +314,29 @@ void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb)
zbuf_reset(zb);
}
-static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p)
+static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp)
{
+ struct interface *ifp = pp->ifp;
struct zbuf *zb, payload;
struct nhrp_packet_header *hdr;
struct nhrp_cie_header *cie;
struct nhrp_extension_header *ext;
- struct nhrp_interface *nifp;
+ struct nhrp_cache *c;
+ union sockunion cie_nbma, cie_proto, *proto_addr, *nbma_addr;
+ int holdtime, prefix_len, hostprefix_len;
+ struct nhrp_interface *nifp = ifp->info;
struct nhrp_peer *peer;
+ size_t paylen;
+ char buf[SU_ADDRSTRLEN];
- if (!(p->if_ad->flags & NHRP_IFF_SHORTCUT)) {
+ if (!(pp->if_ad->flags & NHRP_IFF_SHORTCUT)) {
debugf(NHRP_DEBUG_COMMON, "Shortcuts disabled");
/* FIXME: Send error indication? */
return;
}
- if (p->if_ad->network_id && p->route_type == NHRP_ROUTE_OFF_NBMA
- && p->route_prefix.prefixlen < 8) {
+ if (pp->if_ad->network_id && pp->route_type == NHRP_ROUTE_OFF_NBMA
+ && pp->route_prefix.prefixlen < 8) {
debugf(NHRP_DEBUG_COMMON,
"Shortcut to more generic than /8 dropped");
return;
@@ -338,45 +344,101 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p)
debugf(NHRP_DEBUG_COMMON, "Parsing and replying to Resolution Req");
- if (nhrp_route_address(p->ifp, &p->src_proto, NULL, &peer)
+ if (nhrp_route_address(ifp, &pp->src_proto, NULL, &peer)
!= NHRP_ROUTE_NBMA_NEXTHOP)
return;
-#if 0
- /* FIXME: Update requestors binding if CIE specifies holding time */
- nhrp_cache_update_binding(
- NHRP_CACHE_CACHED, &p->src_proto,
- nhrp_peer_get(p->ifp, &p->src_nbma),
- htons(cie->holding_time));
-#endif
+ /* Copy payload CIE */
+ hostprefix_len = 8 * sockunion_get_addrlen(&pp->if_ad->addr);
+ paylen = zbuf_used(&pp->payload);
+ debugf(NHRP_DEBUG_COMMON, "shortcut res_rep: paylen %zu", paylen);
+
+ while ((cie = nhrp_cie_pull(&pp->payload, pp->hdr, &cie_nbma,
+ &cie_proto))
+ != NULL) {
+ prefix_len = cie->prefix_length;
+ debugf(NHRP_DEBUG_COMMON,
+ "shortcut res_rep: parsing CIE with prefixlen=%u",
+ prefix_len);
+ if (prefix_len == 0 || prefix_len >= hostprefix_len)
+ prefix_len = hostprefix_len;
+
+ if (prefix_len != hostprefix_len
+ && !(pp->hdr->flags
+ & htons(NHRP_FLAG_REGISTRATION_UNIQUE))) {
+ cie->code = NHRP_CODE_BINDING_NON_UNIQUE;
+ continue;
+ }
+
+ /* We currently support only unique prefix registrations */
+ if (prefix_len != hostprefix_len) {
+ cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED;
+ continue;
+ }
+
+ proto_addr = (sockunion_family(&cie_proto) == AF_UNSPEC)
+ ? &pp->src_proto
+ : &cie_proto;
+ nbma_addr = (sockunion_family(&cie_nbma) == AF_UNSPEC)
+ ? &pp->src_nbma
+ : &cie_nbma;
+
+ holdtime = htons(cie->holding_time);
+ debugf(NHRP_DEBUG_COMMON,
+ "shortcut res_rep: holdtime is %u (if 0, using %u)",
+ holdtime, pp->if_ad->holdtime);
+ if (!holdtime)
+ holdtime = pp->if_ad->holdtime;
+
+ c = nhrp_cache_get(ifp, proto_addr, 1);
+ if (!c) {
+ debugf(NHRP_DEBUG_COMMON,
+ "shortcut res_rep: no cache found");
+ cie->code = NHRP_CODE_INSUFFICIENT_RESOURCES;
+ continue;
+ }
+ if (nbma_addr)
+ sockunion2str(nbma_addr, buf, sizeof(buf));
+
+ debugf(NHRP_DEBUG_COMMON,
+ "shortcut res_rep: updating binding for nmba addr %s",
+ nbma_addr ? buf : "(NULL)");
+ if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime,
+ nhrp_peer_ref(pp->peer),
+ htons(cie->mtu), nbma_addr)) {
+ cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED;
+ continue;
+ }
- nifp = peer->ifp->info;
+ cie->code = NHRP_CODE_SUCCESS;
+ }
/* Create reply */
zb = zbuf_alloc(1500);
- hdr = nhrp_packet_push(zb, NHRP_PACKET_RESOLUTION_REPLY, &p->src_nbma,
- &p->src_proto, &p->dst_proto);
+ hdr = nhrp_packet_push(zb, NHRP_PACKET_RESOLUTION_REPLY, &pp->src_nbma,
+ &pp->src_proto, &pp->dst_proto);
/* Copied information from request */
- hdr->flags =
- p->hdr->flags & htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER
- | NHRP_FLAG_RESOLUTION_SOURCE_STABLE);
+ hdr->flags = pp->hdr->flags
+ & htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER
+ | NHRP_FLAG_RESOLUTION_SOURCE_STABLE);
hdr->flags |= htons(NHRP_FLAG_RESOLUTION_DESTINATION_STABLE
| NHRP_FLAG_RESOLUTION_AUTHORATIVE);
- hdr->u.request_id = p->hdr->u.request_id;
+ hdr->u.request_id = pp->hdr->u.request_id;
- /* CIE payload */
+ /* CIE payload for the reply packet */
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, &nifp->nbma,
- &p->if_ad->addr);
- cie->holding_time = htons(p->if_ad->holdtime);
- cie->mtu = htons(p->if_ad->mtu);
- if (p->if_ad->network_id && p->route_type == NHRP_ROUTE_OFF_NBMA)
- cie->prefix_length = p->route_prefix.prefixlen;
+ &pp->if_ad->addr);
+ cie->holding_time = htons(pp->if_ad->holdtime);
+ cie->mtu = htons(pp->if_ad->mtu);
+ if (pp->if_ad->network_id && pp->route_type == NHRP_ROUTE_OFF_NBMA)
+ cie->prefix_length = pp->route_prefix.prefixlen;
else
- cie->prefix_length = 8 * sockunion_get_addrlen(&p->if_ad->addr);
+ cie->prefix_length =
+ 8 * sockunion_get_addrlen(&pp->if_ad->addr);
/* Handle extensions */
- while ((ext = nhrp_ext_pull(&p->extensions, &payload)) != NULL) {
+ while ((ext = nhrp_ext_pull(&pp->extensions, &payload)) != NULL) {
switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) {
case NHRP_EXTENSION_NAT_ADDRESS:
if (sockunion_family(&nifp->nat_nbma) == AF_UNSPEC)
@@ -386,13 +448,13 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p)
if (!ext)
goto err;
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS,
- &nifp->nat_nbma, &p->if_ad->addr);
+ &nifp->nat_nbma, &pp->if_ad->addr);
if (!cie)
goto err;
nhrp_ext_complete(zb, ext);
break;
default:
- if (nhrp_ext_reply(zb, hdr, p->ifp, ext, &payload) < 0)
+ if (nhrp_ext_reply(zb, hdr, ifp, ext, &payload) < 0)
goto err;
break;
}
@@ -657,7 +719,7 @@ enum packet_type_t {
PACKET_INDICATION,
};
-static const struct {
+static struct {
enum packet_type_t type;
const char *name;
void (*handler)(struct nhrp_packet_parser *);
@@ -897,11 +959,15 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
if (extoff) {
assert(zb->head > zb->buf);
uint32_t header_offset = zb->head - zb->buf;
- if ((extoff >= realsize) || (extoff < (header_offset))) {
- info = "extoff larger than packet, or smaller than header";
+ if (extoff >= realsize) {
+ info = "extoff larger than packet";
+ goto drop;
+ }
+ if (extoff < header_offset) {
+ info = "extoff smaller than header offset";
goto drop;
}
- paylen = extoff - (zb->head - zb->buf);
+ paylen = extoff - header_offset;
} else {
paylen = zbuf_used(zb);
}
diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c
index 2552f9fd1..1c2b2b28f 100644
--- a/nhrpd/nhrp_shortcut.c
+++ b/nhrpd/nhrp_shortcut.c
@@ -53,14 +53,21 @@ static int nhrp_shortcut_do_expire(struct thread *t)
static void nhrp_shortcut_cache_notify(struct notifier_block *n,
unsigned long cmd)
{
+ char buf[PREFIX_STRLEN];
+
struct nhrp_shortcut *s =
container_of(n, struct nhrp_shortcut, cache_notifier);
switch (cmd) {
case NOTIFY_CACHE_UP:
if (!s->route_installed) {
- nhrp_route_announce(1, s->type, s->p, NULL,
- &s->cache->remote_addr, 0);
+ debugf(NHRP_DEBUG_ROUTE,
+ "Shortcut: route install %s nh (unspec) dev %s",
+ prefix2str(s->p, buf, sizeof(buf)),
+ s->cache->ifp->name);
+
+ nhrp_route_announce(1, s->type, s->p, s->cache->ifp,
+ NULL, 0);
s->route_installed = 1;
}
break;
@@ -84,6 +91,8 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
enum nhrp_cache_type type,
struct nhrp_cache *c, int holding_time)
{
+ char buf[2][PREFIX_STRLEN];
+
s->type = type;
if (c != s->cache) {
if (s->cache) {
@@ -98,13 +107,29 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
/* Force renewal of Zebra announce on prefix
* change */
s->route_installed = 0;
+ debugf(NHRP_DEBUG_ROUTE,
+ "Shortcut: forcing renewal of zebra announce on prefix change peer %s ht %u cur nbma %s dev %s",
+ sockunion2str(&s->cache->remote_addr,
+ buf[0], sizeof(buf[0])),
+ holding_time,
+ sockunion2str(
+ &s->cache->cur.remote_nbma_natoa,
+ buf[1], sizeof(buf[1])),
+ s->cache->ifp->name);
nhrp_shortcut_cache_notify(&s->cache_notifier,
NOTIFY_CACHE_UP);
}
}
- if (!s->cache || !s->cache->route_installed)
+ if (!s->cache || !s->cache->route_installed) {
+ debugf(NHRP_DEBUG_ROUTE,
+ "Shortcut: notify cache down because cache?%s or ri?%s",
+ s->cache ? "yes" : "no",
+ s->cache ? (s->cache->route_installed ? "yes"
+ : "no")
+ : "n/a");
nhrp_shortcut_cache_notify(&s->cache_notifier,
NOTIFY_CACHE_DOWN);
+ }
}
if (s->type == NHRP_CACHE_NEGATIVE && !s->route_installed) {
nhrp_route_announce(1, s->type, s->p, NULL, NULL, 0);
@@ -141,6 +166,7 @@ static void nhrp_shortcut_delete(struct nhrp_shortcut *s)
rn = route_node_lookup(shortcut_rib[afi], s->p);
if (rn) {
XFREE(MTYPE_NHRP_SHORTCUT, rn->info);
+ rn->info = NULL;
route_unlock_node(rn);
route_unlock_node(rn);
}
@@ -190,11 +216,10 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,
struct nhrp_extension_header *ext;
struct nhrp_cie_header *cie;
struct nhrp_cache *c = NULL;
- union sockunion *proto, cie_proto, *nbma, *nbma_natoa, cie_nbma,
- nat_nbma;
+ union sockunion *proto, cie_proto, *nbma, cie_nbma, nat_nbma;
struct prefix prefix, route_prefix;
struct zbuf extpl;
- char bufp[PREFIX_STRLEN], buf[3][SU_ADDRSTRLEN];
+ char bufp[PREFIX_STRLEN], buf[4][SU_ADDRSTRLEN];
int holding_time = pp->if_ad->holdtime;
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
@@ -262,39 +287,55 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,
}
debugf(NHRP_DEBUG_COMMON,
- "Shortcut: %s is at proto %s cie-nbma %s nat-nbma %s cie-holdtime %d",
+ "Shortcut: %s is at proto %s dst_proto %s cie-nbma %s nat-nbma %s cie-holdtime %d",
prefix2str(&prefix, bufp, sizeof(bufp)),
sockunion2str(proto, buf[0], sizeof(buf[0])),
- sockunion2str(&cie_nbma, buf[1], sizeof(buf[1])),
- sockunion2str(&nat_nbma, buf[2], sizeof(buf[2])),
+ sockunion2str(&pp->dst_proto, buf[1], sizeof(buf[1])),
+ sockunion2str(&cie_nbma, buf[2], sizeof(buf[2])),
+ sockunion2str(&nat_nbma, buf[3], sizeof(buf[3])),
htons(cie->holding_time));
/* Update cache entry for the protocol to nbma binding */
- if (sockunion_family(&nat_nbma) != AF_UNSPEC) {
+ if (sockunion_family(&nat_nbma) != AF_UNSPEC)
nbma = &nat_nbma;
- nbma_natoa = &cie_nbma;
- } else {
+ else
nbma = &cie_nbma;
- nbma_natoa = NULL;
- }
+
if (sockunion_family(nbma)) {
c = nhrp_cache_get(pp->ifp, proto, 1);
if (c) {
- nhrp_cache_update_binding(c, NHRP_CACHE_CACHED,
+ debugf(NHRP_DEBUG_COMMON,
+ "Shortcut: cache found, update binding");
+ nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC,
holding_time,
nhrp_peer_get(pp->ifp, nbma),
- htons(cie->mtu), nbma_natoa);
+ htons(cie->mtu), nbma);
+ } else {
+ debugf(NHRP_DEBUG_COMMON,
+ "Shortcut: no cache for nbma %s", buf[2]);
}
}
/* Update shortcut entry for subnet to protocol gw binding */
- if (c && !sockunion_same(proto, &pp->dst_proto)) {
+ if (c) {
ps = nhrp_shortcut_get(&prefix);
if (ps) {
ps->addr = s->addr;
- nhrp_shortcut_update_binding(ps, NHRP_CACHE_CACHED, c,
+ debugf(NHRP_DEBUG_COMMON,
+ "Shortcut: calling update_binding");
+ nhrp_shortcut_update_binding(ps, NHRP_CACHE_DYNAMIC, c,
holding_time);
+ } else {
+ debugf(NHRP_DEBUG_COMMON,
+ "Shortcut: proto diff but no ps");
}
+ } else {
+ debugf(NHRP_DEBUG_COMMON,
+ "NO Shortcut because c NULL?%s or same proto?%s",
+ c ? "no" : "yes",
+ proto && pp && sockunion_same(proto, &pp->dst_proto)
+ ? "yes"
+ : "no");
}
debugf(NHRP_DEBUG_COMMON, "Shortcut: Resolution reply handled");
@@ -306,7 +347,9 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
struct nhrp_packet_header *hdr;
struct interface *ifp;
struct nhrp_interface *nifp;
+ struct nhrp_afi_data *if_ad;
struct nhrp_peer *peer;
+ struct nhrp_cie_header *cie;
if (nhrp_route_address(NULL, &s->addr, NULL, &peer)
!= NHRP_ROUTE_NBMA_NEXTHOP)
@@ -336,7 +379,15 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
* - MTU: MTU of the source station
* - Holding Time: Max time to cache the source information
* */
- /* FIXME: Send holding time, and MTU */
+ /* FIXME: push CIE for each local protocol address */
+ cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);
+ cie->prefix_length = 0xff;
+ if_ad = &nifp->afi[family2afi(sockunion_family(&s->addr))];
+ cie->holding_time = htons(if_ad->holdtime);
+ cie->mtu = htons(if_ad->mtu);
+ debugf(NHRP_DEBUG_COMMON,
+ "Shortcut res_req: set cie ht to %u and mtu to %u. shortcut ht is %u",
+ ntohs(cie->holding_time), ntohs(cie->mtu), s->holding_time);
nhrp_ext_request(zb, hdr, ifp);
diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c
index f6d18fb77..a3066f917 100644
--- a/nhrpd/nhrp_vty.c
+++ b/nhrpd/nhrp_vty.c
@@ -12,6 +12,7 @@
#include "zclient.h"
#include "stream.h"
#include "filter.h"
+#include "json.h"
#include "nhrpd.h"
#include "netlink.h"
@@ -594,6 +595,7 @@ struct info_ctx {
struct vty *vty;
afi_t afi;
int count;
+ struct json_object *json;
};
static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
@@ -601,22 +603,60 @@ static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN];
+ struct json_object *json = NULL;
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
return;
- if (!ctx->count) {
+
+ if (!ctx->count && !ctx->json) {
vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s\n", "Iface", "Type",
"Protocol", "NBMA", "Flags", "Identity");
}
ctx->count++;
+ sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0]));
+ if (c->cur.peer)
+ sockunion2str(&c->cur.peer->vc->remote.nbma,
+ buf[1], sizeof(buf[1]));
+ else
+ snprintf(buf[1], sizeof(buf[1]), "-");
+
+ if (json) {
+ json = json_object_new_object();
+ json_object_string_add(json, "interface", c->ifp->name);
+ json_object_string_add(json, "type",
+ nhrp_cache_type_str[c->cur.type]);
+ json_object_string_add(json, "protocol", buf[0]);
+ json_object_string_add(json, "nbma", buf[1]);
+
+ if (c->used)
+ json_object_boolean_true_add(json, "used");
+ else
+ json_object_boolean_false_add(json, "used");
+
+ if (c->t_timeout)
+ json_object_boolean_true_add(json, "timeout");
+ else
+ json_object_boolean_false_add(json, "timeout");
+
+ if (c->t_auth)
+ json_object_boolean_true_add(json, "auth");
+ else
+ json_object_boolean_false_add(json, "auth");
+
+ if (c->cur.peer)
+ json_object_string_add(json, "identity",
+ c->cur.peer->vc->remote.id);
+ else
+ json_object_string_add(json, "identity", "-");
+
+ json_object_array_add(ctx->json, json);
+ return;
+ }
vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s\n", c->ifp->name,
nhrp_cache_type_str[c->cur.type],
- sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
- c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma,
- buf[1], sizeof(buf[1]))
- : "-",
+ buf[0], buf[1],
c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ',
c->t_auth ? 'A' : ' ',
c->cur.peer ? c->cur.peer->vc->remote.id : "-");
@@ -628,19 +668,35 @@ static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg,
struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN];
+ struct json_object *json = NULL;
- if (!ctx->count) {
+ if (!ctx->count && !ctx->json) {
vty_out(vty, "%-8s %-24s %-16s %-16s\n", "Iface", "FQDN",
"NBMA", "Protocol");
}
ctx->count++;
+ if (reg && reg->peer)
+ sockunion2str(&reg->peer->vc->remote.nbma,
+ buf[0], sizeof(buf[0]));
+ else
+ snprintf(buf[0], sizeof(buf[0]), "-");
+ sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1],
+ sizeof(buf[1]));
+
+ if (ctx->json) {
+ json = json_object_new_object();
+ json_object_string_add(json, "interface", n->ifp->name);
+ json_object_string_add(json, "fqdn", n->nbma_fqdn);
+ json_object_string_add(json, "nbma", buf[0]);
+ json_object_string_add(json, "protocol", buf[1]);
+
+ json_object_array_add(ctx->json, json);
+ return;
+ }
+
vty_out(vty, "%-8s %-24s %-16s %-16s\n", n->ifp->name, n->nbma_fqdn,
- (reg && reg->peer) ? sockunion2str(&reg->peer->vc->remote.nbma,
- buf[0], sizeof(buf[0]))
- : "-",
- sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1],
- sizeof(buf[1])));
+ buf[0], buf[1]);
}
static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
@@ -649,6 +705,7 @@ static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
struct nhrp_cache *c;
struct vty *vty = ctx->vty;
char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
+ struct json_object *json = NULL;
if (!ctx->count) {
vty_out(vty, "%-8s %-24s %-24s %s\n", "Type", "Prefix", "Via",
@@ -657,20 +714,82 @@ static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
ctx->count++;
c = s->cache;
- vty_out(ctx->vty, "%-8s %-24s %-24s %s\n", nhrp_cache_type_str[s->type],
- prefix2str(s->p, buf1, sizeof(buf1)),
- c ? sockunion2str(&c->remote_addr, buf2, sizeof(buf2)) : "",
+ if (c)
+ sockunion2str(&c->remote_addr, buf2, sizeof(buf2));
+ prefix2str(s->p, buf1, sizeof(buf1));
+
+ if (ctx->json) {
+ json = json_object_new_object();
+ json_object_string_add(json, "type",
+ nhrp_cache_type_str[s->type]);
+ json_object_string_add(json, "prefix", buf1);
+
+ if (c)
+ json_object_string_add(json, "via", buf2);
+
+ if (c && c->cur.peer)
+ json_object_string_add(json, "identity",
+ c->cur.peer->vc->remote.id);
+ else
+ json_object_string_add(json, "identity", "");
+
+ json_object_array_add(ctx->json, json);
+ return;
+ }
+
+ vty_out(ctx->vty, "%-8s %-24s %-24s %s\n",
+ nhrp_cache_type_str[s->type],
+ buf1, buf2,
(c && c->cur.peer) ? c->cur.peer->vc->remote.id : "");
}
static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
{
struct info_ctx *ctx = pctx;
- char buf[SU_ADDRSTRLEN];
+ char buf[3][SU_ADDRSTRLEN];
+ struct json_object *json = NULL;
+
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
return;
+ sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0]));
+ if (c->cur.peer)
+ sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1],
+ sizeof(buf[1]));
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC)
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
+ sizeof(buf[2]));
+ if (ctx->json) {
+ json = json_object_new_object();
+ json_object_string_add(json, "type",
+ nhrp_cache_type_str[c->cur.type]);
+
+ if (c->cur.peer && c->cur.peer->online)
+ json_object_boolean_true_add(json, "up");
+ else
+ json_object_boolean_false_add(json, "up");
+
+ if (c->used)
+ json_object_boolean_true_add(json, "used");
+ else
+ json_object_boolean_false_add(json, "used");
+
+ json_object_string_add(json, "protocolAddress", buf[0]);
+ json_object_int_add(json, "protocolAddressSize",
+ 8 * family2addrsize(sockunion_family
+ (&c->remote_addr)));
+
+ if (c->cur.peer)
+ json_object_string_add(json, "nbmaAddress", buf[1]);
+
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC)
+ json_object_string_add(json, "nbmaNatOaAddress",
+ buf[2]);
+
+ json_object_array_add(ctx->json, json);
+ return;
+ }
vty_out(ctx->vty,
"Type: %s\n"
"Flags:%s%s\n"
@@ -678,40 +797,45 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
nhrp_cache_type_str[c->cur.type],
(c->cur.peer && c->cur.peer->online) ? " up" : "",
c->used ? " used" : "",
- sockunion2str(&c->remote_addr, buf, sizeof(buf)),
+ buf[0],
8 * family2addrsize(sockunion_family(&c->remote_addr)));
- if (c->cur.peer) {
- vty_out(ctx->vty, "NBMA-Address: %s\n",
- sockunion2str(&c->cur.peer->vc->remote.nbma, buf,
- sizeof(buf)));
- }
+ if (c->cur.peer)
+ vty_out(ctx->vty, "NBMA-Address: %s\n", buf[1]);
- if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
- vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n",
- sockunion2str(&c->cur.remote_nbma_natoa, buf,
- sizeof(buf)));
- }
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC)
+ vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", buf[2]);
vty_out(ctx->vty, "\n\n");
}
DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
- "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]",
+ "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp] [json]",
SHOW_STR
AFI_STR
"NHRP information\n"
"Forwarding cache information\n"
"Next hop server information\n"
"Shortcut information\n"
- "opennhrpctl style cache dump\n")
+ "opennhrpctl style cache dump\n"
+ JSON_STR)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct info_ctx ctx = {
- .vty = vty, .afi = cmd_to_afi(argv[1]),
+ .vty = vty, .afi = cmd_to_afi(argv[1]), .json = NULL
};
-
+ bool uj = use_json(argc, argv);
+ struct json_object *json_path = NULL;
+ struct json_object *json_vrf = NULL, *json_vrf_path = NULL;
+ int ret = CMD_SUCCESS;
+
+ if (uj) {
+ json_vrf = json_object_new_object();
+ json_vrf_path = json_object_new_object();
+ json_path = json_object_new_array();
+ ctx.json = json_path;
+ }
if (argc <= 3 || argv[3]->text[0] == 'c') {
FOR_ALL_INTERFACES (vrf, ifp)
nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
@@ -721,49 +845,104 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
} else if (argv[3]->text[0] == 's') {
nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
} else {
- vty_out(vty, "Status: ok\n\n");
+ if (!ctx.json)
+ vty_out(vty, "Status: ok\n\n");
+ else
+ json_object_string_add(json_vrf, "status", "ok");
+
ctx.count++;
FOR_ALL_INTERFACES (vrf, ifp)
nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
}
+ if (uj)
+ json_object_int_add(json_vrf, "entriesCount", ctx.count);
if (!ctx.count) {
- vty_out(vty, "%% No entries\n");
- return CMD_WARNING;
+ if (!ctx.json)
+ vty_out(vty, "%% No entries\n");
+ ret = CMD_WARNING;
}
-
- return CMD_SUCCESS;
+ if (uj) {
+ json_object_object_add(json_vrf_path, "attr", json_vrf);
+ json_object_object_add(json_vrf_path, "table", ctx.json);
+ vty_out(vty, "%s",
+ json_object_to_json_string_ext(
+ json_vrf_path, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json_vrf_path);
+ }
+ return ret;
}
+struct dmvpn_cfg {
+ struct vty *vty;
+ struct json_object *json;
+};
+
static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
{
- struct vty *vty = ctx;
+ struct dmvpn_cfg *ctxt = ctx;
+ struct vty *vty;
char buf[2][SU_ADDRSTRLEN];
+ struct json_object *json = NULL;
+
+ if (!ctxt || !ctxt->vty)
+ return;
+ vty = ctxt->vty;
+ sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0]));
+ sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1]));
+ if (ctxt->json) {
+ json = json_object_new_object();
+ json_object_string_add(json, "src", buf[0]);
+ json_object_string_add(json, "dst", buf[1]);
+
+ if (notifier_active(&vc->notifier_list))
+ json_object_boolean_true_add(json, "notifierActive");
+ else
+ json_object_boolean_false_add(json, "notifierActive");
- vty_out(vty, "%-24s %-24s %c %-4d %-24s\n",
- sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0])),
- sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1])),
- notifier_active(&vc->notifier_list) ? 'n' : ' ', vc->ipsec,
- vc->remote.id);
+ json_object_int_add(json, "sas", vc->ipsec);
+ json_object_string_add(json, "identity", vc->remote.id);
+ json_object_array_add(ctxt->json, json);
+ } else {
+ vty_out(vty, "%-24s %-24s %c %-4d %-24s\n",
+ buf[0], buf[1], notifier_active(&vc->notifier_list) ?
+ 'n' : ' ', vc->ipsec, vc->remote.id);
+ }
}
DEFUN(show_dmvpn, show_dmvpn_cmd,
- "show dmvpn",
+ "show dmvpn [json]",
SHOW_STR
- "DMVPN information\n")
+ "DMVPN information\n"
+ JSON_STR)
{
- vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n", "Src", "Dst", "Flags",
- "SAs", "Identity");
-
- nhrp_vc_foreach(show_dmvpn_entry, vty);
-
+ bool uj = use_json(argc, argv);
+ struct dmvpn_cfg ctxt;
+ struct json_object *json_path = NULL;
+
+ ctxt.vty = vty;
+ if (!uj) {
+ ctxt.json = NULL;
+ vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n",
+ "Src", "Dst", "Flags", "SAs", "Identity");
+ } else {
+ json_path = json_object_new_array();
+ ctxt.json = json_path;
+ }
+ nhrp_vc_foreach(show_dmvpn_entry, &ctxt);
+ if (uj) {
+ vty_out(vty, "%s",
+ json_object_to_json_string_ext(
+ json_path, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json_path);
+ }
return CMD_SUCCESS;
}
static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
{
struct info_ctx *ctx = data;
- if (c->cur.type <= NHRP_CACHE_CACHED) {
+ if (c->cur.type <= NHRP_CACHE_DYNAMIC) {
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
ctx->count++;
}
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 1717f1e65..f8df37094 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -256,7 +256,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
&& ospf6_route_is_same(request, request->next)) {
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
zlog_debug(
- " Best-path removal resulted Sencondary addition");
+ " Best-path removal resulted Secondary addition");
type = ADD;
request = request->next;
}
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index 58f087ca4..9cd83c245 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -731,7 +731,7 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
OSPF_DD_FLAG_I | OSPF_DD_FLAG_M | OSPF_DD_FLAG_MS;
if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL))
zlog_info(
- "%s: Intializing [DD]: %s with seqnum:%x , flags:%x",
+ "%s: Initializing [DD]: %s with seqnum:%x , flags:%x",
(oi->ospf->name) ? oi->ospf->name
: VRF_DEFAULT_NAME,
inet_ntoa(nbr->router_id), nbr->dd_seqnum,
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index d87f02627..0808f245e 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -2335,7 +2335,7 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd,
ip_len = iph->ip_len;
-#if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
+#if defined(__FreeBSD__) && (__FreeBSD_version < 1000000)
/*
* Kernel network code touches incoming IP header parameters,
* before protocol specific processing.
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index abc154896..30208deb1 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1520,6 +1520,10 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
pim_ifp->pim_ifstat_join_recv);
json_object_int_add(json_row, "joinTx",
pim_ifp->pim_ifstat_join_send);
+ json_object_int_add(json_row, "pruneTx",
+ pim_ifp->pim_ifstat_prune_send);
+ json_object_int_add(json_row, "pruneRx",
+ pim_ifp->pim_ifstat_prune_recv);
json_object_int_add(json_row, "registerRx",
pim_ifp->pim_ifstat_reg_recv);
json_object_int_add(json_row, "registerTx",
@@ -1706,7 +1710,10 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
json_object_int_add(json_row, "SGRpt", 1);
-
+ if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+ json_object_int_add(json_row, "protocolPim", 1);
+ if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
+ json_object_int_add(json_row, "protocolIgmp", 1);
json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
if (!json_grp) {
json_grp = json_object_new_object();
@@ -3732,8 +3739,6 @@ static void pim_show_bsr(struct pim_instance *pim,
char bsr_str[PREFIX_STRLEN];
json_object *json = NULL;
- vty_out(vty, "PIMv2 Bootstrap information\n");
-
if (pim->global_scope.current_bsr.s_addr == INADDR_ANY) {
strlcpy(bsr_str, "0.0.0.0", sizeof(bsr_str));
pim_time_uptime(uptime, sizeof(uptime),
@@ -3779,6 +3784,7 @@ static void pim_show_bsr(struct pim_instance *pim,
}
else {
+ vty_out(vty, "PIMv2 Bootstrap information\n");
vty_out(vty, "Current preferred BSR address: %s\n", bsr_str);
vty_out(vty,
"Priority Fragment-Tag State UpTime\n");
@@ -5790,13 +5796,18 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
int oif_vif_index;
struct interface *ifp_in;
char proto[100];
+ char state_str[PIM_REG_STATE_STR_LEN];
char mroute_uptime[10];
if (uj) {
json = json_object_new_object();
} else {
+ vty_out(vty, "IP Multicast Routing Table\n");
+ vty_out(vty, "Flags: S- Sparse, C - Connected, P - Pruned\n");
+ vty_out(vty,
+ " R - RP-bit set, F - Register flag, T - SPT-bit set\n");
vty_out(vty,
- "Source Group Proto Input Output TTL Uptime\n");
+ "\nSource Group Flags Proto Input Output TTL Uptime\n");
}
now = pim_time_monotonic_sec();
@@ -5819,6 +5830,23 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
sizeof(grp_str));
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
sizeof(src_str));
+
+ strlcpy(state_str, "S", sizeof(state_str));
+ /* When a non DR receives a igmp join, it creates a (*,G)
+ * channel_oil without any upstream creation */
+ if (c_oil->up) {
+ if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
+ strlcat(state_str, "C", sizeof(state_str));
+ if (pim_upstream_is_sg_rpt(c_oil->up))
+ strlcat(state_str, "R", sizeof(state_str));
+ if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
+ strlcat(state_str, "F", sizeof(state_str));
+ if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
+ strlcat(state_str, "T", sizeof(state_str));
+ }
+ if (pim_channel_oil_empty(c_oil))
+ strlcat(state_str, "P", sizeof(state_str));
+
ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
if (ifp_in)
@@ -5842,7 +5870,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
}
/* Find the source nested under the group, create it if
- * it doesn't exist */
+ * it doesn't exist
+ */
json_object_object_get_ex(json_group, src_str,
&json_source);
@@ -5965,14 +5994,16 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
}
vty_out(vty,
- "%-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
- src_str, grp_str, proto, in_ifname,
- out_ifname, ttl, mroute_uptime);
+ "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
+ src_str, grp_str, state_str, proto,
+ in_ifname, out_ifname, ttl,
+ mroute_uptime);
if (first) {
src_str[0] = '\0';
grp_str[0] = '\0';
in_ifname[0] = '\0';
+ state_str[0] = '\0';
mroute_uptime[0] = '\0';
first = 0;
}
@@ -5980,9 +6011,10 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
}
if (!uj && !found_oif) {
- vty_out(vty, "%-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
- src_str, grp_str, "none", in_ifname, "none", 0,
- "--:--:--");
+ vty_out(vty,
+ "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
+ src_str, grp_str, state_str, "none", in_ifname,
+ "none", 0, "--:--:--");
}
}
@@ -6600,18 +6632,18 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim,
switch (pim->spt.switchover) {
case PIM_SPT_IMMEDIATE:
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
pim_upstream_add_lhr_star_pimreg(pim);
break;
case PIM_SPT_INFINITY:
pim_upstream_remove_lhr_star_pimreg(pim, plist);
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
if (plist)
pim->spt.plist =
- XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist);
+ XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
break;
}
@@ -6672,6 +6704,26 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
}
+DEFPY (pim_register_accept_list,
+ pim_register_accept_list_cmd,
+ "[no] ip pim register-accept-list WORD$word",
+ NO_STR
+ IP_STR
+ PIM_STR
+ "Only accept registers from a specific source prefix list\n"
+ "Prefix-List name\n")
+{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+
+ if (no)
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
+ else {
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
+ pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, word);
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ip_pim_joinprune_time,
ip_pim_joinprune_time_cmd,
"ip pim join-prune-interval (60-600)",
@@ -7237,11 +7289,20 @@ DEFUN (no_ip_pim_ecmp_rebalance,
static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
{
struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
uint8_t need_startup = 0;
pim_ifp = ifp->info;
if (!pim_ifp) {
+ pim = pim_get_pim_instance(ifp->vrf_id);
+ /* Limit mcast interfaces to number of vifs available */
+ if (pim->mcast_if_count == MAXVIFS) {
+ vty_out(vty,
+ "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s\n",
+ MAXVIFS, ifp->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
(void)pim_if_new(ifp, true, false, false, false);
need_startup = 1;
} else {
@@ -7991,13 +8052,21 @@ DEFPY_HIDDEN (interface_ip_igmp_query_generate,
return CMD_SUCCESS;
}
-static int pim_cmd_interface_add(struct interface *ifp)
+static int pim_cmd_interface_add(struct vty *vty, struct interface *ifp)
{
struct pim_interface *pim_ifp = ifp->info;
+ struct pim_instance *pim;
- if (!pim_ifp)
+ if (!pim_ifp) {
+ pim = pim_get_pim_instance(ifp->vrf_id);
+ /* Limiting mcast interfaces to number of VIFs */
+ if (pim->mcast_if_count == MAXVIFS) {
+ vty_out(vty, "Max multicast interfaces(%d) reached.",
+ MAXVIFS);
+ return 0;
+ }
pim_ifp = pim_if_new(ifp, false, true, false, false);
- else
+ } else
PIM_IF_DO_PIM(pim_ifp->options);
pim_if_addr_add_all(ifp);
@@ -8068,15 +8137,17 @@ DEFPY (interface_ip_pim_activeactive,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct pim_interface *pim_ifp;
- if (!no && !pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM active-active on interface\n");
+ if (!no && !pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty,
+ "Could not enable PIM SM active-active on interface %s\n",
+ ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}
- if (PIM_DEBUG_MLAG)
- zlog_debug("%sConfiguring PIM active-active on Interface: %s",
- no ? "Un-":" ", ifp->name);
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%sConfiguring PIM active-active on Interface: %s",
+ no ? "Un-" : " ", ifp->name);
pim_ifp = ifp->info;
if (no)
@@ -8096,8 +8167,9 @@ DEFUN_HIDDEN (interface_ip_pim_ssm,
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty, "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -8113,8 +8185,9 @@ static int interface_ip_pim_helper(struct vty *vty)
VTY_DECLVAR_CONTEXT(interface, ifp);
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty, "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -8402,8 +8475,10 @@ DEFUN (interface_ip_pim_hello,
struct pim_interface *pim_ifp = ifp->info;
if (!pim_ifp) {
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty,
+ "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}
}
@@ -9145,8 +9220,10 @@ DEFUN (ip_pim_bfd,
struct bfd_info *bfd_info = NULL;
if (!pim_ifp) {
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty,
+ "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING;
}
}
@@ -9196,8 +9273,10 @@ DEFUN (ip_pim_bsm,
struct pim_interface *pim_ifp = ifp->info;
if (!pim_ifp) {
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty,
+ "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING;
}
}
@@ -9240,8 +9319,10 @@ DEFUN (ip_pim_ucast_bsm,
struct pim_interface *pim_ifp = ifp->info;
if (!pim_ifp) {
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty,
+ "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING;
}
}
@@ -9308,8 +9389,10 @@ DEFUN(
struct pim_interface *pim_ifp = ifp->info;
if (!pim_ifp) {
- if (!pim_cmd_interface_add(ifp)) {
- vty_out(vty, "Could not enable PIM SM on interface\n");
+ if (!pim_cmd_interface_add(vty, ifp)) {
+ vty_out(vty,
+ "Could not enable PIM SM on interface %s\n",
+ ifp->name);
return CMD_WARNING;
}
}
@@ -10770,6 +10853,8 @@ void pim_cmd_init(void)
install_element(CONFIG_NODE,
&no_ip_pim_spt_switchover_infinity_plist_cmd);
install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
+ install_element(CONFIG_NODE, &pim_register_accept_list_cmd);
+ install_element(VRF_NODE, &pim_register_accept_list_cmd);
install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index cb31878e0..d05790d33 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -186,6 +186,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_sock_reset(ifp);
pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
+ pim_ifp->pim->mcast_if_count++;
return pim_ifp;
}
@@ -209,6 +210,7 @@ void pim_if_delete(struct interface *ifp)
pim_neighbor_delete_all(ifp, "Interface removed from configuration");
pim_if_del_vif(ifp);
+ pim_ifp->pim->mcast_if_count--;
list_delete(&pim_ifp->igmp_socket_list);
list_delete(&pim_ifp->pim_neighbor_list);
@@ -1583,8 +1585,14 @@ int pim_ifp_create(struct interface *ifp)
}
if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
- sizeof(PIM_VXLAN_TERM_DEV_NAME)))
- pim_vxlan_add_term_dev(pim, ifp);
+ sizeof(PIM_VXLAN_TERM_DEV_NAME))) {
+ if (pim->mcast_if_count < MAXVIFS)
+ pim_vxlan_add_term_dev(pim, ifp);
+ else
+ zlog_warn(
+ "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
+ __func__, ifp->name, MAXVIFS);
+ }
return 0;
}
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 44d4ee719..70e06ccc4 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -628,6 +628,12 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
up->dualactive_ifchannel_count, up->flags);
}
+ if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
+ PIM_IF_FLAG_SET_PROTO_PIM(ch->flags);
+
+ if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+ PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags);
+
if (PIM_DEBUG_PIM_TRACE)
zlog_debug("%s: ifchannel %s(%s) is created ", __func__,
ch->sg_str, ch->interface->name);
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index 3d5cbd8ec..425622b79 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -69,7 +69,7 @@ struct pim_assert_metric {
#define PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(flags) ((flags) &= ~PIM_IF_FLAG_MASK_ASSERT_TRACKING_DESIRED)
/*
- * Flat to tell us if the ifchannel is (S,G,rpt)
+ * Flag to tell us if the ifchannel is (S,G,rpt)
*/
#define PIM_IF_FLAG_MASK_S_G_RPT (1 << 2)
#define PIM_IF_FLAG_TEST_S_G_RPT(flags) ((flags) & PIM_IF_FLAG_MASK_S_G_RPT)
@@ -77,6 +77,23 @@ struct pim_assert_metric {
#define PIM_IF_FLAG_UNSET_S_G_RPT(flags) ((flags) &= ~PIM_IF_FLAG_MASK_S_G_RPT)
/*
+ * Flag to tell us if the ifchannel is proto PIM
+ */
+#define PIM_IF_FLAG_MASK_PROTO_PIM (1 << 3)
+#define PIM_IF_FLAG_TEST_PROTO_PIM(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_PIM)
+#define PIM_IF_FLAG_SET_PROTO_PIM(flags) ((flags) |= PIM_IF_FLAG_MASK_PROTO_PIM)
+#define PIM_IF_FLAG_UNSET_PROTO_PIM(flags) \
+ ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_PIM)
+/*
+ * Flag to tell us if the ifchannel is proto IGMP
+ */
+#define PIM_IF_FLAG_MASK_PROTO_IGMP (1 << 4)
+#define PIM_IF_FLAG_TEST_PROTO_IGMP(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_IGMP)
+#define PIM_IF_FLAG_SET_PROTO_IGMP(flags) \
+ ((flags) |= PIM_IF_FLAG_MASK_PROTO_IGMP)
+#define PIM_IF_FLAG_UNSET_PROTO_IGMP(flags) \
+ ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_IGMP)
+/*
Per-interface (S,G) state
*/
struct pim_ifchannel {
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
index 347b0fc28..b4c2dd28c 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -69,6 +69,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
pim_msdp_exit(pim);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
}
@@ -81,6 +83,7 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
pim_if_init(pim);
+ pim->mcast_if_count = 0;
pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
pim->rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD;
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index 7b1fd2e17..71bd7c108 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -135,6 +135,9 @@ struct pim_instance {
char *plist;
} spt;
+ /* The name of the register-accept prefix-list */
+ char *register_plist;
+
struct hash *rpf_hash;
void *ssm_info; /* per-vrf SSM configuration */
@@ -165,6 +168,7 @@ struct pim_instance {
struct route_table *rp_table;
int iface_vif_index[MAXVIFS];
+ int mcast_if_count;
struct rb_pim_oil_head channel_oil_head;
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index 62bd2360c..3a88de207 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -140,18 +140,19 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh,
if ((source_flags & PIM_RPT_BIT_MASK)
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
- struct pim_rpf *rp = RP(pim_ifp->pim, sg->grp);
+ /*
+ * RFC 4601 Section 4.5.2:
+ * Received Prune(*,G) messages are processed even if the
+ * RP in the message does not match RP(G).
+ */
+ if (PIM_DEBUG_PIM_TRACE) {
+ char received_rp[INET_ADDRSTRLEN];
- if (!rp) {
- if (PIM_DEBUG_PIM_TRACE)
- zlog_debug(
- "%s: RP for %pSG4 completely failed lookup",
- __func__, sg);
- return;
+ pim_inet4_dump("<received?>", sg->src, received_rp,
+ sizeof(received_rp));
+ zlog_debug("%s: Prune received with RP(%s) for %pSG4",
+ __func__, received_rp, sg);
}
- // Ignoring Prune *,G's at the moment.
- if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr)
- return;
sg->src.s_addr = INADDR_ANY;
}
diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c
index 2bbab67e4..6bc8062c4 100644
--- a/pimd/pim_memory.c
+++ b/pimd/pim_memory.c
@@ -51,5 +51,5 @@ DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source")
DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state")
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration")
-DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name")
+DEFINE_MTYPE(PIMD, PIM_PLIST_NAME, "PIM Prefix List Names")
DEFINE_MTYPE(PIMD, PIM_VXLAN_SG, "PIM VxLAN mroute cache")
diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h
index e5ca57a15..6beeb6007 100644
--- a/pimd/pim_memory.h
+++ b/pimd/pim_memory.h
@@ -50,7 +50,7 @@ DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
DECLARE_MTYPE(PIM_PIM_INSTANCE)
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
DECLARE_MTYPE(PIM_SSM_INFO)
-DECLARE_MTYPE(PIM_SPT_PLIST_NAME);
+DECLARE_MTYPE(PIM_PLIST_NAME);
DECLARE_MTYPE(PIM_VXLAN_SG)
#endif /* _QUAGGA_PIM_MEMORY_H */
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index f366fdbe7..f75bd2c1b 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -232,6 +232,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
pim_upstream_mroute_iif_update(up->channel_oil, __func__);
}
pim_register_join(up);
+ /* if we have receiver, inherit from parent */
+ pim_upstream_inherited_olist_decide(pim_ifp->pim, up);
return 0;
}
@@ -961,7 +963,7 @@ static inline void pim_mroute_copy(struct mfcctl *oil,
static int pim_mroute_add(struct channel_oil *c_oil, const char *name)
{
struct pim_instance *pim = c_oil->pim;
- struct mfcctl tmp_oil;
+ struct mfcctl tmp_oil = { {0} };
int err;
pim->mroute_add_last = pim_time_monotonic_sec();
@@ -1017,8 +1019,10 @@ static int pim_mroute_add(struct channel_oil *c_oil, const char *name)
pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
}
- c_oil->installed = 1;
- c_oil->mroute_creation = pim_time_monotonic_sec();
+ if (!c_oil->installed) {
+ c_oil->installed = 1;
+ c_oil->mroute_creation = pim_time_monotonic_sec();
+ }
return 0;
}
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index ca7ca1140..d8a797f98 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -779,6 +779,7 @@ void pim_neighbor_update(struct pim_neighbor *neigh,
uint32_t dr_priority, struct list *addr_list)
{
struct pim_interface *pim_ifp = neigh->interface->info;
+ uint32_t old, new;
/* Received holdtime ? */
if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
@@ -818,6 +819,16 @@ void pim_neighbor_update(struct pim_neighbor *neigh,
neigh->prefix_list = addr_list;
update_dr_priority(neigh, hello_options, dr_priority);
+ new = PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
+ old = PIM_OPTION_IS_SET(neigh->hello_options,
+ PIM_OPTION_MASK_LAN_PRUNE_DELAY);
+
+ if (old != new) {
+ if (old)
+ ++pim_ifp->pim_number_of_nonlandelay_neighbors;
+ else
+ --pim_ifp->pim_number_of_nonlandelay_neighbors;
+ }
/*
Copy flags
*/
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 19baecb9c..7b0af8999 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -324,14 +324,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
struct prefix_sg sg;
uint32_t *bits;
int i_am_rp = 0;
- struct pim_interface *pim_ifp = NULL;
-
- pim_ifp = ifp->info;
+ struct pim_interface *pim_ifp = ifp->info;
+ struct pim_instance *pim = pim_ifp->pim;
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
- if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, dest_addr)) {
+ if (!pim_rp_check_is_my_ip_address(pim, dest_addr)) {
if (PIM_DEBUG_PIM_REG) {
char dest[INET_ADDRSTRLEN];
@@ -375,7 +374,7 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
sg.src = ip_hdr->ip_src;
sg.grp = ip_hdr->ip_dst;
- i_am_rp = I_am_RP(pim_ifp->pim, sg.grp);
+ i_am_rp = I_am_RP(pim, sg.grp);
if (PIM_DEBUG_PIM_REG) {
char src_str[INET_ADDRSTRLEN];
@@ -387,9 +386,36 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
if (i_am_rp
&& (dest_addr.s_addr
- == ((RP(pim_ifp->pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) {
+ == ((RP(pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) {
sentRegisterStop = 0;
+ if (pim->register_plist) {
+ struct prefix_list *plist;
+ struct prefix src;
+
+ plist = prefix_list_lookup(AFI_IP, pim->register_plist);
+
+ src.family = AF_INET;
+ src.prefixlen = IPV4_MAX_PREFIXLEN;
+ src.u.prefix4 = sg.src;
+
+ if (prefix_list_apply(plist, &src) == PREFIX_DENY) {
+ pim_register_stop_send(ifp, &sg, dest_addr,
+ src_addr);
+ if (PIM_DEBUG_PIM_PACKETS) {
+ char src_str[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<src?>", src_addr,
+ src_str,
+ sizeof(src_str));
+ zlog_debug("%s: Sending register-stop to %s for %pSG4 due to prefix-list denial, dropping packet",
+ __func__, src_str, &sg);
+ }
+
+ return 0;
+ }
+ }
+
if (*bits & PIM_REGISTER_BORDER_BIT) {
struct in_addr pimbr = pim_br_get_pmbr(&sg);
if (PIM_DEBUG_PIM_PACKETS)
@@ -411,14 +437,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
}
}
- struct pim_upstream *upstream =
- pim_upstream_find(pim_ifp->pim, &sg);
+ struct pim_upstream *upstream = pim_upstream_find(pim, &sg);
/*
* If we don't have a place to send ignore the packet
*/
if (!upstream) {
upstream = pim_upstream_add(
- pim_ifp->pim, &sg, ifp,
+ pim, &sg, ifp,
PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__,
NULL);
if (!upstream) {
@@ -452,9 +477,8 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
}
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
- || ((SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))
- && pim_upstream_inherited_olist(pim_ifp->pim, upstream)
- == 0)) {
+ || ((SwitchToSptDesiredOnRp(pim, &sg))
+ && pim_upstream_inherited_olist(pim, upstream) == 0)) {
pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
sentRegisterStop = 1;
} else {
@@ -463,15 +487,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
upstream->sptbit);
}
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
- || (SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))) {
+ || (SwitchToSptDesiredOnRp(pim, &sg))) {
if (sentRegisterStop) {
pim_upstream_keep_alive_timer_start(
- upstream,
- pim_ifp->pim->rp_keep_alive_time);
+ upstream, pim->rp_keep_alive_time);
} else {
pim_upstream_keep_alive_timer_start(
- upstream,
- pim_ifp->pim->keep_alive_time);
+ upstream, pim->keep_alive_time);
}
}
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 8799134ed..a9f1d9335 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -248,13 +248,14 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
if (PIM_DEBUG_PIM_TRACE) {
char buf[PREFIX_STRLEN];
- route_unlock_node(rn);
zlog_debug("Lookedup: %p for rp_info: %p(%s) Lock: %d", rn,
rp_info,
prefix2str(&rp_info->group, buf, sizeof(buf)),
rn->lock);
}
+ route_unlock_node(rn);
+
if (!best)
return rp_info;
@@ -1293,10 +1294,16 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
json_row, "outboundInterface",
rp_info->rp.source_nexthop
.interface->name);
-
+ else
+ json_object_string_add(
+ json_row, "outboundInterface",
+ "Unknown");
if (rp_info->i_am_rp)
json_object_boolean_true_add(json_row,
"iAmRP");
+ else
+ json_object_boolean_false_add(json_row,
+ "iAmRP");
if (rp_info->plist)
json_object_string_add(json_row,
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index efa58c1b1..07f8315a1 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -1794,10 +1794,16 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
continue;
if (pim_upstream_evaluate_join_desired_interface(up, ch,
starch)) {
- int flag = PIM_OIF_FLAG_PROTO_PIM;
+ int flag = 0;
if (!ch)
flag = PIM_OIF_FLAG_PROTO_STAR;
+ else {
+ if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
+ flag = PIM_OIF_FLAG_PROTO_IGMP;
+ if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+ flag |= PIM_OIF_FLAG_PROTO_PIM;
+ }
pim_channel_add_oif(up->channel_oil, ifp, flag,
__func__);
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 8a87dfbb5..72540903b 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -216,6 +216,11 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
ssm->plist_name);
++writes;
}
+ if (pim->register_plist) {
+ vty_out(vty, "%sip pim register-accept-list %s\n", spaces,
+ pim->register_plist);
+ ++writes;
+ }
if (pim->spt.switchover == PIM_SPT_INFINITY) {
if (pim->spt.plist)
vty_out(vty,
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index 569b04d27..380c97a97 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -253,8 +253,17 @@ static void pim_vxlan_orig_mr_up_del(struct pim_vxlan_sg *vxlan_sg)
/* if there are other references register the source
* for nht
*/
- if (up)
- pim_rpf_update(vxlan_sg->pim, up, NULL, __func__);
+ if (up) {
+ enum pim_rpf_result r;
+
+ r = pim_rpf_update(vxlan_sg->pim, up, NULL, __func__);
+ if (r == PIM_RPF_FAILURE) {
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug(
+ "vxlan SG %s rpf_update failure",
+ vxlan_sg->sg_str);
+ }
+ }
}
}
@@ -788,8 +797,8 @@ void pim_vxlan_sg_del(struct pim_instance *pim, struct prefix_sg *sg)
if (!vxlan_sg)
return;
- pim_vxlan_sg_del_item(vxlan_sg);
hash_release(pim->vxlan.sg_hash, vxlan_sg);
+ pim_vxlan_sg_del_item(vxlan_sg);
}
/******************************* MLAG handling *******************************/
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index e791500ed..8355c2099 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -835,7 +835,7 @@ void igmp_source_forward_stop(struct igmp_source *source)
void pim_forward_start(struct pim_ifchannel *ch)
{
struct pim_upstream *up = ch->upstream;
- uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
+ uint32_t mask = 0;
if (PIM_DEBUG_PIM_TRACE) {
char source_str[INET_ADDRSTRLEN];
@@ -853,9 +853,12 @@ void pim_forward_start(struct pim_ifchannel *ch)
inet_ntoa(up->upstream_addr));
}
- if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+ if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
mask = PIM_OIF_FLAG_PROTO_IGMP;
+ if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+ mask |= PIM_OIF_FLAG_PROTO_PIM;
+
pim_channel_add_oif(up->channel_oil, ch->interface,
mask, __func__);
}
diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c
index 55dafd7c1..77c73ab39 100644
--- a/ripd/rip_peer.c
+++ b/ripd/rip_peer.c
@@ -131,7 +131,6 @@ void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from)
static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
{
time_t uptime;
- struct tm tm;
/* If there is no connection has been done before print `never'. */
if (peer->uptime == 0) {
@@ -142,17 +141,9 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len)
/* Get current time. */
uptime = time(NULL);
uptime -= peer->uptime;
- gmtime_r(&uptime, &tm);
-
- if (uptime < ONE_DAY_SECOND)
- snprintf(buf, len, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- snprintf(buf, len, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- snprintf(buf, len, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
+
+ frrtime_to_interval(uptime, buf, len);
+
return buf;
}
diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c
index c038bfccf..e6ff58dd0 100644
--- a/ripngd/ripng_peer.c
+++ b/ripngd/ripng_peer.c
@@ -141,7 +141,6 @@ void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from)
static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
{
time_t uptime;
- struct tm tm;
/* If there is no connection has been done before print `never'. */
if (peer->uptime == 0) {
@@ -152,17 +151,9 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
/* Get current time. */
uptime = time(NULL);
uptime -= peer->uptime;
- gmtime_r(&uptime, &tm);
-
- if (uptime < ONE_DAY_SECOND)
- snprintf(buf, len, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- snprintf(buf, len, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- snprintf(buf, len, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
+
+ frrtime_to_interval(uptime, buf, len);
+
return buf;
}
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 486ccf6bf..fd2e37e67 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -337,11 +337,129 @@ DEFUN_NOSH (show_debugging_sharpd,
DEBUG_STR
"Sharp Information\n")
{
- vty_out(vty, "Sharp debugging status\n");
+ vty_out(vty, "Sharp debugging status:\n");
return CMD_SUCCESS;
}
+DEFPY(sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
+ "sharp lsp (0-100000)$inlabel\
+ nexthop-group NHGNAME$nhgname\
+ [prefix A.B.C.D/M$pfx\
+ " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
+ "Sharp Routing Protocol\n"
+ "Add an LSP\n"
+ "The ingress label to use\n"
+ "Use nexthops from a nexthop-group\n"
+ "The nexthop-group name\n"
+ "Label a prefix\n"
+ "The v4 prefix to label\n"
+ FRR_IP_REDIST_HELP_STR_SHARPD
+ "Instance to use\n"
+ "Instance\n")
+{
+ struct nexthop_group_cmd *nhgc = NULL;
+ struct prefix p = {};
+ int type = 0;
+
+ /* We're offered a v4 prefix */
+ if (pfx->family > 0 && type_str) {
+ p.family = pfx->family;
+ p.prefixlen = pfx->prefixlen;
+ p.u.prefix4 = pfx->prefix;
+
+ type = proto_redistnum(AFI_IP, type_str);
+ if (type < 0) {
+ vty_out(vty, "%% Unknown route type '%s'\n", type_str);
+ return CMD_WARNING;
+ }
+ } else if (pfx->family > 0 || type_str) {
+ vty_out(vty, "%% Must supply both prefix and type\n");
+ return CMD_WARNING;
+ }
+
+ nhgc = nhgc_find(nhgname);
+ if (!nhgc) {
+ vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
+ nhgname);
+ return CMD_WARNING;
+ }
+
+ if (nhgc->nhg.nexthop == NULL) {
+ vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
+ return CMD_WARNING;
+ }
+
+ if (sharp_install_lsps_helper(true, pfx->family > 0 ? &p : NULL,
+ type, instance, inlabel,
+ &(nhgc->nhg)) == 0)
+ return CMD_SUCCESS;
+ else {
+ vty_out(vty, "%% LSP install failed!\n");
+ return CMD_WARNING;
+ }
+}
+
+DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
+ "sharp remove lsp \
+ (0-100000)$inlabel\
+ nexthop-group NHGNAME$nhgname\
+ [prefix A.B.C.D/M$pfx\
+ " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
+ "Sharp Routing Protocol\n"
+ "Remove data\n"
+ "Remove an LSP\n"
+ "The ingress label\n"
+ "Use nexthops from a nexthop-group\n"
+ "The nexthop-group name\n"
+ "Specify a v4 prefix\n"
+ "The v4 prefix to label\n"
+ FRR_IP_REDIST_HELP_STR_SHARPD
+ "Routing instance\n"
+ "Instance to use\n")
+{
+ struct nexthop_group_cmd *nhgc = NULL;
+ struct prefix p = {};
+ int type = 0;
+
+ /* We're offered a v4 prefix */
+ if (pfx->family > 0 && type_str) {
+ p.family = pfx->family;
+ p.prefixlen = pfx->prefixlen;
+ p.u.prefix4 = pfx->prefix;
+
+ type = proto_redistnum(AFI_IP, type_str);
+ if (type < 0) {
+ vty_out(vty, "%% Unknown route type '%s'\n", type_str);
+ return CMD_WARNING;
+ }
+ } else if (pfx->family > 0 || type_str) {
+ vty_out(vty, "%% Must supply both prefix and type\n");
+ return CMD_WARNING;
+ }
+
+ nhgc = nhgc_find(nhgname);
+ if (!nhgc) {
+ vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
+ nhgname);
+ return CMD_WARNING;
+ }
+
+ if (nhgc->nhg.nexthop == NULL) {
+ vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
+ return CMD_WARNING;
+ }
+
+ if (sharp_install_lsps_helper(false, pfx->family > 0 ? &p : NULL,
+ type, instance, inlabel,
+ &(nhgc->nhg)) == 0)
+ return CMD_SUCCESS;
+ else {
+ vty_out(vty, "%% LSP remove failed!\n");
+ return CMD_WARNING;
+ }
+}
+
void sharp_vty_init(void)
{
install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
@@ -351,6 +469,8 @@ void sharp_vty_init(void)
install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
+ install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
+ install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
install_element(VIEW_NODE, &show_debugging_sharpd_cmd);
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 5baa74fe9..882e73f87 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -87,6 +87,61 @@ static int sharp_ifp_down(struct interface *ifp)
return 0;
}
+int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
+ uint8_t type, int instance, uint32_t in_label,
+ const struct nexthop_group *nhg)
+{
+ struct zapi_labels zl = {};
+ struct zapi_nexthop *znh;
+ const struct nexthop *nh;
+ int i, ret;
+
+ zl.type = ZEBRA_LSP_SHARP;
+ zl.local_label = in_label;
+
+ if (p) {
+ SET_FLAG(zl.message, ZAPI_LABELS_FTN);
+ prefix_copy(&zl.route.prefix, p);
+ zl.route.type = type;
+ zl.route.instance = instance;
+ }
+
+ i = 0;
+ for (ALL_NEXTHOPS_PTR(nhg, nh)) {
+ znh = &zl.nexthops[i];
+
+ /* Must have labels to be useful */
+ if (nh->nh_label == NULL || nh->nh_label->num_labels == 0)
+ continue;
+
+ if (nh->type == NEXTHOP_TYPE_IFINDEX ||
+ nh->type == NEXTHOP_TYPE_BLACKHOLE)
+ /* Hmm - can't really deal with these types */
+ continue;
+
+ ret = zapi_nexthop_from_nexthop(znh, nh);
+ if (ret < 0)
+ return -1;
+
+ i++;
+ }
+
+ /* Whoops - no nexthops isn't very useful */
+ if (i == 0)
+ return -1;
+
+ zl.nexthop_num = i;
+
+ if (install_p)
+ ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_ADD,
+ &zl);
+ else
+ ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE,
+ &zl);
+
+ return ret;
+}
+
void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
uint8_t instance, struct nexthop_group *nhg,
uint32_t routes)
@@ -241,43 +296,8 @@ void route_add(struct prefix *p, vrf_id_t vrf_id,
for (ALL_NEXTHOPS_PTR(nhg, nh)) {
api_nh = &api.nexthops[i];
- api_nh->vrf_id = nh->vrf_id;
- api_nh->type = nh->type;
- api_nh->weight = nh->weight;
-
- switch (nh->type) {
- case NEXTHOP_TYPE_IPV4:
- api_nh->gate = nh->gate;
- break;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- api_nh->gate = nh->gate;
- api_nh->ifindex = nh->ifindex;
- break;
- case NEXTHOP_TYPE_IFINDEX:
- api_nh->ifindex = nh->ifindex;
- break;
- case NEXTHOP_TYPE_IPV6:
- memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16);
- break;
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- api_nh->ifindex = nh->ifindex;
- memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16);
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- api_nh->bh_type = nh->bh_type;
- break;
- }
-
- if (nh->nh_label && nh->nh_label->num_labels > 0) {
- int j;
-
- SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
-
- api_nh->label_num = nh->nh_label->num_labels;
- for (j = 0; j < nh->nh_label->num_labels; j++)
- api_nh->labels[j] = nh->nh_label->label[j];
- }
+ zapi_nexthop_from_nexthop(api_nh, nh);
i++;
}
api.nexthop_num = i;
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index 57ffcc769..c995d557a 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -37,4 +37,8 @@ extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
uint32_t routes);
extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
uint8_t instance, uint32_t routes);
+
+int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
+ uint8_t type, int instance, uint32_t in_label,
+ const struct nexthop_group *nhg);
#endif
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 40bcf2b5d..a950b0473 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -867,7 +867,7 @@ DEFPY(ip_route_address_interface,
"Table to configure\n"
"The table number to configure\n"
VRF_CMD_HELP_STR
- "Treat the nexthop as directly attached to the interface")
+ "Treat the nexthop as directly attached to the interface\n")
{
struct static_vrf *svrf;
struct static_vrf *nh_svrf;
@@ -935,7 +935,7 @@ DEFPY(ip_route_address_interface_vrf,
"Table to configure\n"
"The table number to configure\n"
VRF_CMD_HELP_STR
- "Treat the nexthop as directly attached to the interface")
+ "Treat the nexthop as directly attached to the interface\n")
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
const char *flag = NULL;
@@ -1211,7 +1211,7 @@ DEFPY(ipv6_route_address_interface,
"Table to configure\n"
"The table number to configure\n"
VRF_CMD_HELP_STR
- "Treat the nexthop as directly attached to the interface")
+ "Treat the nexthop as directly attached to the interface\n")
{
struct static_vrf *svrf;
struct static_vrf *nh_svrf;
@@ -1279,7 +1279,7 @@ DEFPY(ipv6_route_address_interface_vrf,
"Table to configure\n"
"The table number to configure\n"
VRF_CMD_HELP_STR
- "Treat the nexthop as directly attached to the interface")
+ "Treat the nexthop as directly attached to the interface\n")
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct static_vrf *svrf = vrf->info;
diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c
index 9feec7156..b94355e8b 100644
--- a/tests/bgpd/test_aspath.c
+++ b/tests/bgpd/test_aspath.c
@@ -474,6 +474,20 @@ static struct test_segment {
14,
{NULL, NULL, 0, 0, 0, 0, 0, 0},
},
+ {
+ /* 28 */
+ "BGP_AS_ZERO",
+ "seq(8466,3,52737,0,4096)",
+ {0x2, 0x5,
+ 0x21, 0x12,
+ 0x00, 0x03,
+ 0xce, 0x01,
+ 0x00, 0x00,
+ 0x10, 0x00},
+ 12,
+ {"8466 3 52737 0 4096", "8466 3 52737 0 4096", 5, 0,
+ NOT_ALL_PRIVATE, 4096, 4, 8466},
+ },
{NULL, NULL, {0}, 0, {NULL, 0, 0}}};
#define COMMON_ATTRS \
@@ -678,6 +692,21 @@ static struct aspath_tests {
COMMON_ATTR_SIZE + 3,
&test_segments[0],
},
+ /* 13 */
+ {
+ "4b AS4_PATH: BGP_AS_ZERO",
+ &test_segments[28],
+ "8466 3 52737 0 4096",
+ AS4_DATA,
+ -1,
+ PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV,
+ {
+ COMMON_ATTRS,
+ BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
+ BGP_ATTR_AS4_PATH, 22,
+ },
+ COMMON_ATTR_SIZE + 3,
+ },
{NULL, NULL, NULL, 0, 0, 0, {0}, 0},
};
diff --git a/tests/bgpd/test_aspath.py b/tests/bgpd/test_aspath.py
index 15ae514c8..5fa1f1162 100644
--- a/tests/bgpd/test_aspath.py
+++ b/tests/bgpd/test_aspath.py
@@ -52,6 +52,7 @@ TestAspath.parsertest("redundantset2")
TestAspath.parsertest("zero-size overflow")
TestAspath.parsertest("zero-size overflow + valid segment")
TestAspath.parsertest("invalid segment type")
+TestAspath.parsertest("BGP_AS_ZERO")
for i in range(10):
TestAspath.okfail("prepend test %d" % i)
@@ -77,3 +78,4 @@ TestAspath.attrtest("4b AS_PATH: too long2")
TestAspath.attrtest("4b AS_PATH: bad flags")
TestAspath.attrtest("4b AS4_PATH w/o AS_PATH")
TestAspath.attrtest("4b AS4_PATH: confed")
+TestAspath.attrtest("4b AS4_PATH: BGP_AS_ZERO")
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index c97ea5715..7fabaad7f 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -951,12 +951,19 @@ static struct test_segment mp_prefix_sid[] = {
"PREFIX-SID",
"PREFIX-SID Test 1",
{
- 0x01, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02,
- 0x03, 0x00, 0x08, 0x00,
- 0x00, 0x0a, 0x1b, 0xfe,
- 0x00, 0x00, 0x0a
+ /* TLV[0] Latel-Index TLV */
+ 0x01, /* Type 0x01:Label-Index */
+ 0x00, 0x07, /* Length */
+ 0x00, /* RESERVED */
+ 0x00, 0x00, /* Flags */
+ 0x00, 0x00, 0x00, 0x02, /* Label Index */
+
+ /* TLV[1] SRGB TLV */
+ 0x03, /* Type 0x03:SRGB */
+ 0x00, 0x08, /* Length */
+ 0x00, 0x00, /* Flags */
+ 0x0a, 0x1b, 0xfe, /* SRGB[0] first label */
+ 0x00, 0x00, 0x0a /* SRBG[0] nb-labels in range */
},
.len = 21,
.parses = SHOULD_PARSE,
@@ -1027,7 +1034,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
break;
case BGP_ATTR_PREFIX_SID:
- parse_ret = bgp_attr_prefix_sid(&attr_args, &nlri);
+ parse_ret = bgp_attr_prefix_sid(&attr_args);
break;
default:
printf("unknown type");
diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
index 46e45e5ee..4f59d1d7c 100644
--- a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+++ b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
Binary files differ
diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
index 16609221c..a671e14e0 100755
--- a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
+++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
@@ -307,7 +307,7 @@ def test_converge_protocols():
expected = open(v4_routesFile).read().rstrip()
expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
- actual = net['r%s' %i].cmd('vtysh -c "show ip route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip()
+ actual = net['r%s' %i].cmd('vtysh -c "show ip route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null').rstrip()
# Drop time in last update
actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
@@ -329,7 +329,7 @@ def test_converge_protocols():
expected = open(v6_routesFile).read().rstrip()
expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
- actual = net['r%s' %i].cmd('vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip()
+ actual = net['r%s' %i].cmd('vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null').rstrip()
# Drop time in last update
actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py
index 59858d6fd..e2bd80daa 100755
--- a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py
+++ b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py
@@ -142,7 +142,7 @@ def test_bfd_connection():
test_func = partial(topotest.router_json_cmp,
router, 'show bfd peers json', expected)
- _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=16, wait=0.5)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
@@ -173,7 +173,7 @@ def test_bfd_loss_intermediate():
test_func = partial(topotest.router_json_cmp,
router, 'show bfd peers json', expected)
- _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=16, wait=0.5)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
@@ -229,7 +229,7 @@ def test_bfd_comes_back_again():
test_func = partial(topotest.router_json_cmp,
router, 'show bfd peers json', expected)
- _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=16, wait=0.5)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
diff --git a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
index e99111d90..43639a81d 100755
--- a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
+++ b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
@@ -79,6 +79,9 @@ try:
except IOError:
assert False, "Could not read file {}".format(jsonFile)
+#Global Variable
+KEEPALIVETIMER = 2
+HOLDDOWNTIMER = 6
class CreateTopo(Topo):
"""
@@ -292,8 +295,8 @@ def test_bgp_timers_functionality(request):
"r2": {
"dest_link":{
"r1": {
- "keepalivetimer": 60,
- "holddowntimer": 180,
+ "keepalivetimer": KEEPALIVETIMER,
+ "holddowntimer": HOLDDOWNTIMER
}
}
}
@@ -319,8 +322,6 @@ def test_bgp_timers_functionality(request):
write_test_footer(tc_name)
-
-
def test_static_routes(request):
""" Test to create and verify static routes. """
diff --git a/tests/topotests/bgp_prefix_sid/__init__.py b/tests/topotests/bgp_prefix_sid/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/__init__.py
diff --git a/tests/topotests/bgp_prefix_sid/exabgp.env b/tests/topotests/bgp_prefix_sid/exabgp.env
new file mode 100644
index 000000000..6c554f5fa
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/exabgp.env
@@ -0,0 +1,53 @@
+
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg b/tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg
new file mode 100644
index 000000000..5b55366a0
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg
@@ -0,0 +1,103 @@
+group controller {
+ neighbor 10.0.0.1 {
+ router-id 10.0.0.101;
+ local-address 10.0.0.101;
+ local-as 2;
+ peer-as 1;
+
+ family {
+ ipv4 nlri-mpls;
+ }
+
+ static {
+ # ref: draft-ietf-idr-bgp-prefix-sid-27
+ #
+ # IANA temporarily assigned the following:
+ # attribute code type (suggested value: 40) to
+ # the BGP Prefix-SID attribute
+ #
+ # 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
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Type | Length | RESERVED |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Flags | Label Index |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Label Index |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # Figure. Label-Index TLV (Prefix-SID type-1)
+ #
+ # 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
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Type | Length | Flags |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Flags |
+ # +-+-+-+-+-+-+-+-+
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | SRGB 1 (6 octets) |
+ # | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | SRGB n (6 octets) |
+ # | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<Paste>
+ # Figure. Originator SRGB TLV (Prefix-SID type-3)
+
+ # ExaBGP generic-attribute binary pattern:
+ # Attribute-type: 0x28 (40:BGP_PREFIX_SID)
+ # Attribute-flag: 0xc0 (Option, Transitive)
+ # Attribute-body: Label-Index TLV and Originator SRGB TLV
+ # Label-Index TLV: 0x01000700000000000001
+ # Type (08bit): 0x01
+ # Length (16bit): 0x0007
+ # RESERVED (08bit): 0x00
+ # Flags (16bit): 0x0000
+ # Label Index (32bit): 0x00000001
+ # Originator SRGB TLV: 0x03000800000c350000000a
+ # Type (08bit): 0x03
+ # Length (16bit): 0x0008 (nb-SRGB is 1)
+ # Flags (16bit): 0x0000
+ # SRGB1 (48bit): 0x0c3500:0x00000a (800000-800010 is SRGB1)
+ route 3.0.0.1/32 next-hop 10.0.0.101 label [800001] attribute [0x28 0xc0 0x0100070000000000000103000800000c350000000a];
+
+ # ExaBGP generic-attribute binary pattern:
+ # Attribute-type: 0x28 (40:BGP_PREFIX_SID)
+ # Attribute-flag: 0xc0 (Option, Transitive)
+ # Attribute-body: Label-Index TLV and Originator SRGB TLV
+ # Label-Index TLV: 0x01000700000000000001
+ # Type (08bit): 0x01
+ # Length (16bit): 0x0007
+ # RESERVED (08bit): 0x00
+ # Flags (16bit): 0x0000
+ # Label Index (32bit): 0x00000002
+ # Originator SRGB TLV: 0x03000800000c350000000a
+ # Type (08bit): 0x03
+ # Length (16bit): 0x0008 (nb-SRGB is 1)
+ # Flags (16bit): 0x0000
+ # SRGB1 (48bit): 0x0c3500:0x00000a (800000-800010 is SRGB1)
+ route 3.0.0.2/32 next-hop 10.0.0.101 label [800002] attribute [0x28 0xc0 0x0100070000000000000203000800000c350000000a];
+
+ # ExaBGP generic-attribute binary pattern:
+ # Attribute-type: 0x28 (40:BGP_PREFIX_SID)
+ # Attribute-flag: 0xc0 (Option, Transitive)
+ # Attribute-body: Label-Index TLV and Originator SRGB TLV
+ # Label-Index TLV: 0x01000700000000000001
+ # Type (08bit): 0x01
+ # Length (16bit): 0x0007
+ # RESERVED (08bit): 0x00
+ # Flags (16bit): 0x0000
+ # Label Index (32bit): 0x00000003
+ # Originator SRGB TLV: 0x03000800000c350000000a
+ # Type (08bit): 0x03
+ # Length (16bit): 0x0008 (nb-SRGB is 1)
+ # Flags (16bit): 0x0000
+ # SRGB1 (48bit): 0x0c3500:0x00000a (800000-800010 is SRGB1)
+ route 3.0.0.3/32 next-hop 10.0.0.101 label [800003] attribute [0x28 0xc0 0x0100070000000000000303000800000c350000000a];
+ }
+ }
+}
diff --git a/tests/topotests/bgp_prefix_sid/peer2/exa-receive.py b/tests/topotests/bgp_prefix_sid/peer2/exa-receive.py
new file mode 100755
index 000000000..eaa6a6787
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/peer2/exa-receive.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+ try:
+ line = stdin.readline()
+ routesavefile.write(line)
+ routesavefile.flush()
+
+ if line == "":
+ counter += 1
+ if counter > 100:
+ break
+ continue
+
+ counter = 0
+ except KeyboardInterrupt:
+ pass
+ except IOError:
+ # most likely a signal during readline
+ pass
+
+routesavefile.close()
diff --git a/tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg b/tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg
new file mode 100644
index 000000000..dabd88e03
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg
@@ -0,0 +1,19 @@
+group controller {
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 2";
+ receive-routes;
+ encoder json;
+ }
+
+ neighbor 10.0.0.1 {
+ router-id 10.0.0.102;
+ local-address 10.0.0.102;
+ local-as 3;
+ peer-as 1;
+
+ family {
+ ipv4 nlri-mpls;
+ }
+ }
+}
diff --git a/tests/topotests/bgp_prefix_sid/r1/bgpd.conf b/tests/topotests/bgp_prefix_sid/r1/bgpd.conf
new file mode 100644
index 000000000..7a38cc307
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/r1/bgpd.conf
@@ -0,0 +1,15 @@
+log stdout notifications
+log monitor notifications
+log commands
+!
+router bgp 1
+ bgp router-id 10.0.0.1
+ no bgp default ipv4-unicast
+ neighbor 10.0.0.101 remote-as 2
+ neighbor 10.0.0.102 remote-as 3
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 10.0.0.101 activate
+ neighbor 10.0.0.102 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_prefix_sid/r1/zebra.conf b/tests/topotests/bgp_prefix_sid/r1/zebra.conf
new file mode 100644
index 000000000..0cd26052f
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/r1/zebra.conf
@@ -0,0 +1,7 @@
+hostname r1
+!
+interface r1-eth0
+ ip address 10.0.0.1/24
+ no shutdown
+!
+line vty
diff --git a/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py b/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py
new file mode 100755
index 000000000..dc203cabc
--- /dev/null
+++ b/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_prefix_sid.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by LINE Corporation
+# Copyright (c) 2020 by Hiroki Shirokura <slank.dev@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_bgp_prefix_sid.py: Test BGP topology with EBGP on prefix-sid
+"""
+
+import json
+import os
+import sys
+import functools
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+ def build(self, **_opts):
+ tgen = get_topogen(self)
+ router = tgen.add_router('r1')
+ switch = tgen.add_switch('s1')
+ switch.add_link(router)
+
+ switch = tgen.gears['s1']
+ peer1 = tgen.add_exabgp_peer('peer1', ip='10.0.0.101', defaultRoute='via 10.0.0.1')
+ peer2 = tgen.add_exabgp_peer('peer2', ip='10.0.0.102', defaultRoute='via 10.0.0.1')
+ switch.add_link(peer1)
+ switch.add_link(peer2)
+
+
+def setup_module(module):
+ tgen = Topogen(TemplateTopo, module.__name__)
+ tgen.start_topology()
+
+ router = tgen.gears['r1']
+ router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, '{}/zebra.conf'.format('r1')))
+ router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, '{}/bgpd.conf'.format('r1')))
+ router.start()
+
+ logger.info('starting exaBGP on peer1')
+ peer_list = tgen.exabgp_peers()
+ for pname, peer in peer_list.iteritems():
+ peer_dir = os.path.join(CWD, pname)
+ env_file = os.path.join(CWD, 'exabgp.env')
+ logger.info('Running ExaBGP peer')
+ peer.start(peer_dir, env_file)
+ logger.info(pname)
+
+
+def teardown_module(module):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_r1_receive_and_advertise_prefix_sid_type1():
+ tgen = get_topogen()
+ router = tgen.gears['r1']
+
+ def _check_type1_r1(router, prefix, remoteLabel, labelIndex):
+ output = router.vtysh_cmd('show bgp ipv4 labeled-unicast {} json'.format(prefix))
+ output = json.loads(output)
+ expected = {
+ 'prefix': prefix,
+ 'advertisedTo': { '10.0.0.101':{}, '10.0.0.102':{} },
+ 'paths': [{
+ 'valid':True,
+ 'remoteLabel': remoteLabel,
+ 'labelIndex': labelIndex,
+ }]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_check_type1_r1, router, '3.0.0.1/32', 800001, 1)
+ success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result is None, 'Failed _check_type1_r1 in "{}"'.format(router)
+
+ test_func = functools.partial(_check_type1_r1, router, '3.0.0.2/32', 800002, 2)
+ success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result is None, 'Failed _check_type1_r1 in "{}"'.format(router)
+
+
+def exabgp_get_update_prefix(filename, afi, nexthop, prefix):
+ with open('/tmp/peer2-received.log') as f:
+ for line in f.readlines():
+ output = json.loads(line)
+ ret = output.get('neighbor')
+ if ret is None:
+ continue
+ ret = ret.get('message')
+ if ret is None:
+ continue
+ ret = ret.get('update')
+ if ret is None:
+ continue
+ ret = ret.get('announce')
+ if ret is None:
+ continue
+ ret = ret.get(afi)
+ if ret is None:
+ continue
+ ret = ret.get(nexthop)
+ if ret is None:
+ continue
+ ret = ret.get(prefix)
+ if ret is None:
+ continue
+ return output
+ return "Not found"
+
+
+def test_peer2_receive_prefix_sid_type1():
+ tgen = get_topogen()
+ peer2 = tgen.gears['peer2']
+
+ def _check_type1_peer2(prefix, labelindex):
+ output = exabgp_get_update_prefix('/tmp/peer2-received.log', 'ipv4 nlri-mpls', '10.0.0.101', prefix)
+ expected = {
+ 'type': 'update',
+ 'neighbor': {
+ 'ip': '10.0.0.1',
+ 'message': {
+ 'update': {
+ 'attribute': {
+ 'attribute-0x28-0xE0': '0x010007000000{:08x}'.format(labelindex)
+ },
+ 'announce': { 'ipv4 nlri-mpls': { '10.0.0.101': {} } }
+ }
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_check_type1_peer2, '3.0.0.1/32', labelindex=1)
+ success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result is None, 'Failed _check_type1_peer2 in "{}"'.format('peer2')
+
+ test_func = functools.partial(_check_type1_peer2, '3.0.0.2/32', labelindex=2)
+ success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result is None, 'Failed _check_type1_peer2 in "{}"'.format('peer2')
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ ret = pytest.main(args)
+ sys.exit(ret)
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r1/ldpd.conf
new file mode 100644
index 000000000..85bb970fd
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/ldpd.conf
@@ -0,0 +1,25 @@
+hostname r1
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 1.1.1.1
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 1.1.1.1
+ label local allocate host-routes
+ !
+ interface r1-eth0
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf
new file mode 100644
index 000000000..6daf034d1
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf
@@ -0,0 +1,7 @@
+hostname r1
+log file ospfd.log
+!
+router ospf
+ router-id 1.1.1.1
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..2c493173f
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json
@@ -0,0 +1,12 @@
+{
+ "neighbors":{
+ "2.2.2.2":[
+ {
+ "priority":1,
+ "state":"Full\/DR",
+ "address":"10.0.1.2",
+ "ifaceName":"r1-eth0:10.0.1.1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref
new file mode 100644
index 000000000..d75b8f21d
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref
@@ -0,0 +1,171 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0/24":[
+ {
+ "prefix":"10.0.1.0/24",
+ "protocol":"ospf",
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0/24":[
+ {
+ "prefix":"10.0.2.0/24",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0/24":[
+ {
+ "prefix":"10.0.3.0/24",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0/24":[
+ {
+ "prefix":"123.0.1.0/24",
+ "protocol":"ospf",
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"123.0.1.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref
new file mode 100644
index 000000000..ccc841364
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref
@@ -0,0 +1,55 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"2.2.2.2",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"2.2.2.2",
+ "localLabel":"-",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"2.2.2.2",
+ "localLabel":"-",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"2.2.2.2",
+ "localLabel":"-",
+ "inUse":1
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref
new file mode 100644
index 000000000..b349f4418
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref
@@ -0,0 +1,11 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"link",
+ "interface":"r1-eth0",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref
new file mode 100644
index 000000000..4bff444a4
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref
@@ -0,0 +1,10 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "state":"OPERATIONAL",
+ "transportAddress":"2.2.2.2"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf
new file mode 100644
index 000000000..83aea46e6
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf
@@ -0,0 +1,17 @@
+log file zebra.log
+!
+hostname r1
+!
+interface lo
+ ip address 1.1.1.1/32
+!
+interface r1-eth0
+ description to sw0
+ ip address 10.0.1.1/24
+ ip address 123.0.1.1/24
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf
new file mode 100644
index 000000000..e1a552c70
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf
@@ -0,0 +1,28 @@
+hostname r2
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 2.2.2.2
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 2.2.2.2
+ !
+ interface r2-eth0
+ !
+ interface r2-eth1
+ !
+ interface r2-eth2
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf
new file mode 100644
index 000000000..867881366
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf
@@ -0,0 +1,7 @@
+hostname r2
+log file ospfd.log
+!
+router ospf
+ router-id 2.2.2.2
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..55f12359e
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json
@@ -0,0 +1,31 @@
+{
+ "neighbors":{
+ "1.1.1.1":[
+ {
+ "priority":1,
+ "state":"Full\/Backup",
+ "address":"10.0.1.1",
+ "ifaceName":"r2-eth0:10.0.1.2",
+ "retransmitCounter":0,
+ "requestCounter":0,
+ "dbSummaryCounter":0
+ }
+ ],
+ "3.3.3.3":[
+ {
+ "priority":1,
+ "state":"Full\/Backup",
+ "address":"10.0.2.3",
+ "ifaceName":"r2-eth1:10.0.2.2"
+ }
+ ],
+ "4.4.4.4":[
+ {
+ "priority":1,
+ "state":"Full\/DR",
+ "address":"10.0.2.4",
+ "ifaceName":"r2-eth1:10.0.2.2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref
new file mode 100644
index 000000000..060c0b429
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref
@@ -0,0 +1,209 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0\/24":[
+ {
+ "prefix":"123.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref
new file mode 100644
index 000000000..ea32de3ed
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref
@@ -0,0 +1,63 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"1.1.1.1",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"3.3.3.3",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"3.3.3.3",
+ "localLabel":"imp-null",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"3.3.3.3",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref
new file mode 100644
index 000000000..812957008
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref
@@ -0,0 +1,18 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "type":"link",
+ "interface":"r2-eth0",
+ "helloHoldtime":15
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "type":"link",
+ "interface":"r2-eth1",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref
new file mode 100644
index 000000000..eed35289e
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref
@@ -0,0 +1,16 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "state":"OPERATIONAL",
+ "transportAddress":"1.1.1.1"
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "state":"OPERATIONAL",
+ "transportAddress":"3.3.3.3"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf
new file mode 100644
index 000000000..1f1e3e391
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf
@@ -0,0 +1,27 @@
+log file zebra.log
+!
+hostname r2
+!
+interface lo
+ ip address 2.2.2.2/32
+!
+interface r2-eth0
+ description to sw0
+ ip address 10.0.1.2/24
+! no link-detect
+!
+interface r2-eth1
+ description to sw1
+ ip address 10.0.2.2/24
+! no link-detect
+!
+interface r2-eths2
+ description to sw2
+ ip address 10.0.3.2/24
+! no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf
new file mode 100644
index 000000000..4e66b140a
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf
@@ -0,0 +1,24 @@
+hostname r3
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 3.3.3.3
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 3.3.3.3
+ !
+ interface r3-eth0
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf
new file mode 100644
index 000000000..202be238e
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf
@@ -0,0 +1,8 @@
+hostname r3
+password 1
+log file ospfd.log
+!
+router ospf
+ router-id 3.3.3.3
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..24502ed81
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json
@@ -0,0 +1,20 @@
+{
+ "neighbors":{
+ "2.2.2.2":[
+ {
+ "priority":1,
+ "state":"Full\/DROther",
+ "address":"10.0.2.2",
+ "ifaceName":"r3-eth0:10.0.2.3"
+ }
+ ],
+ "4.4.4.4":[
+ {
+ "priority":1,
+ "state":"Full\/DR",
+ "address":"10.0.2.4",
+ "ifaceName":"r3-eth0:10.0.2.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref
new file mode 100644
index 000000000..40800762b
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref
@@ -0,0 +1,209 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0\/24":[
+ {
+ "prefix":"123.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref
new file mode 100644
index 000000000..bb1b2b302
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref
@@ -0,0 +1,62 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"2.2.2.2",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"2.2.2.2",
+ "localLabel":"imp-null",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref
new file mode 100644
index 000000000..c3a07e7e3
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref
@@ -0,0 +1,11 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"link",
+ "interface":"r3-eth0",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref
new file mode 100644
index 000000000..4bff444a4
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref
@@ -0,0 +1,10 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "state":"OPERATIONAL",
+ "transportAddress":"2.2.2.2"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf
new file mode 100644
index 000000000..234c215dd
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf
@@ -0,0 +1,22 @@
+log file zebra.log
+!
+hostname r3
+!
+interface lo
+ ip address 3.3.3.3/32
+!
+interface r3-eth0
+ description to sw1
+ ip address 10.0.2.3/24
+! no link-detect
+!
+interface r3-eth1
+ description to sw2
+ ip address 10.0.3.3/24
+! no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf
new file mode 100644
index 000000000..6b7d28f98
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf
@@ -0,0 +1,24 @@
+hostname r4
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 4.4.4.4
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 4.4.4.4
+ !
+ !interface r4-eth0
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf
new file mode 100644
index 000000000..569dbc54e
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf
@@ -0,0 +1,7 @@
+hostname r4
+log file ospfd.log
+!
+router ospf
+ router-id 4.4.4.4
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..794410522
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json
@@ -0,0 +1,21 @@
+
+{
+ "neighbors":{
+ "2.2.2.2":[
+ {
+ "priority":1,
+ "state":"Full\/DROther",
+ "address":"10.0.2.2",
+ "ifaceName":"r4-eth0:10.0.2.4"
+ }
+ ],
+ "3.3.3.3":[
+ {
+ "priority":1,
+ "state":"Full\/Backup",
+ "address":"10.0.2.3",
+ "ifaceName":"r4-eth0:10.0.2.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref
new file mode 100644
index 000000000..c9b83a1c7
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref
@@ -0,0 +1,196 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0\/24":[
+ {
+ "prefix":"123.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref
new file mode 100644
index 000000000..2a46c4034
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref
@@ -0,0 +1,68 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf
new file mode 100644
index 000000000..7e291053e
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf
@@ -0,0 +1,17 @@
+log file zebra.log
+!
+hostname r4
+!
+interface lo
+ ip address 4.4.4.4/32
+!
+interface r4-eth0
+ description to sw1
+ ip address 10.0.2.4/24
+! no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot
new file mode 100644
index 000000000..62058e3cb
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot
@@ -0,0 +1,76 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="Test Topology - LDP-OC 1";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r4 [
+ shape=doubleoctagon
+ label="r4",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+
+ # Switches
+ s0 [
+ shape=oval,
+ label="10.0.1.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s1 [
+ shape=oval,
+ label="10.0.2.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s2 [
+ shape=oval,
+ label="10.0.3.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+
+ r1 -- s0 [label="eth0"];
+ r2 -- s0 [label="eth0"];
+
+ r2 -- s1 [label="eth1"];
+ r3 -- s1 [label="eth0"];
+ r4 -- s1 [label="eth0"];
+
+ r2 -- s2 [label="eth2"];
+ r3 -- s2 [label="eth1"];
+}
diff --git a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py
new file mode 100755
index 000000000..47b32a16e
--- /dev/null
+++ b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+
+#
+# test_ldp_oc_acl_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by Volta Networks
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ldp_oc_acl_topo1.py: Simple FRR/Quagga LDP Test
+
+ +---------+
+ | r1 |
+ | 1.1.1.1 |
+ +----+----+
+ | .1 r1-eth0
+ |
+ ~~~~~~~~~~~~~
+ ~~ sw0 ~~
+ ~~ 10.0.1.0/24 ~~
+ ~~~~~~~~~~~~~
+ |10.0.1.0/24
+ |
+ | .2 r2-eth0
+ +----+----+
+ | r2 |
+ | 2.2.2.2 |
+ +--+---+--+
+ r2-eth2 .2 | | .2 r2-eth1
+ ______/ \______
+ / \
+ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
+~~ sw2 ~~ ~~ sw1 ~~
+~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~
+ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
+ | / |
+ \ _________/ |
+ \ / \
+r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
+ +----+--+---+ +----+----+
+ | r3 | | r4 |
+ | 3.3.3.3 | | 4.4.4.4 |
+ +-----------+ +---------+
+"""
+
+import os
+import sys
+import pytest
+import json
+from time import sleep
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+class TemplateTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ #
+ # Define FRR Routers
+ #
+ for router in ['r1', 'r2', 'r3', 'r4']:
+ tgen.add_router(router)
+
+ #
+ # Define connections
+ #
+ switch = tgen.add_switch('s0')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r3'])
+ switch.add_link(tgen.gears['r4'])
+
+ switch = tgen.add_switch('s2')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r3'])
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ # For all registered routers, load the zebra configuration file
+ for rname, router in router_list.iteritems():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ )
+ # Don't start ospfd and ldpd in the CE nodes
+ if router.name[0] == 'r':
+ router.load_config(
+ TopoRouter.RD_OSPF,
+ os.path.join(CWD, '{}/ospfd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_LDP,
+ os.path.join(CWD, '{}/ldpd.conf'.format(rname))
+ )
+
+ tgen.start_router()
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = '{}/{}/{}'.format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result. Wait at most 80 seconds.
+ test_func = partial(topotest.router_json_cmp,
+ tgen.gears[rname], command, expected)
+ _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
+
+ assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+def test_ospf_convergence():
+ logger.info("Test: check OSPF adjacencies")
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json")
+
+def test_rib():
+ logger.info("Test: verify RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show ip route json", "show_ip_route.ref")
+
+def test_ldp_adjacencies():
+ logger.info("Test: verify LDP adjacencies")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show mpls ldp discovery json", "show_ldp_discovery.ref")
+
+def test_ldp_neighbors():
+ logger.info("Test: verify LDP neighbors")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show mpls ldp neighbor json", "show_ldp_neighbor.ref")
+
+def test_ldp_bindings():
+ logger.info("Test: verify LDP bindings")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show mpls ldp binding json", "show_ldp_binding.ref")
+
+# Memory leak test template
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ldp-oc-topo1/r1/ldpd.conf b/tests/topotests/ldp-oc-topo1/r1/ldpd.conf
new file mode 100644
index 000000000..2a8e02383
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/ldpd.conf
@@ -0,0 +1,24 @@
+hostname r1
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 1.1.1.1
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 1.1.1.1
+ !
+ interface r1-eth0
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r1/ospfd.conf b/tests/topotests/ldp-oc-topo1/r1/ospfd.conf
new file mode 100644
index 000000000..6daf034d1
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/ospfd.conf
@@ -0,0 +1,7 @@
+hostname r1
+log file ospfd.log
+!
+router ospf
+ router-id 1.1.1.1
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..2c493173f
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json
@@ -0,0 +1,12 @@
+{
+ "neighbors":{
+ "2.2.2.2":[
+ {
+ "priority":1,
+ "state":"Full\/DR",
+ "address":"10.0.1.2",
+ "ifaceName":"r1-eth0:10.0.1.1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref
new file mode 100644
index 000000000..d75b8f21d
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref
@@ -0,0 +1,171 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0/24":[
+ {
+ "prefix":"10.0.1.0/24",
+ "protocol":"ospf",
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0/24":[
+ {
+ "prefix":"10.0.2.0/24",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0/24":[
+ {
+ "prefix":"10.0.3.0/24",
+ "protocol":"ospf",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0/24":[
+ {
+ "prefix":"123.0.1.0/24",
+ "protocol":"ospf",
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"123.0.1.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref
new file mode 100644
index 000000000..99a59668f
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref
@@ -0,0 +1,61 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"2.2.2.2",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"2.2.2.2",
+ "localLabel":"imp-null",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"2.2.2.2",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref
new file mode 100644
index 000000000..b349f4418
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref
@@ -0,0 +1,11 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"link",
+ "interface":"r1-eth0",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref
new file mode 100644
index 000000000..4bff444a4
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref
@@ -0,0 +1,10 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "state":"OPERATIONAL",
+ "transportAddress":"2.2.2.2"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r1/zebra.conf b/tests/topotests/ldp-oc-topo1/r1/zebra.conf
new file mode 100644
index 000000000..83aea46e6
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r1/zebra.conf
@@ -0,0 +1,17 @@
+log file zebra.log
+!
+hostname r1
+!
+interface lo
+ ip address 1.1.1.1/32
+!
+interface r1-eth0
+ description to sw0
+ ip address 10.0.1.1/24
+ ip address 123.0.1.1/24
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r2/ldpd.conf b/tests/topotests/ldp-oc-topo1/r2/ldpd.conf
new file mode 100644
index 000000000..e1a552c70
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/ldpd.conf
@@ -0,0 +1,28 @@
+hostname r2
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 2.2.2.2
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 2.2.2.2
+ !
+ interface r2-eth0
+ !
+ interface r2-eth1
+ !
+ interface r2-eth2
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r2/ospfd.conf b/tests/topotests/ldp-oc-topo1/r2/ospfd.conf
new file mode 100644
index 000000000..867881366
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/ospfd.conf
@@ -0,0 +1,7 @@
+hostname r2
+log file ospfd.log
+!
+router ospf
+ router-id 2.2.2.2
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..55f12359e
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json
@@ -0,0 +1,31 @@
+{
+ "neighbors":{
+ "1.1.1.1":[
+ {
+ "priority":1,
+ "state":"Full\/Backup",
+ "address":"10.0.1.1",
+ "ifaceName":"r2-eth0:10.0.1.2",
+ "retransmitCounter":0,
+ "requestCounter":0,
+ "dbSummaryCounter":0
+ }
+ ],
+ "3.3.3.3":[
+ {
+ "priority":1,
+ "state":"Full\/Backup",
+ "address":"10.0.2.3",
+ "ifaceName":"r2-eth1:10.0.2.2"
+ }
+ ],
+ "4.4.4.4":[
+ {
+ "priority":1,
+ "state":"Full\/DR",
+ "address":"10.0.2.4",
+ "ifaceName":"r2-eth1:10.0.2.2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref
new file mode 100644
index 000000000..060c0b429
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref
@@ -0,0 +1,209 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0\/24":[
+ {
+ "prefix":"123.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref
new file mode 100644
index 000000000..95fb847c1
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref
@@ -0,0 +1,63 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"1.1.1.1",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"3.3.3.3",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"1.1.1.1",
+ "localLabel":"imp-null",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"3.3.3.3",
+ "localLabel":"imp-null",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"3.3.3.3",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"1.1.1.1",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref
new file mode 100644
index 000000000..812957008
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref
@@ -0,0 +1,18 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "type":"link",
+ "interface":"r2-eth0",
+ "helloHoldtime":15
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "type":"link",
+ "interface":"r2-eth1",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref
new file mode 100644
index 000000000..eed35289e
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref
@@ -0,0 +1,16 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "state":"OPERATIONAL",
+ "transportAddress":"1.1.1.1"
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "state":"OPERATIONAL",
+ "transportAddress":"3.3.3.3"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r2/zebra.conf b/tests/topotests/ldp-oc-topo1/r2/zebra.conf
new file mode 100644
index 000000000..1f1e3e391
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r2/zebra.conf
@@ -0,0 +1,27 @@
+log file zebra.log
+!
+hostname r2
+!
+interface lo
+ ip address 2.2.2.2/32
+!
+interface r2-eth0
+ description to sw0
+ ip address 10.0.1.2/24
+! no link-detect
+!
+interface r2-eth1
+ description to sw1
+ ip address 10.0.2.2/24
+! no link-detect
+!
+interface r2-eths2
+ description to sw2
+ ip address 10.0.3.2/24
+! no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r3/ldpd.conf b/tests/topotests/ldp-oc-topo1/r3/ldpd.conf
new file mode 100644
index 000000000..4e66b140a
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/ldpd.conf
@@ -0,0 +1,24 @@
+hostname r3
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 3.3.3.3
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 3.3.3.3
+ !
+ interface r3-eth0
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r3/ospfd.conf b/tests/topotests/ldp-oc-topo1/r3/ospfd.conf
new file mode 100644
index 000000000..202be238e
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/ospfd.conf
@@ -0,0 +1,8 @@
+hostname r3
+password 1
+log file ospfd.log
+!
+router ospf
+ router-id 3.3.3.3
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..24502ed81
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json
@@ -0,0 +1,20 @@
+{
+ "neighbors":{
+ "2.2.2.2":[
+ {
+ "priority":1,
+ "state":"Full\/DROther",
+ "address":"10.0.2.2",
+ "ifaceName":"r3-eth0:10.0.2.3"
+ }
+ ],
+ "4.4.4.4":[
+ {
+ "priority":1,
+ "state":"Full\/DR",
+ "address":"10.0.2.4",
+ "ifaceName":"r3-eth0:10.0.2.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref
new file mode 100644
index 000000000..40800762b
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref
@@ -0,0 +1,209 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0\/24":[
+ {
+ "prefix":"123.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref
new file mode 100644
index 000000000..100dd307e
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref
@@ -0,0 +1,61 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"2.2.2.2",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"2.2.2.2",
+ "localLabel":"imp-null",
+ "remoteLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"2.2.2.2",
+ "inUse":1
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref
new file mode 100644
index 000000000..c3a07e7e3
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref
@@ -0,0 +1,11 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"link",
+ "interface":"r3-eth0",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref
new file mode 100644
index 000000000..4bff444a4
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref
@@ -0,0 +1,10 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "state":"OPERATIONAL",
+ "transportAddress":"2.2.2.2"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r3/zebra.conf b/tests/topotests/ldp-oc-topo1/r3/zebra.conf
new file mode 100644
index 000000000..234c215dd
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r3/zebra.conf
@@ -0,0 +1,22 @@
+log file zebra.log
+!
+hostname r3
+!
+interface lo
+ ip address 3.3.3.3/32
+!
+interface r3-eth0
+ description to sw1
+ ip address 10.0.2.3/24
+! no link-detect
+!
+interface r3-eth1
+ description to sw2
+ ip address 10.0.3.3/24
+! no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r4/ldpd.conf b/tests/topotests/ldp-oc-topo1/r4/ldpd.conf
new file mode 100644
index 000000000..6b7d28f98
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/ldpd.conf
@@ -0,0 +1,24 @@
+hostname r4
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp discovery hello recv
+debug mpls ldp discovery hello sent
+!
+mpls ldp
+ router-id 4.4.4.4
+ ordered-control
+ !
+ address-family ipv4
+ discovery transport-address 4.4.4.4
+ !
+ !interface r4-eth0
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/r4/ospfd.conf b/tests/topotests/ldp-oc-topo1/r4/ospfd.conf
new file mode 100644
index 000000000..569dbc54e
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/ospfd.conf
@@ -0,0 +1,7 @@
+hostname r4
+log file ospfd.log
+!
+router ospf
+ router-id 4.4.4.4
+ network 0.0.0.0/0 area 0
+!
diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json
new file mode 100644
index 000000000..794410522
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json
@@ -0,0 +1,21 @@
+
+{
+ "neighbors":{
+ "2.2.2.2":[
+ {
+ "priority":1,
+ "state":"Full\/DROther",
+ "address":"10.0.2.2",
+ "ifaceName":"r4-eth0:10.0.2.4"
+ }
+ ],
+ "3.3.3.3":[
+ {
+ "priority":1,
+ "state":"Full\/Backup",
+ "address":"10.0.2.3",
+ "ifaceName":"r4-eth0:10.0.2.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref
new file mode 100644
index 000000000..c9b83a1c7
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref
@@ -0,0 +1,196 @@
+{
+ "1.1.1.1/32":[
+ {
+ "prefix":"1.1.1.1/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2/32":[
+ {
+ "prefix":"2.2.2.2/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3/32":[
+ {
+ "prefix":"3.3.3.3/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4/32":[
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":0,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"4.4.4.4/32",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "123.0.1.0\/24":[
+ {
+ "prefix":"123.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r4-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref
new file mode 100644
index 000000000..2a46c4034
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref
@@ -0,0 +1,68 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"4.4.4.4/32",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.2.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"10.0.3.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"123.0.1.0/24",
+ "neighborId":"0.0.0.0",
+ "localLabel":"imp-null",
+ "remoteLabel":"-",
+ "inUse":0
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ldp-oc-topo1/r4/zebra.conf b/tests/topotests/ldp-oc-topo1/r4/zebra.conf
new file mode 100644
index 000000000..7e291053e
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/r4/zebra.conf
@@ -0,0 +1,17 @@
+log file zebra.log
+!
+hostname r4
+!
+interface lo
+ ip address 4.4.4.4/32
+!
+interface r4-eth0
+ description to sw1
+ ip address 10.0.2.4/24
+! no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot
new file mode 100644
index 000000000..62058e3cb
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot
@@ -0,0 +1,76 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="Test Topology - LDP-OC 1";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r4 [
+ shape=doubleoctagon
+ label="r4",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+
+ # Switches
+ s0 [
+ shape=oval,
+ label="10.0.1.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s1 [
+ shape=oval,
+ label="10.0.2.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s2 [
+ shape=oval,
+ label="10.0.3.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+
+ r1 -- s0 [label="eth0"];
+ r2 -- s0 [label="eth0"];
+
+ r2 -- s1 [label="eth1"];
+ r3 -- s1 [label="eth0"];
+ r4 -- s1 [label="eth0"];
+
+ r2 -- s2 [label="eth2"];
+ r3 -- s2 [label="eth1"];
+}
diff --git a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py
new file mode 100755
index 000000000..eda1b37e5
--- /dev/null
+++ b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+
+#
+# test_ldp_oc_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by by Volta Networks
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ldp_oc_topo1.py: Simple FRR/Quagga LDP Test
+
+ +---------+
+ | r1 |
+ | 1.1.1.1 |
+ +----+----+
+ | .1 r1-eth0
+ |
+ ~~~~~~~~~~~~~
+ ~~ sw0 ~~
+ ~~ 10.0.1.0/24 ~~
+ ~~~~~~~~~~~~~
+ |10.0.1.0/24
+ |
+ | .2 r2-eth0
+ +----+----+
+ | r2 |
+ | 2.2.2.2 |
+ +--+---+--+
+ r2-eth2 .2 | | .2 r2-eth1
+ ______/ \______
+ / \
+ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
+~~ sw2 ~~ ~~ sw1 ~~
+~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~
+ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
+ | / |
+ \ _________/ |
+ \ / \
+r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
+ +----+--+---+ +----+----+
+ | r3 | | r4 |
+ | 3.3.3.3 | | 4.4.4.4 |
+ +-----------+ +---------+
+"""
+
+import os
+import sys
+import pytest
+import json
+from time import sleep
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+class TemplateTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ #
+ # Define FRR Routers
+ #
+ for router in ['r1', 'r2', 'r3', 'r4']:
+ tgen.add_router(router)
+
+ #
+ # Define connections
+ #
+ switch = tgen.add_switch('s0')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r3'])
+ switch.add_link(tgen.gears['r4'])
+
+ switch = tgen.add_switch('s2')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r3'])
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ # For all registered routers, load the zebra configuration file
+ for rname, router in router_list.iteritems():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ )
+ # Don't start ospfd and ldpd in the CE nodes
+ if router.name[0] == 'r':
+ router.load_config(
+ TopoRouter.RD_OSPF,
+ os.path.join(CWD, '{}/ospfd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_LDP,
+ os.path.join(CWD, '{}/ldpd.conf'.format(rname))
+ )
+
+ tgen.start_router()
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = '{}/{}/{}'.format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result. Wait at most 80 seconds.
+ test_func = partial(topotest.router_json_cmp,
+ tgen.gears[rname], command, expected)
+ _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
+
+ assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+def test_ospf_convergence():
+ logger.info("Test: check OSPF adjacencies")
+
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json")
+
+def test_rib():
+ logger.info("Test: verify RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show ip route json", "show_ip_route.ref")
+
+def test_ldp_adjacencies():
+ logger.info("Test: verify LDP adjacencies")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show mpls ldp discovery json", "show_ldp_discovery.ref")
+
+def test_ldp_neighbors():
+ logger.info("Test: verify LDP neighbors")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show mpls ldp neighbor json", "show_ldp_neighbor.ref")
+
+def test_ldp_bindings():
+ logger.info("Test: verify LDP bindings")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ['r1', 'r2', 'r3', 'r4']:
+ router_compare_json_output(rname, "show mpls ldp binding json", "show_ldp_binding.ref")
+
+# Memory leak test template
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref b/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref
index f244122f1..a13c1d459 100644
--- a/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref
+++ b/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref
@@ -3,3 +3,4 @@ xx as to xx via inet 10.0.1.2 dev r1-eth0 proto xx
xx via inet 10.0.1.2 dev r1-eth0 proto xx
xx via inet 10.0.1.2 dev r1-eth0 proto xx
xx via inet 10.0.1.2 dev r1-eth0 proto xx
+
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index f3c17be68..997b72d69 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -382,8 +382,8 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
disable_connected = peer.setdefault("disable_connected_check",
False)
- keep_alive = peer.setdefault("keep_alive", 60)
- hold_down = peer.setdefault("hold_down", 180)
+ keep_alive = peer.setdefault("keepalivetimer", 60)
+ hold_down = peer.setdefault("holddowntimer", 180)
password = peer.setdefault("password", None)
max_hop_limit = peer.setdefault("ebgp_multihop", 1)
diff --git a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
index cb0c4af22..2f7a4ce4e 100755
--- a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
+++ b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
@@ -319,18 +319,18 @@ def test_linux_ipv6_kernel_routingTable():
# Now compare the routing tables (after substituting link-local addresses)
for i in range(1, 5):
- if topotest.version_cmp(platform.release(), '5.3') < 0:
+ # Actual output from router
+ actual = tgen.gears['r{}'.format(i)].run('ip -6 route').rstrip()
+ if "nhid" in actual:
+ refTableFile = os.path.join(CWD, 'r{}/ip_6_address.nhg.ref'.format(i))
+ else:
refTableFile = os.path.join(CWD, 'r{}/ip_6_address.ref'.format(i))
- else:
- refTableFile = os.path.join(CWD, 'r{}/ip_6_address.nhg.ref'.format(i))
- if os.path.isfile(refTableFile):
+ if os.path.isfile(refTableFile):
expected = open(refTableFile).read().rstrip()
# Fix newlines (make them all the same)
expected = ('\n'.join(expected.splitlines())).splitlines(1)
- # Actual output from router
- actual = tgen.gears['r{}'.format(i)].run('ip -6 route').rstrip()
# Mask out Link-Local mac addresses
for ll in linklocals:
actual = actual.replace(ll[1], "fe80::__(%s)__" % ll[0])
diff --git a/tests/topotests/pim-basic/r1/pimd.conf b/tests/topotests/pim-basic/r1/pimd.conf
index cec765699..f64a46deb 100644
--- a/tests/topotests/pim-basic/r1/pimd.conf
+++ b/tests/topotests/pim-basic/r1/pimd.conf
@@ -7,6 +7,10 @@ interface r1-eth0
interface r1-eth1
ip pim
!
+interface r1-eth2
+ ip igmp
+ ip pim
+!
interface lo
ip pim
!
diff --git a/tests/topotests/pim-basic/r1/zebra.conf b/tests/topotests/pim-basic/r1/zebra.conf
index b0a25f12a..e43041758 100644
--- a/tests/topotests/pim-basic/r1/zebra.conf
+++ b/tests/topotests/pim-basic/r1/zebra.conf
@@ -6,6 +6,9 @@ interface r1-eth0
interface r1-eth1
ip address 10.0.30.1/24
!
+interface r1-eth2
+ ip address 10.0.40.1/24
+!
interface lo
ip address 10.254.0.1/32
!
diff --git a/tests/topotests/pim-basic/r3/pimd.conf b/tests/topotests/pim-basic/r3/pimd.conf
new file mode 100644
index 000000000..f94ee9993
--- /dev/null
+++ b/tests/topotests/pim-basic/r3/pimd.conf
@@ -0,0 +1 @@
+hostname r3
diff --git a/tests/topotests/pim-basic/r3/zebra.conf b/tests/topotests/pim-basic/r3/zebra.conf
new file mode 100644
index 000000000..8e58e8c66
--- /dev/null
+++ b/tests/topotests/pim-basic/r3/zebra.conf
@@ -0,0 +1,8 @@
+hostname r3
+!
+interface r3-eth0
+ ip address 10.0.40.4/24
+!
+interface lo
+ ip address 10.254.0.4/32
+!
diff --git a/tests/topotests/pim-basic/rp/pimd.conf b/tests/topotests/pim-basic/rp/pimd.conf
index 3f1b4d65c..6e35c9797 100644
--- a/tests/topotests/pim-basic/rp/pimd.conf
+++ b/tests/topotests/pim-basic/rp/pimd.conf
@@ -7,3 +7,6 @@ interface lo
ip pim
!
ip pim rp 10.254.0.3
+ip pim register-accept-list ACCEPT
+
+ip prefix-list ACCEPT seq 5 permit 10.0.20.0/24 le 32
diff --git a/tests/topotests/pim-basic/test_pim.py b/tests/topotests/pim-basic/test_pim.py
index 0e0569e23..9101d7e03 100644
--- a/tests/topotests/pim-basic/test_pim.py
+++ b/tests/topotests/pim-basic/test_pim.py
@@ -46,14 +46,18 @@ class PIMTopo(Topo):
"Build function"
tgen = get_topogen(self)
- for routern in range(1, 3):
+ for routern in range(1, 4):
tgen.add_router('r{}'.format(routern))
tgen.add_router('rp')
+ # rp ------ r1 -------- r2
+ # \
+ # --------- r3
# r1 -> .1
# r2 -> .2
# rp -> .3
+ # r3 -> .4
# loopback network is 10.254.0.X/32
#
# r1 <- sw1 -> r2
@@ -70,6 +74,10 @@ class PIMTopo(Topo):
sw.add_link(tgen.gears['r1'])
sw.add_link(tgen.gears['rp'])
+ # 10.0.40.0/24
+ sw = tgen.add_switch('sw3')
+ sw.add_link(tgen.gears['r1'])
+ sw.add_link(tgen.gears['r3'])
def setup_module(mod):
"Sets up the pytest environment"
@@ -130,12 +138,15 @@ def test_pim_send_mcast_stream():
pytest.skip(tgen.errors)
rp = tgen.gears['rp']
+ r3 = tgen.gears['r3']
r2 = tgen.gears['r2']
r1 = tgen.gears['r1']
# Let's establish a S,G stream from r2 -> r1
CWD = os.path.dirname(os.path.realpath(__file__))
r2.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r2-eth0 > /tmp/bar".format(CWD))
+ # And from r3 -> r1
+ r3.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r3-eth0 > /tmp/bar".format(CWD))
# Let's see that it shows up and we have established some basic state
out = r1.vtysh_cmd("show ip pim upstream json", isjson=True)
diff --git a/tools/coccinelle/int_to_bool_function.cocci b/tools/coccinelle/int_to_bool_function.cocci
new file mode 100644
index 000000000..f86fe70be
--- /dev/null
+++ b/tools/coccinelle/int_to_bool_function.cocci
@@ -0,0 +1,24 @@
+@@
+identifier fn;
+typedef bool;
+symbol false;
+symbol true;
+identifier I;
+struct thread *thread;
+@@
+
+- int
++ bool
+fn (...)
+{
+... when strict
+ when != I = THREAD_ARG(thread);
+(
+- return 0;
++ return false;
+|
+- return 1;
++ return true;
+)
+?...
+}
diff --git a/zebra/main.c b/zebra/main.c
index 5951c7e28..dab144919 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -53,6 +53,7 @@
#include "zebra/zebra_rnh.h"
#include "zebra/zebra_pbr.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_routemap.h"
#if defined(HANDLE_NETLINK_FUZZING)
#include "zebra/kernel_netlink.h"
@@ -179,7 +180,13 @@ static void sigint(void)
access_list_reset();
prefix_list_reset();
- route_map_finish();
+ /*
+ * zebra_routemap_finish will
+ * 1 set rmap upd timer to 0 so that rmap update wont be scheduled again
+ * 2 Put off the rmap update thread
+ * 3 route_map_finish
+ */
+ zebra_routemap_finish();
list_delete(&zrouter.client_list);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index d1148061b..80cc18a57 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -173,8 +173,7 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
afi = family2afi(p->family);
if (!afi) {
flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
- "%s: Unknown AFI/SAFI prefix received\n",
- __FUNCTION__);
+ "%s: Unknown AFI/SAFI prefix received\n", __func__);
return;
}
if (!zebra_check_addr(p)) {
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index e40bf45f5..2f675e2d5 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1111,7 +1111,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
* @param nlmsg: nlmsghdr structure to fill in.
* @param req_size: The size allocated for the message.
*/
-static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
+static void _netlink_route_build_singlepath(const struct prefix *p,
+ const char *routedesc, int bytelen,
const struct nexthop *nexthop,
struct nlmsghdr *nlmsg,
struct rtmsg *rtmsg,
@@ -1176,9 +1177,8 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- " 5549: _netlink_route_build_singlepath() (%s): "
- "nexthop via %s %s if %u(%u)",
- routedesc, ipv4_ll_buf, label_buf,
+ " 5549: _netlink_route_build_singlepath() (%s): %pFX nexthop via %s %s if %u(%u)",
+ routedesc, p, ipv4_ll_buf, label_buf,
nexthop->ifindex, nexthop->vrf_id);
return;
}
@@ -1202,9 +1202,8 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u(%u)",
- routedesc, inet_ntoa(nexthop->gate.ipv4),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u(%u)",
+ routedesc, p, inet_ntoa(nexthop->gate.ipv4),
label_buf, nexthop->ifindex, nexthop->vrf_id);
}
@@ -1225,9 +1224,8 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u(%u)",
- routedesc, inet6_ntoa(nexthop->gate.ipv6),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u(%u)",
+ routedesc, p, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex, nexthop->vrf_id);
}
@@ -1251,9 +1249,9 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via if %u(%u)",
- routedesc, nexthop->ifindex, nexthop->vrf_id);
+ "netlink_route_multipath() (%s): %pFX nexthop via if %u(%u)",
+ routedesc, p, nexthop->ifindex,
+ nexthop->vrf_id);
}
}
@@ -1273,12 +1271,11 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
* @param src: pointer pointing to a location where
* the prefsrc should be stored.
*/
-static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
- const struct nexthop *nexthop,
- struct rtattr *rta,
- struct rtnexthop *rtnh,
- struct rtmsg *rtmsg,
- const union g_addr **src)
+static void
+_netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
+ int bytelen, const struct nexthop *nexthop,
+ struct rtattr *rta, struct rtnexthop *rtnh,
+ struct rtmsg *rtmsg, const union g_addr **src)
{
mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
@@ -1340,6 +1337,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
bytelen);
rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
rtnh->rtnh_ifindex = nexthop->ifindex;
+ if (nexthop->weight)
+ rtnh->rtnh_hops = nexthop->weight - 1;
if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
*src = &nexthop->rmap_src;
@@ -1348,9 +1347,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- " 5549: netlink_route_build_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, ipv4_ll_buf, label_buf,
+ " 5549: netlink_route_build_multipath() (%s): %pFX nexthop via %s %s if %u",
+ routedesc, p, ipv4_ll_buf, label_buf,
nexthop->ifindex);
return;
}
@@ -1367,9 +1365,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, inet_ntoa(nexthop->gate.ipv4),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u",
+ routedesc, p, inet_ntoa(nexthop->gate.ipv4),
label_buf, nexthop->ifindex);
}
if (nexthop->type == NEXTHOP_TYPE_IPV6
@@ -1385,9 +1382,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, inet6_ntoa(nexthop->gate.ipv6),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u",
+ routedesc, p, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
@@ -1408,16 +1404,16 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via if %u",
- routedesc, nexthop->ifindex);
+ "netlink_route_multipath() (%s): %pFX nexthop via if %u",
+ routedesc, p, nexthop->ifindex);
}
if (nexthop->weight)
rtnh->rtnh_hops = nexthop->weight - 1;
}
-static inline void _netlink_mpls_build_singlepath(const char *routedesc,
+static inline void _netlink_mpls_build_singlepath(const struct prefix *p,
+ const char *routedesc,
const zebra_nhlfe_t *nhlfe,
struct nlmsghdr *nlmsg,
struct rtmsg *rtmsg,
@@ -1428,23 +1424,24 @@ static inline void _netlink_mpls_build_singlepath(const char *routedesc,
family = NHLFE_FAMILY(nhlfe);
bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
+ _netlink_route_build_singlepath(p, routedesc, bytelen, nhlfe->nexthop,
nlmsg, rtmsg, req_size, cmd);
}
static inline void
-_netlink_mpls_build_multipath(const char *routedesc, const zebra_nhlfe_t *nhlfe,
- struct rtattr *rta, struct rtnexthop *rtnh,
- struct rtmsg *rtmsg, const union g_addr **src)
+_netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc,
+ const zebra_nhlfe_t *nhlfe, struct rtattr *rta,
+ struct rtnexthop *rtnh, struct rtmsg *rtmsg,
+ const union g_addr **src)
{
int bytelen;
uint8_t family;
family = NHLFE_FAMILY(nhlfe);
bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta,
- rtnh, rtmsg, src);
+ _netlink_route_build_multipath(p, routedesc, bytelen, nhlfe->nexthop,
+ rta, rtnh, rtmsg, src);
}
@@ -1644,6 +1641,10 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
}
if (kernel_nexthops_supported()) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath(): %pFX nhg_id is %u",
+ p, dplane_ctx_get_nhe_id(ctx));
/* Kernel supports nexthop objects */
addattr32(&req.n, sizeof(req), RTA_NH_ID,
dplane_ctx_get_nhe_id(ctx));
@@ -1730,7 +1731,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
: "single-path";
_netlink_route_build_singlepath(
- routedesc, bytelen, nexthop, &req.n,
+ p, routedesc, bytelen, nexthop, &req.n,
&req.r, sizeof(req), cmd);
nexthop_num++;
break;
@@ -1800,8 +1801,8 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
nexthop_num++;
_netlink_route_build_multipath(
- routedesc, bytelen, nexthop, rta, rtnh,
- &req.r, &src1);
+ p, routedesc, bytelen, nexthop, rta,
+ rtnh, &req.r, &src1);
rtnh = RTNH_NEXT(rtnh);
if (!setsrc && src1) {
@@ -3464,6 +3465,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
unsigned int nexthop_num;
const char *routedesc;
int route_type;
+ struct prefix p = {0};
struct {
struct nlmsghdr n;
@@ -3550,8 +3552,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
NEXTHOP_FLAG_FIB)))) {
/* Add the gateway */
_netlink_mpls_build_singlepath(
- routedesc, nhlfe,
- &req.n, &req.r,
+ &p, routedesc, nhlfe, &req.n, &req.r,
sizeof(req), cmd);
nexthop_num++;
@@ -3591,9 +3592,9 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
nexthop_num++;
/* Build the multipath */
- _netlink_mpls_build_multipath(routedesc, nhlfe,
- rta, rtnh, &req.r,
- &src1);
+ _netlink_mpls_build_multipath(&p, routedesc,
+ nhlfe, rta, rtnh,
+ &req.r, &src1);
rtnh = RTNH_NEXT(rtnh);
}
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 88e3ce68d..f1c181438 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2418,9 +2418,11 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
}
if (!(zpr.rule.filter.dst_ip.family == AF_INET
|| zpr.rule.filter.dst_ip.family == AF_INET6)) {
- zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")",
- family2str(zpr.rule.filter.dst_ip.family),
- zpr.rule.filter.dst_ip.family);
+ zlog_warn(
+ "Unsupported PBR destination IP family: %s (%" PRIu8
+ ")",
+ family2str(zpr.rule.filter.dst_ip.family),
+ zpr.rule.filter.dst_ip.family);
return;
}
@@ -2512,14 +2514,18 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
if (!(zpi.dst.family == AF_INET
|| zpi.dst.family == AF_INET6)) {
- zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")",
- family2str(zpi.dst.family), zpi.dst.family);
+ zlog_warn(
+ "Unsupported PBR destination IP family: %s (%" PRIu8
+ ")",
+ family2str(zpi.dst.family), zpi.dst.family);
goto stream_failure;
}
if (!(zpi.src.family == AF_INET
|| zpi.src.family == AF_INET6)) {
- zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")",
- family2str(zpi.src.family), zpi.src.family);
+ zlog_warn(
+ "Unsupported PBR source IP family: %s (%" PRIu8
+ ")",
+ family2str(zpi.src.family), zpi.src.family);
goto stream_failure;
}
diff --git a/zebra/zebra_mlag.c b/zebra/zebra_mlag.c
index cf2fe2648..8ba7998f5 100644
--- a/zebra/zebra_mlag.c
+++ b/zebra/zebra_mlag.c
@@ -322,7 +322,7 @@ static int zebra_mlag_post_data_from_main_thread(struct thread *thread)
STREAM_GETL(s, msg_type);
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug(
- "%s: Posting MLAG data for msg_type:0x%x to interested cleints",
+ "%s: Posting MLAG data for msg_type:0x%x to interested clients",
__func__, msg_type);
msg_len = s->endp - ZEBRA_MLAG_METADATA_LEN;
@@ -364,7 +364,7 @@ stream_failure:
/*
* Start the MLAG Thread, this will be used to write client data on to
- * MLAG Process and to read the data from MLAG and post to cleints.
+ * MLAG Process and to read the data from MLAG and post to clients.
* when all clients are un-registered, this Thread will be
* suspended.
*/
diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c
index 01d5114b9..eabc2e005 100644
--- a/zebra/zebra_ptm_redistribute.c
+++ b/zebra/zebra_ptm_redistribute.c
@@ -59,6 +59,9 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
stream_put(s, &sp->u.prefix, blen);
stream_putc(s, sp->prefixlen);
+ /* c-bit bullshit */
+ stream_putc(s, 0);
+
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 6cfc68eb7..c758e2583 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -1030,7 +1030,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
default:
flog_err(EC_ZEBRA_RNH_UNKNOWN_FAMILY,
"%s: Unknown family (%d) notification attempted\n",
- __FUNCTION__, rn->p.family);
+ __func__, rn->p.family);
break;
}
if (re) {
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 2963d8382..500c2c84a 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -1793,6 +1793,15 @@ static void zebra_route_map_set_delay_timer(uint32_t value)
}
}
+void zebra_routemap_finish(void)
+{
+ /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
+ zebra_rmap_update_timer = 0;
+ /* Thread off if any scheduled already */
+ THREAD_TIMER_OFF(zebra_t_rmap_update);
+ route_map_finish();
+}
+
void zebra_route_map_write_delay_timer(struct vty *vty)
{
if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h
index 6a630e1ac..56e805ea0 100644
--- a/zebra/zebra_routemap.h
+++ b/zebra/zebra_routemap.h
@@ -56,4 +56,5 @@ zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p,
}
#endif
+extern void zebra_routemap_finish(void);
#endif
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 79ce43be9..ccc6e9e46 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -241,25 +241,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
vty_out(vty, "\n");
time_t uptime;
- struct tm tm;
uptime = monotime(NULL);
uptime -= re->uptime;
- gmtime_r(&uptime, &tm);
- vty_out(vty, " Last update ");
+ frrtime_to_interval(uptime, buf, sizeof(buf));
- if (uptime < ONE_DAY_SECOND)
- vty_out(vty, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out(vty, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- vty_out(vty, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7),
- tm.tm_hour);
- vty_out(vty, " ago\n");
+ vty_out(vty, " Last update %s ago\n", buf);
if (show_ng)
vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id);
@@ -402,14 +390,15 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_route = NULL;
json_object *json_labels = NULL;
time_t uptime;
- struct tm tm;
struct vrf *vrf = NULL;
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct nexthop_group *nhg;
+ char up_str[MONOTIME_STRLEN];
uptime = monotime(NULL);
uptime -= re->uptime;
- gmtime_r(&uptime, &tm);
+
+ frrtime_to_interval(uptime, up_str, sizeof(up_str));
/* If showing fib information, use the fib view of the
* nexthops.
@@ -474,18 +463,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_int_add(json_route, "internalNextHopActiveNum",
nexthop_group_active_nexthop_num(
&(re->nhe->nhg)));
- if (uptime < ONE_DAY_SECOND)
- sprintf(buf, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- sprintf(buf, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- sprintf(buf, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7),
- tm.tm_hour);
- json_object_string_add(json_route, "uptime", buf);
+ json_object_string_add(json_route, "uptime", up_str);
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
json_nexthop = json_object_new_object();
@@ -774,17 +753,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
sizeof(buf), 1));
}
- if (uptime < ONE_DAY_SECOND)
- vty_out(vty, ", %02d:%02d:%02d", tm.tm_hour,
- tm.tm_min, tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out(vty, ", %dd%02dh%02dm", tm.tm_yday,
- tm.tm_hour, tm.tm_min);
- else
- vty_out(vty, ", %02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7),
- tm.tm_hour);
- vty_out(vty, "\n");
+ vty_out(vty, ", %s\n", up_str);
}
}
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 40aa9010c..7f806d82c 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -858,7 +858,6 @@ void zserv_event(struct zserv *client, enum zserv_event event)
#define ZEBRA_TIME_BUF 32
static char *zserv_time_buf(time_t *time1, char *buf, int buflen)
{
- struct tm tm;
time_t now;
assert(buf != NULL);
@@ -872,17 +871,9 @@ static char *zserv_time_buf(time_t *time1, char *buf, int buflen)
now = monotime(NULL);
now -= *time1;
- gmtime_r(&now, &tm);
-
- if (now < ONE_DAY_SECOND)
- snprintf(buf, buflen, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (now < ONE_WEEK_SECOND)
- snprintf(buf, buflen, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- snprintf(buf, buflen, "%02dw%dd%02dh", tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
+
+ frrtime_to_interval(now, buf, buflen);
+
return buf;
}
@@ -1001,8 +992,6 @@ static void zebra_show_stale_client_detail(struct vty *vty,
struct zserv *client)
{
char buf[PREFIX2STR_BUFFER];
- struct tm tm;
- struct timeval tv;
time_t uptime;
struct client_gr_info *info = NULL;
struct zserv *s = NULL;
@@ -1028,26 +1017,13 @@ static void zebra_show_stale_client_detail(struct vty *vty,
if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities)) {
if (info->stale_client_ptr) {
s = (struct zserv *)(info->stale_client_ptr);
- uptime = monotime(&tv);
+ uptime = monotime(NULL);
uptime -= s->restart_time;
- gmtime_r(&uptime, &tm);
-
- vty_out(vty, "Last restart time : ");
- if (uptime < ONE_DAY_SECOND)
- vty_out(vty, "%02d:%02d:%02d",
- tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- else if (uptime < ONE_WEEK_SECOND)
- vty_out(vty, "%dd%02dh%02dm",
- tm.tm_yday, tm.tm_hour,
- tm.tm_min);
- else
- vty_out(vty, "%02dw%dd%02dh",
- tm.tm_yday / 7,
- tm.tm_yday - ((tm.tm_yday / 7)
- * 7),
- tm.tm_hour);
- vty_out(vty, " ago\n");
+
+ frrtime_to_interval(uptime, buf, sizeof(buf));
+
+ vty_out(vty, "Last restart time : %s ago\n",
+ buf);
vty_out(vty, "Stalepath removal time: %d sec\n",
info->stale_removal_time);
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 6a075cc9a..6ab7fbd91 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -314,7 +314,7 @@ extern void zserv_read_file(char *input);
#endif
/* TODO */
-int zebra_finalize(struct thread *event);
+__attribute__((__noreturn__)) int zebra_finalize(struct thread *event);
/*
* Graceful restart functions.