summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd_packet.c2
-rw-r--r--bfdd/bfdd_vty.c15
-rw-r--r--bfdd/ptm_adapter.c12
-rw-r--r--bgpd/bgp_bmp.c2
-rw-r--r--bgpd/bgp_damp.c62
-rw-r--r--bgpd/bgp_ecommunity.c2
-rw-r--r--bgpd/bgp_evpn_mh.c63
-rw-r--r--bgpd/bgp_evpn_vty.c181
-rw-r--r--bgpd/bgp_filter.c16
-rw-r--r--bgpd/bgp_flowspec_vty.c6
-rw-r--r--bgpd/bgp_labelpool.c37
-rw-r--r--bgpd/bgp_mpath.c14
-rw-r--r--bgpd/bgp_mplsvpn.c10
-rw-r--r--bgpd/bgp_nht.c7
-rw-r--r--bgpd/bgp_open.c143
-rw-r--r--bgpd/bgp_open.h15
-rw-r--r--bgpd/bgp_packet.c66
-rw-r--r--bgpd/bgp_packet.h2
-rw-r--r--bgpd/bgp_route.c582
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_routemap.c239
-rw-r--r--bgpd/bgp_routemap_nb_config.c2
-rw-r--r--bgpd/bgp_vpn.c12
-rw-r--r--bgpd/bgp_vty.c178
-rw-r--r--bgpd/bgp_zebra.c44
-rw-r--r--bgpd/bgp_zebra.h7
-rw-r--r--bgpd/bgpd.c12
-rw-r--r--bgpd/bgpd.h4
-rw-r--r--configure.ac1
-rw-r--r--doc/developer/frr-release-procedure.rst184
-rw-r--r--doc/user/bgp.rst56
-rw-r--r--doc/user/overview.rst3
-rw-r--r--doc/user/routemap.rst14
-rw-r--r--eigrpd/eigrp_filter.c2
-rw-r--r--eigrpd/eigrp_network.c2
-rw-r--r--eigrpd/eigrp_northbound.c4
-rw-r--r--isisd/isis_bfd.c3
-rw-r--r--isisd/isis_circuit.c6
-rw-r--r--isisd/isis_ldp_sync.c2
-rw-r--r--isisd/isis_nb_config.c2
-rw-r--r--isisd/isis_pfpacket.c11
-rw-r--r--isisd/isis_sr.c10
-rw-r--r--ldpd/ldp_vty_exec.c61
-rw-r--r--lib/command.c41
-rw-r--r--lib/command.h3
-rw-r--r--lib/ferr.c8
-rw-r--r--lib/filter.c56
-rw-r--r--lib/if.c23
-rw-r--r--lib/if.h41
-rw-r--r--lib/json.c24
-rw-r--r--lib/json.h48
-rw-r--r--lib/link_state.c12
-rw-r--r--lib/log_vty.c23
-rw-r--r--lib/nexthop_group.c17
-rw-r--r--lib/northbound.c3
-rw-r--r--lib/northbound_confd.c91
-rw-r--r--lib/plist.c21
-rw-r--r--lib/routemap.c122
-rw-r--r--lib/routemap.h86
-rw-r--r--lib/routemap_cli.c21
-rw-r--r--lib/routemap_northbound.c20
-rw-r--r--lib/srv6.c8
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h2
-rw-r--r--lib/vty.c16
-rw-r--r--lib/vty.h8
-rw-r--r--lib/zclient.c15
-rw-r--r--nhrpd/nhrp_interface.c10
-rw-r--r--nhrpd/nhrp_route.c8
-rw-r--r--ospf6d/ospf6_area.c8
-rw-r--r--ospf6d/ospf6_asbr.c39
-rw-r--r--ospf6d/ospf6_bfd.c2
-rw-r--r--ospf6d/ospf6_flood.c20
-rw-r--r--ospf6d/ospf6_flood.h2
-rw-r--r--ospf6d/ospf6_gr_helper.c8
-rw-r--r--ospf6d/ospf6_interface.c48
-rw-r--r--ospf6d/ospf6_intra.c22
-rw-r--r--ospf6d/ospf6_lsa.c62
-rw-r--r--ospf6d/ospf6_lsa.h3
-rw-r--r--ospf6d/ospf6_message.c55
-rw-r--r--ospf6d/ospf6_neighbor.c22
-rw-r--r--ospf6d/ospf6_route.c45
-rw-r--r--ospf6d/ospf6_route.h15
-rw-r--r--ospf6d/ospf6_snmp.c9
-rw-r--r--ospf6d/ospf6_top.c23
-rw-r--r--ospf6d/ospf6_top.h1
-rw-r--r--ospf6d/ospf6d.c14
-rw-r--r--ospfd/ospf_asbr.c4
-rw-r--r--ospfd/ospf_ase.c13
-rw-r--r--ospfd/ospf_dump.c21
-rw-r--r--ospfd/ospf_ext.c4
-rw-r--r--ospfd/ospf_interface.c28
-rw-r--r--ospfd/ospf_ldp_sync.c36
-rw-r--r--ospfd/ospf_packet.c2
-rw-r--r--ospfd/ospf_sr.c337
-rw-r--r--ospfd/ospf_sr.h6
-rw-r--r--ospfd/ospf_te.c8
-rw-r--r--ospfd/ospf_vty.c518
-rw-r--r--ospfd/ospfd.c4
-rw-r--r--pathd/path_ted.c8
-rw-r--r--pbrd/pbr_vrf.c11
-rw-r--r--pbrd/pbr_vrf.h1
-rw-r--r--pbrd/pbr_vty.c41
-rw-r--r--pbrd/pbr_zebra.c2
-rw-r--r--pimd/pim_bfd.c2
-rw-r--r--pimd/pim_bsm.c6
-rw-r--r--pimd/pim_cmd.c44
-rw-r--r--pimd/pim_iface.c78
-rw-r--r--pimd/pim_iface.h1
-rw-r--r--pimd/pim_ifchannel.c18
-rw-r--r--pimd/pim_ifchannel.h1
-rw-r--r--pimd/pim_igmp.c14
-rw-r--r--pimd/pim_igmp.h1
-rw-r--r--pimd/pim_jp_agg.c2
-rw-r--r--pimd/pim_nb_config.c8
-rw-r--r--pimd/pim_pim.c4
-rw-r--r--pimd/pim_rp.c51
-rw-r--r--pimd/pim_static.c2
-rw-r--r--pimd/pim_upstream.c9
-rw-r--r--pimd/pim_vxlan.c2
-rw-r--r--pimd/pim_vxlan.h2
-rw-r--r--pimd/pim_zebra.c11
-rw-r--r--pimd/pim_zebra.h2
-rw-r--r--redhat/frr.spec.in4
-rw-r--r--ripd/rip_interface.c54
-rw-r--r--ripngd/ripng_interface.c55
-rw-r--r--sharpd/sharp_vty.c12
-rw-r--r--staticd/static_routes.c8
-rw-r--r--staticd/static_vrf.c11
-rw-r--r--staticd/static_vrf.h1
-rw-r--r--staticd/static_zebra.c6
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer1/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer10/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer11/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer12/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer13/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer14/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer15/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer16/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer17/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer18/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer19/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer2/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer20/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer3/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer4/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer5/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer6/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer7/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer8/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer9/exa-send.py2
-rw-r--r--tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py2
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/__init__.py0
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py106
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py1542
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py404
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py (renamed from tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py)2321
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py1686
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py1515
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py1216
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py1367
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py1024
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py4358
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py56
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer1/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer2/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer3/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer4/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer5/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer6/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer7/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer8/exa-send.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py0
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf32
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf33
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf11
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py121
-rw-r--r--tests/topotests/bgp_route_server_client/__init__.py0
-rw-r--r--tests/topotests/bgp_route_server_client/r1/bgpd.conf11
-rw-r--r--tests/topotests/bgp_route_server_client/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_route_server_client/r2/bgpd.conf15
-rw-r--r--tests/topotests/bgp_route_server_client/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_route_server_client/r3/bgpd.conf11
-rw-r--r--tests/topotests/bgp_route_server_client/r3/zebra.conf7
-rw-r--r--tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py134
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json563
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json1088
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py916
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py539
-rwxr-xr-xtests/topotests/bgp_vrf_netns/peer1/exa-send.py2
-rw-r--r--tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py34
-rw-r--r--tests/topotests/lib/bgp.py92
-rw-r--r--tests/topotests/lib/common_config.py39
-rw-r--r--tests/topotests/lib/ospf.py115
-rw-r--r--tests/topotests/lib/pim.py44
-rw-r--r--tests/topotests/lib/topojson.py15
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py2
-rw-r--r--tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json52
-rw-r--r--tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json86
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py162
-rwxr-xr-xtests/topotests/pim_basic/mcast-rx.py2
-rwxr-xr-xtests/topotests/pim_basic/mcast-tx.py2
-rw-r--r--tools/coccinelle/json_object_string_addf_inet_ntop.cocci19
-rw-r--r--tools/coccinelle/json_object_string_addf_prefix2str.cocci16
-rw-r--r--tools/coccinelle/vty_json.cocci9
-rw-r--r--vrrpd/vrrp.c12
-rw-r--r--vrrpd/vrrp_zebra.c32
-rw-r--r--vtysh/vtysh.c70
-rw-r--r--vtysh/vtysh_config.c2
-rw-r--r--yang/confd/confd.frr-ripd.yang6
-rw-r--r--yang/confd/confd.frr-ripngd.yang6
-rw-r--r--yang/frr-bgp-bmp.yang2
-rw-r--r--yang/frr-bgp-common-structure.yang2
-rw-r--r--yang/frr-bgp-neighbor.yang4
-rw-r--r--yang/frr-bgp-peer-group.yang4
-rw-r--r--yang/frr-route-map.yang14
-rw-r--r--yang/frr-routing.yang2
-rw-r--r--yang/subdir.am30
-rw-r--r--zebra/connected.c24
-rw-r--r--zebra/dplane_fpm_nl.c3
-rw-r--r--zebra/if_ioctl.c2
-rw-r--r--zebra/if_netlink.c13
-rw-r--r--zebra/interface.c112
-rw-r--r--zebra/ioctl.c14
-rw-r--r--zebra/main.c7
-rw-r--r--zebra/redistribute.c32
-rw-r--r--zebra/router-id.c6
-rw-r--r--zebra/rt_netlink.c27
-rw-r--r--zebra/rtadv.c109
-rw-r--r--zebra/zapi_msg.c19
-rw-r--r--zebra/zebra_dplane.c26
-rw-r--r--zebra/zebra_evpn.c18
-rw-r--r--zebra/zebra_evpn_mac.c19
-rw-r--r--zebra/zebra_evpn_mh.c83
-rw-r--r--zebra/zebra_evpn_neigh.c21
-rw-r--r--zebra/zebra_evpn_vxlan.h2
-rw-r--r--zebra/zebra_l2.c6
-rw-r--r--zebra/zebra_mpls.c29
-rw-r--r--zebra/zebra_ptm.c2
-rw-r--r--zebra/zebra_pw.c4
-rw-r--r--zebra/zebra_rib.c4
-rw-r--r--zebra/zebra_router.c5
-rw-r--r--zebra/zebra_router.h1
-rw-r--r--zebra/zebra_srv6_vty.c4
-rw-r--r--zebra/zebra_vty.c42
-rw-r--r--zebra/zebra_vxlan.c204
-rw-r--r--zebra/zserv.c7
256 files changed, 15766 insertions, 9824 deletions
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index b7c1af7e71..5b1329fa37 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -583,7 +583,7 @@ int bfd_recv_cb(struct thread *t)
if (ifindex) {
ifp = if_lookup_by_index(ifindex, vrfid);
if (ifp)
- vrfid = ifp->vrf_id;
+ vrfid = ifp->vrf->vrf_id;
}
/* Implement RFC 5880 6.8.6 */
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index 4091ab9caa..fc3a178703 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -282,8 +282,7 @@ static void _display_peer_json(struct vty *vty, struct bfd_session *bs)
{
struct json_object *jo = __display_peer_json(bs);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
- json_object_free(jo);
+ vty_json(vty, jo);
}
struct bfd_vrf_tuple {
@@ -353,8 +352,7 @@ static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json)
bvt.jo = jo;
bfd_id_iterate(_display_peer_json_iter, &bvt);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
- json_object_free(jo);
+ vty_json(vty, jo);
}
static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
@@ -407,8 +405,7 @@ static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
{
struct json_object *jo = __display_peer_counters_json(bs);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
- json_object_free(jo);
+ vty_json(vty, jo);
}
static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg)
@@ -472,8 +469,7 @@ static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json
bvt.jo = jo;
bfd_id_iterate(_display_peer_counter_json_iter, &bvt);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
- json_object_free(jo);
+ vty_json(vty, jo);
}
static void _clear_peer_counter(struct bfd_session *bs)
@@ -556,8 +552,7 @@ static void _display_peers_brief(struct vty *vty, const char *vrfname, bool use_
bfd_id_iterate(_display_peer_json_iter, &bvt);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
- json_object_free(jo);
+ vty_json(vty, jo);
}
static struct bfd_session *
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 434d79c8f5..bf8f731d50 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -666,9 +666,7 @@ static void bfdd_sessions_enable_interface(struct interface *ifp)
struct bfd_session *bs;
struct vrf *vrf;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- if (!vrf)
- return;
+ vrf = ifp->vrf;
TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
bs = bso->bso_bs;
@@ -767,8 +765,8 @@ void bfdd_sessions_disable_vrf(struct vrf *vrf)
static int bfd_ifp_destroy(struct interface *ifp)
{
if (bglobal.debug_zebra)
- zlog_debug("zclient: delete interface %s (VRF %u)", ifp->name,
- ifp->vrf_id);
+ zlog_debug("zclient: delete interface %s (VRF %s(%u))",
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
bfdd_sessions_disable_interface(ifp);
@@ -837,8 +835,8 @@ static int bfdd_interface_address_update(ZAPI_CALLBACK_ARGS)
static int bfd_ifp_create(struct interface *ifp)
{
if (bglobal.debug_zebra)
- zlog_debug("zclient: add interface %s (VRF %u)", ifp->name,
- ifp->vrf_id);
+ zlog_debug("zclient: add interface %s (VRF %s(%u))", ifp->name,
+ ifp->vrf->name, ifp->vrf->vrf_id);
bfdd_sessions_enable_interface(ifp);
return 0;
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index b4da226999..746f067ae0 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -2050,7 +2050,7 @@ DEFPY(bmp_connect,
DEFPY(bmp_acl,
bmp_acl_cmd,
- "[no] <ip|ipv6>$af access-list WORD",
+ "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
NO_STR
IP_STR
IPV6_STR
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 6726dd6160..90b7958c43 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -653,21 +653,42 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
}
static int bgp_print_dampening_parameters(struct bgp *bgp, struct vty *vty,
- afi_t afi, safi_t safi)
+ afi_t afi, safi_t safi, bool use_json)
{
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
- vty_out(vty, "Half-life time: %lld min\n",
- (long long)damp[afi][safi].half_life / 60);
- vty_out(vty, "Reuse penalty: %d\n",
- damp[afi][safi].reuse_limit);
- vty_out(vty, "Suppress penalty: %d\n",
- damp[afi][safi].suppress_value);
- vty_out(vty, "Max suppress time: %lld min\n",
- (long long)damp[afi][safi].max_suppress_time / 60);
- vty_out(vty, "Max suppress penalty: %u\n",
- damp[afi][safi].ceiling);
- vty_out(vty, "\n");
- } else
+ struct bgp_damp_config *bdc = &damp[afi][safi];
+
+ if (use_json) {
+ json_object *json = json_object_new_object();
+
+ json_object_int_add(json, "halfLifeSecs",
+ bdc->half_life);
+ json_object_int_add(json, "reusePenalty",
+ bdc->reuse_limit);
+ json_object_int_add(json, "suppressPenalty",
+ bdc->suppress_value);
+ json_object_int_add(json, "maxSuppressTimeSecs",
+ bdc->max_suppress_time);
+ json_object_int_add(json, "maxSuppressPenalty",
+ bdc->ceiling);
+
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ } else {
+ vty_out(vty, "Half-life time: %lld min\n",
+ (long long)bdc->half_life / 60);
+ vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit);
+ vty_out(vty, "Suppress penalty: %d\n",
+ bdc->suppress_value);
+ vty_out(vty, "Max suppress time: %lld min\n",
+ (long long)bdc->max_suppress_time / 60);
+ vty_out(vty, "Max suppress penalty: %u\n",
+ bdc->ceiling);
+ vty_out(vty, "\n");
+ }
+ } else if (!use_json)
vty_out(vty, "dampening not enabled for %s\n",
get_afi_safi_str(afi, safi, false));
@@ -678,6 +699,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
uint16_t show_flags)
{
struct bgp *bgp;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
bgp = bgp_get_default();
if (bgp == NULL) {
@@ -686,7 +709,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
}
if (!CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL))
- return bgp_print_dampening_parameters(bgp, vty, afi, safi);
+ return bgp_print_dampening_parameters(bgp, vty, afi, safi,
+ use_json);
if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
|| CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
@@ -697,11 +721,12 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
"Unknown"))
continue;
- if (!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON))
+ if (!use_json)
vty_out(vty, "\nFor address family: %s\n\n",
get_afi_safi_str(afi, safi, false));
- bgp_print_dampening_parameters(bgp, vty, afi, safi);
+ bgp_print_dampening_parameters(bgp, vty, afi, safi,
+ use_json);
}
} else {
FOREACH_AFI_SAFI (afi, safi) {
@@ -709,11 +734,12 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
"Unknown"))
continue;
- if (!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON))
+ if (!use_json)
vty_out(vty, "\nFor address family: %s\n",
get_afi_safi_str(afi, safi, false));
- bgp_print_dampening_parameters(bgp, vty, afi, safi);
+ bgp_print_dampening_parameters(bgp, vty, afi, safi,
+ use_json);
}
}
return CMD_SUCCESS;
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 1e95d401aa..5a053a7f34 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -934,7 +934,7 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
strlcat(str_buf, " ", str_size);
/* Retrieve value field */
- pnt = ecom->val + (i * 8);
+ pnt = ecom->val + (i * ecom->unit_size);
/* High-order octet is the type */
type = *pnt++;
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 9316d218a2..2254bc6ba7 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -2191,13 +2191,11 @@ static void bgp_evpn_es_json_vtep_fill(json_object *json_vteps,
{
json_object *json_vtep_entry;
json_object *json_flags;
- char ip_buf[INET6_ADDRSTRLEN];
json_vtep_entry = json_object_new_object();
- json_object_string_add(
- json_vtep_entry, "vtep_ip",
- inet_ntop(AF_INET, &es_vtep->vtep_ip, ip_buf, sizeof(ip_buf)));
+ json_object_string_addf(json_vtep_entry, "vtep_ip", "%pI4",
+ &es_vtep->vtep_ip);
if (es_vtep->flags & (BGP_EVPNES_VTEP_ESR |
BGP_EVPNES_VTEP_ACTIVE)) {
json_flags = json_object_new_array();
@@ -2314,8 +2312,6 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
static void bgp_evpn_es_show_entry_detail(struct vty *vty,
struct bgp_evpn_es *es, json_object *json)
{
- char ip_buf[INET6_ADDRSTRLEN];
-
if (json) {
json_object *json_flags;
json_object *json_incons;
@@ -2338,9 +2334,8 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
json_array_string_add(json_flags, "bypass");
json_object_object_add(json, "flags", json_flags);
}
- json_object_string_add(json, "originator_ip",
- inet_ntop(AF_INET, &es->originator_ip,
- ip_buf, sizeof(ip_buf)));
+ json_object_string_addf(json, "originator_ip", "%pI4",
+ &es->originator_ip);
json_object_int_add(json, "remoteVniCount",
es->remote_es_evi_cnt);
json_object_int_add(json, "vrfCount",
@@ -2456,11 +2451,8 @@ void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail)
}
/* print the array of json-ESs */
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
/* Display specific ES */
@@ -2480,11 +2472,8 @@ void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj)
vty_out(vty, "ESI not found\n");
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
}
/*****************************************************************************/
@@ -3035,12 +3024,8 @@ void bgp_evpn_es_vrf_show(struct vty *vty, bool uj, struct bgp_evpn_es *es)
}
/* print the array of json-ESs */
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
/* Display specific ES VRF */
@@ -3714,13 +3699,11 @@ static void bgp_evpn_es_evi_json_vtep_fill(json_object *json_vteps,
{
json_object *json_vtep_entry;
json_object *json_flags;
- char ip_buf[INET6_ADDRSTRLEN];
json_vtep_entry = json_object_new_object();
- json_object_string_add(
- json_vtep_entry, "vtep_ip",
- inet_ntop(AF_INET, &evi_vtep->vtep_ip, ip_buf, sizeof(ip_buf)));
+ json_object_string_addf(json_vtep_entry, "vtep_ip", "%pI4",
+ &evi_vtep->vtep_ip);
if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD_PER_ES |
BGP_EVPN_EVI_VTEP_EAD_PER_EVI)) {
json_flags = json_object_new_array();
@@ -3891,11 +3874,8 @@ void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail)
(void (*)(struct hash_bucket *,
void *))bgp_evpn_es_evi_show_one_vni_hash_cb,
&wctx);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
/* Display specific ES EVI */
@@ -3929,11 +3909,8 @@ void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
vty_out(vty, "VNI not found\n");
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
/*****************************************************************************
@@ -4661,12 +4638,8 @@ void bgp_evpn_nh_show(struct vty *vty, bool uj)
}
/* print the array of json-ESs */
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
/*****************************************************************************/
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index aced0177ea..f377c8352b 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -377,7 +377,6 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
json_object *json_import_rtl = NULL;
json_object *json_export_rtl = NULL;
char buf2[ETHER_ADDR_STRLEN];
- char originator_ip[BUFSIZ] = {0};
json_import_rtl = json_export_rtl = 0;
@@ -390,19 +389,15 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
json_object_string_add(
json, "rd",
prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
- json_object_string_add(
- json, "originatorIp",
- inet_ntop(AF_INET, &bgp_vrf->originator_ip,
- originator_ip, sizeof(originator_ip)));
+ json_object_string_addf(json, "originatorIp", "%pI4",
+ &bgp_vrf->originator_ip);
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
json_object_string_add(json, "advertiseSviMacIp", "n/a");
json_object_string_add(json, "advertisePip",
bgp_vrf->evpn_info->advertise_pip ?
"Enabled" : "Disabled");
- json_object_string_add(json, "sysIP",
- inet_ntop(AF_INET,
- &bgp_vrf->evpn_info->pip_ip,
- buf1, INET_ADDRSTRLEN));
+ json_object_string_addf(json, "sysIP", "%pI4",
+ &bgp_vrf->evpn_info->pip_ip);
json_object_string_add(json, "sysMac",
prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
buf2, sizeof(buf2)));
@@ -483,7 +478,6 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
json_object *json_import_rtl = NULL;
json_object *json_export_rtl = NULL;
struct bgp *bgp_evpn;
- char buf[BUFSIZ] = {0};
bgp_evpn = bgp_get_evpn();
@@ -497,12 +491,10 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
json_object_string_add(
json, "rd",
prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
- json_object_string_add(json, "originatorIp",
- inet_ntop(AF_INET, &vpn->originator_ip,
- buf, sizeof(buf)));
- json_object_string_add(
- json, "mcastGroup",
- inet_ntop(AF_INET, &vpn->mcast_grp, buf, sizeof(buf)));
+ json_object_string_addf(json, "originatorIp", "%pI4",
+ &vpn->originator_ip);
+ json_object_string_addf(json, "mcastGroup", "%pI4",
+ &vpn->mcast_grp);
/* per vni knob is enabled -- Enabled
* Global knob is enabled -- Active
* default -- Disabled
@@ -933,7 +925,6 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_object *json_export_rtl = NULL;
char buf1[10];
char buf2[INET6_ADDRSTRLEN];
- char buf3[BUFSIZ] = {0};
char rt_buf[25];
char *ecom_str;
struct listnode *node, *nnode;
@@ -956,9 +947,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_object_int_add(json_vni, "vni", bgp->l3vni);
json_object_string_add(json_vni, "type", "L3");
json_object_string_add(json_vni, "inKernel", "True");
- json_object_string_add(json_vni, "originatorIp",
- inet_ntop(AF_INET, &bgp->originator_ip,
- buf3, sizeof(buf3)));
+ json_object_string_addf(json_vni, "originatorIp", "%pI4",
+ &bgp->originator_ip);
json_object_string_add(
json_vni, "rd",
prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
@@ -968,10 +958,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_object_string_add(
json_vni, "advertisePip",
bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
- json_object_string_add(json_vni, "sysIP",
- inet_ntop(AF_INET,
- &bgp->evpn_info->pip_ip, buf3,
- sizeof(buf3)));
+ json_object_string_addf(json_vni, "sysIP", "%pI4",
+ &bgp->evpn_info->pip_ip);
json_object_string_add(json_vni, "sysMAC",
prefix_mac2str(&bgp->evpn_info->pip_rmac,
buf2, sizeof(buf2)));
@@ -1060,7 +1048,6 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
char buf1[10];
char buf2[RD_ADDRSTRLEN];
- char buf3[BUFSIZ] = {0};
char rt_buf[25];
char *ecom_str;
struct listnode *node, *nnode;
@@ -1090,12 +1077,10 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
json_object_string_add(
json_vni, "rd",
prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
- json_object_string_add(json_vni, "originatorIp",
- inet_ntop(AF_INET, &vpn->originator_ip,
- buf3, sizeof(buf3)));
- json_object_string_add(json_vni, "mcastGroup",
- inet_ntop(AF_INET, &vpn->mcast_grp, buf3,
- sizeof(buf3)));
+ json_object_string_addf(json_vni, "originatorIp", "%pI4",
+ &vpn->originator_ip);
+ json_object_string_addf(json_vni, "mcastGroup", "%pI4",
+ &vpn->mcast_grp);
/* per vni knob is enabled -- Enabled
* Global knob is enabled -- Active
* default -- Disabled
@@ -1207,7 +1192,6 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
char rd_str[RD_ADDRSTRLEN];
char buf[BUFSIZ];
int no_display;
- char router_id[BUFSIZ] = {0};
unsigned long output_count = 0;
unsigned long total_count = 0;
@@ -1296,14 +1280,11 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
json_object_int_add(
json, "bgpTableVersion",
tbl_ver);
- json_object_string_add(
+ json_object_string_addf(
json,
"bgpLocalRouterId",
- inet_ntop(
- AF_INET,
- &bgp->router_id,
- router_id,
- sizeof(router_id)));
+ "%pI4",
+ &bgp->router_id);
json_object_int_add(
json,
"defaultLocPrf",
@@ -1364,10 +1345,12 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
json_prefix_info = json_object_new_object();
- json_object_string_add(
- json_prefix_info, "prefix",
- prefix2str((struct prefix_evpn *)p, buf,
- BUFSIZ));
+ prefix2str((struct prefix_evpn *)p, buf,
+ BUFSIZ);
+
+ json_object_string_addf(
+ json_prefix_info, "prefix", "%pFX",
+ (struct prefix_evpn *)p);
json_object_int_add(json_prefix_info,
"prefixLen", p->prefixlen);
@@ -1387,9 +1370,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
if (use_json) {
json_object_int_add(json, "numPrefix", output_count);
json_object_int_add(json, "totalPrefix", total_count);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (output_count == 0)
vty_out(vty, "No prefixes displayed, %ld exist\n",
@@ -4408,14 +4389,8 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
evpn_show_vni(vty, bgp_evpn, vni, json);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_PRETTY
- | JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -4693,11 +4668,8 @@ DEFUN(show_bgp_l2vpn_evpn_route,
evpn_show_all_routes(vty, bgp, type, json, detail);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -4757,11 +4729,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
else
evpn_show_route_rd(vty, bgp, &prd, type, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -4843,11 +4812,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
else
evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -4887,11 +4853,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_esi,
evpn_show_routes_esi(vty, bgp, &esi, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -4957,11 +4920,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5027,11 +4987,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5085,11 +5042,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5148,11 +5102,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
evpn_show_routes_vni_all(vty, bgp, vtep_ip, json, da);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5184,12 +5135,8 @@ DEFPY_HIDDEN(
if (uj)
json = json_object_new_object();
bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5221,12 +5168,8 @@ DEFPY_HIDDEN(
if (uj)
json = json_object_new_object();
bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5258,11 +5201,8 @@ DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
evpn_show_vrf_import_rts(vty, bgp_evpn, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5294,11 +5234,8 @@ DEFUN(show_bgp_l2vpn_evpn_import_rt,
evpn_show_import_rts(vty, bgp, json);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -5781,7 +5718,6 @@ DEFUN (show_bgp_vrf_l3vni_info,
{
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
- char originator_ip[BUFSIZ] = {0};
int idx_vrf = 3;
const char *name = NULL;
struct bgp *bgp = NULL;
@@ -5845,10 +5781,8 @@ DEFUN (show_bgp_vrf_l3vni_info,
prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
} else {
json_object_string_add(json, "vrf", name);
- json_object_string_add(json, "local-ip",
- inet_ntop(AF_INET, &bgp->originator_ip,
- originator_ip,
- sizeof(originator_ip)));
+ json_object_string_addf(json, "local-ip", "%pI4",
+ &bgp->originator_ip);
json_object_int_add(json, "l3vni", bgp->l3vni);
json_object_string_add(
json, "rmac",
@@ -5883,11 +5817,8 @@ DEFUN (show_bgp_vrf_l3vni_info,
prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index 7dda4f0180..fc9fc1e523 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -672,12 +672,8 @@ DEFUN (show_as_path_access_list,
if (aslist)
as_list_show(vty, aslist, json);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -707,12 +703,8 @@ DEFUN (show_as_path_access_list_all,
as_list_show_all(vty, json);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index 11487ed847..8873ca5c0c 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -449,11 +449,7 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
pi, display, json_paths);
}
if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_paths,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json_paths);
+ vty_json(vty, json_paths);
json_paths = NULL;
}
}
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c
index fcb2df9d6f..1bc7b62304 100644
--- a/bgpd/bgp_labelpool.c
+++ b/bgpd/bgp_labelpool.c
@@ -638,10 +638,7 @@ DEFUN(show_bgp_labelpool_summary, show_bgp_labelpool_summary_cmd,
json_object_int_add(json, "LabelChunks", listcount(lp->chunks));
json_object_int_add(json, "Pending", lp->pending_count);
json_object_int_add(json, "Reconnects", lp->reconnect_count);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
vty_out(vty, "Labelpool Summary\n");
vty_out(vty, "-----------------\n");
@@ -738,12 +735,8 @@ DEFUN(show_bgp_labelpool_ledger, show_bgp_labelpool_ledger_cmd,
break;
}
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -833,12 +826,8 @@ DEFUN(show_bgp_labelpool_inuse, show_bgp_labelpool_inuse_cmd,
break;
}
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -911,12 +900,8 @@ DEFUN(show_bgp_labelpool_requests, show_bgp_labelpool_requests_cmd,
break;
}
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -962,12 +947,8 @@ DEFUN(show_bgp_labelpool_chunks, show_bgp_labelpool_chunks_cmd,
vty_out(vty, "%-10u %-10u\n", chunk->first,
chunk->last);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 42077d4e8e..ba66bf3b6e 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -181,6 +181,20 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
}
}
+ /*
+ * If both nexthops are same then check
+ * if they belong to same VRF
+ */
+ if (!compare && bpi1->attr->nh_type != NEXTHOP_TYPE_BLACKHOLE) {
+ if (bpi1->extra && bpi1->extra->bgp_orig && bpi2->extra
+ && bpi2->extra->bgp_orig) {
+ if (bpi1->extra->bgp_orig->vrf_id
+ != bpi2->extra->bgp_orig->vrf_id) {
+ compare = 1;
+ }
+ }
+ }
+
return compare;
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 659029b04c..e24c1ab764 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -779,10 +779,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
* schemes that could be implemented in the future.
*
*/
- for (bpi_ultimate = source_bpi;
- bpi_ultimate->extra && bpi_ultimate->extra->parent;
- bpi_ultimate = bpi_ultimate->extra->parent)
- ;
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
/*
* match parent
@@ -1619,10 +1616,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
if (!CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
/* work back to original route */
- for (bpi_ultimate = path_vpn;
- bpi_ultimate->extra && bpi_ultimate->extra->parent;
- bpi_ultimate = bpi_ultimate->extra->parent)
- ;
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
/*
* if original route was unicast,
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index a33e9800e6..19ae137208 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -588,7 +588,7 @@ static void bgp_nht_ifp_handle(struct interface *ifp, bool up)
{
struct bgp *bgp;
- bgp = bgp_lookup_by_vrf_id(ifp->vrf_id);
+ bgp = ifp->vrf->info;
if (!bgp)
return;
@@ -895,10 +895,11 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match,
resolve_via_default, bnc->bgp->vrf_id);
- /* TBD: handle the failure */
- if (ret == ZCLIENT_SEND_FAILURE)
+ if (ret == ZCLIENT_SEND_FAILURE) {
flog_warn(EC_BGP_ZEBRA_SEND,
"sendmsg_nexthop: zclient_send_message() failed");
+ return;
+ }
if (command == ZEBRA_NEXTHOP_REGISTER)
SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index e15690835a..a05921e7b6 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -57,6 +57,7 @@ static const struct message capcode_str[] = {
{CAPABILITY_CODE_FQDN, "FQDN"},
{CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
{CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
+ {CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart"},
{0}};
/* Minimum sizes for length field of each cap (so not inc. the header) */
@@ -75,6 +76,7 @@ static const size_t cap_minsizes[] = {
[CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
[CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
[CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
+ [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
};
/* value the capability must be a multiple of.
@@ -97,6 +99,7 @@ static const size_t cap_modsizes[] = {
[CAPABILITY_CODE_FQDN] = 1,
[CAPABILITY_CODE_ENHANCED_RR] = 1,
[CAPABILITY_CODE_EXT_MESSAGE] = 1,
+ [CAPABILITY_CODE_LLGR] = 1,
};
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
@@ -1088,7 +1091,7 @@ static bool strict_capability_same(struct peer *peer)
/* peek into option, stores ASN to *as4 if the AS4 capability was found.
* Returns 0 if no as4 found, as4cap value otherwise.
*/
-as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
+as_t peek_for_as4_capability(struct peer *peer, uint16_t length)
{
struct stream *s = BGP_INPUT(peer);
size_t orig_getp = stream_get_getp(s);
@@ -1104,7 +1107,7 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
*/
while (stream_get_getp(s) < end) {
uint8_t opt_type;
- uint8_t opt_length;
+ uint16_t opt_length;
/* Check the length. */
if (stream_get_getp(s) + 2 > end)
@@ -1112,7 +1115,9 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
/* Fetch option type and length. */
opt_type = stream_getc(s);
- opt_length = stream_getc(s);
+ opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
+ ? stream_getw(s)
+ : stream_getc(s);
/* Option length check. */
if (stream_get_getp(s) + opt_length > end)
@@ -1160,7 +1165,8 @@ end:
*
* @param[out] mp_capability @see bgp_capability_parse() for semantics.
*/
-int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
+int bgp_open_option_parse(struct peer *peer, uint16_t length,
+ int *mp_capability)
{
int ret = 0;
uint8_t *error;
@@ -1179,7 +1185,7 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
while (stream_get_getp(s) < end) {
uint8_t opt_type;
- uint8_t opt_length;
+ uint16_t opt_length;
/* Must have at least an OPEN option header */
if (STREAM_READABLE(s) < 2) {
@@ -1191,11 +1197,14 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
/* Fetch option type and length. */
opt_type = stream_getc(s);
- opt_length = stream_getc(s);
+ opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
+ ? stream_getw(s)
+ : stream_getc(s);
/* Option length check. */
if (STREAM_READABLE(s) < opt_length) {
- zlog_info("%s Option length error", peer->host);
+ zlog_info("%s Option length error (%d)", peer->host,
+ opt_length);
bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
@@ -1299,9 +1308,10 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
}
static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
- afi_t afi, safi_t safi, uint8_t code)
+ afi_t afi, safi_t safi, uint8_t code,
+ bool ext_opt_params)
{
- uint8_t cap_len;
+ uint16_t cap_len;
uint8_t orf_len;
unsigned long capp;
unsigned long orfp;
@@ -1315,7 +1325,8 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
stream_putc(s, BGP_OPEN_OPT_CAP);
capp = stream_get_endp(s); /* Set Capability Len Pointer */
- stream_putc(s, 0); /* Capability Length */
+ ext_opt_params ? stream_putw(s, 0)
+ : stream_putc(s, 0); /* Capability Length */
stream_putc(s, code); /* Capability Code */
orfp = stream_get_endp(s); /* Set ORF Len Pointer */
stream_putc(s, 0); /* ORF Length */
@@ -1363,11 +1374,12 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
/* Total Capability Len. */
cap_len = stream_get_endp(s) - capp - 1;
- stream_putc_at(s, capp, cap_len);
+ ext_opt_params ? stream_putw_at(s, capp, cap_len)
+ : stream_putc_at(s, capp, cap_len);
}
static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
- unsigned long cp)
+ bool ext_opt_params)
{
int len;
iana_afi_t pkt_afi;
@@ -1389,7 +1401,8 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
capp = stream_get_endp(s); /* Set Capability Len Pointer */
- stream_putc(s, 0); /* Capability Length */
+ ext_opt_params ? stream_putw(s, 0)
+ : stream_putc(s, 0); /* Capability Length */
stream_putc(s, CAPABILITY_CODE_RESTART);
/* Set Restart Capability Len Pointer */
rcapp = stream_get_endp(s);
@@ -1444,11 +1457,12 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
/* Total Capability Len. */
len = stream_get_endp(s) - capp - 1;
- stream_putc_at(s, capp, len);
+ ext_opt_params ? stream_putw_at(s, capp, len - 1)
+ : stream_putc_at(s, capp, len);
}
static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
- unsigned long cp)
+ bool ext_opt_params)
{
int len;
iana_afi_t pkt_afi;
@@ -1465,7 +1479,8 @@ static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
stream_putc(s, BGP_OPEN_OPT_CAP);
capp = stream_get_endp(s); /* Set Capability Len Pointer */
- stream_putc(s, 0); /* Capability Length */
+ ext_opt_params ? stream_putw(s, 0)
+ : stream_putc(s, 0); /* Capability Length */
stream_putc(s, CAPABILITY_CODE_LLGR);
rcapp = stream_get_endp(s);
@@ -1491,14 +1506,16 @@ static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
/* Total Capability Len. */
len = stream_get_endp(s) - capp - 1;
- stream_putc_at(s, capp, len);
+ ext_opt_params ? stream_putw_at(s, capp, len - 1)
+ : stream_putc_at(s, capp, len);
}
/* Fill in capability open option to the packet. */
-void bgp_open_capability(struct stream *s, struct peer *peer)
+uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
+ bool ext_opt_params)
{
- uint8_t len;
- unsigned long cp, capp, rcapp;
+ uint16_t len;
+ unsigned long cp, capp, rcapp, eopl = 0;
iana_afi_t pkt_afi;
afi_t afi;
safi_t safi;
@@ -1507,16 +1524,26 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
uint8_t afi_safi_count = 0;
int adv_addpath_tx = 0;
- /* Remember current pointer for Opt Parm Len. */
+ /* Non-Ext OP Len. */
cp = stream_get_endp(s);
-
- /* Opt Parm Len. */
stream_putc(s, 0);
+ if (ext_opt_params) {
+ /* Non-Ext OP Len. */
+ stream_putc_at(s, cp, BGP_OPEN_NON_EXT_OPT_LEN);
+
+ /* Non-Ext OP Type */
+ stream_putc(s, BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH);
+
+ /* Extended Opt. Parm. Length */
+ eopl = stream_get_endp(s);
+ stream_putw(s, 0);
+ }
+
/* Do not send capability. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
|| CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY))
- return;
+ return 0;
/* MP capability for configured AFI, SAFI */
FOREACH_AFI_SAFI (afi, safi) {
@@ -1527,7 +1554,9 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
peer->afc_adv[afi][safi] = 1;
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_MP_LEN + 2);
+ ext_opt_params
+ ? stream_putw(s, CAPABILITY_CODE_MP_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc(s, CAPABILITY_CODE_MP);
stream_putc(s, CAPABILITY_CODE_MP_LEN);
stream_putw(s, pkt_afi);
@@ -1547,7 +1576,13 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
*/
SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_ENHE_LEN + 2);
+ ext_opt_params
+ ? stream_putw(s,
+ CAPABILITY_CODE_ENHE_LEN
+ + 2)
+ : stream_putc(s,
+ CAPABILITY_CODE_ENHE_LEN
+ + 2);
stream_putc(s, CAPABILITY_CODE_ENHE);
stream_putc(s, CAPABILITY_CODE_ENHE_LEN);
@@ -1568,25 +1603,29 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
/* Route refresh. */
SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
+ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
stream_putc(s, CAPABILITY_CODE_REFRESH_OLD);
stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
+ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
stream_putc(s, CAPABILITY_CODE_REFRESH);
stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
/* Enhanced Route Refresh. */
SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN + 2);
+ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_ENHANCED_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN + 2);
stream_putc(s, CAPABILITY_CODE_ENHANCED_RR);
stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN);
/* AS4 */
SET_FLAG(peer->cap, PEER_CAP_AS4_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2);
+ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_AS4_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2);
stream_putc(s, CAPABILITY_CODE_AS4);
stream_putc(s, CAPABILITY_CODE_AS4_LEN);
if (peer->change_local_as)
@@ -1598,7 +1637,8 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
/* Extended Message Support */
SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
+ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE);
stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN);
@@ -1617,7 +1657,11 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2);
+ ext_opt_params
+ ? stream_putw(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
+ + 2)
+ : stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
+ + 2);
stream_putc(s, CAPABILITY_CODE_ADDPATH);
stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count);
@@ -1664,9 +1708,11 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
|| CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_ORF_PREFIX_RM)) {
bgp_open_capability_orf(s, peer, afi, safi,
- CAPABILITY_CODE_ORF_OLD);
+ CAPABILITY_CODE_ORF_OLD,
+ ext_opt_params);
bgp_open_capability_orf(s, peer, afi, safi,
- CAPABILITY_CODE_ORF);
+ CAPABILITY_CODE_ORF,
+ ext_opt_params);
}
}
@@ -1674,11 +1720,15 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
+ ext_opt_params
+ ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD);
stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
stream_putc(s, BGP_OPEN_OPT_CAP);
- stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
+ ext_opt_params
+ ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
+ : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
stream_putc(s, CAPABILITY_CODE_DYNAMIC);
stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
}
@@ -1688,7 +1738,8 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */
- stream_putc(s, 0); /* dummy len for now */
+ ext_opt_params ? stream_putw(s, 0)
+ : stream_putc(s, 0); /* Capability Length */
stream_putc(s, CAPABILITY_CODE_FQDN);
capp = stream_get_endp(s);
stream_putc(s, 0); /* dummy len for now */
@@ -1710,7 +1761,9 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
/* Set the lengths straight */
len = stream_get_endp(s) - rcapp - 1;
- stream_putc_at(s, rcapp, len);
+ ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
+ : stream_putc_at(s, rcapp, len);
+
len = stream_get_endp(s) - capp - 1;
stream_putc_at(s, capp, len);
@@ -1721,10 +1774,18 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
cmd_domainname_get());
}
- bgp_peer_send_gr_capability(s, peer, cp);
- bgp_peer_send_llgr_capability(s, peer, cp);
+ bgp_peer_send_gr_capability(s, peer, ext_opt_params);
+ bgp_peer_send_llgr_capability(s, peer, ext_opt_params);
/* Total Opt Parm Len. */
len = stream_get_endp(s) - cp - 1;
- stream_putc_at(s, cp, len);
+
+ if (ext_opt_params) {
+ len = stream_get_endp(s) - eopl - 2;
+ stream_putw_at(s, eopl, len);
+ } else {
+ stream_putc_at(s, cp, len);
+ }
+
+ return len;
}
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 0d616926a2..c04816c006 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -93,10 +93,19 @@ struct graceful_restart_af {
/* Long-lived Graceful Restart */
#define LLGR_F_BIT 0x80
-extern int bgp_open_option_parse(struct peer *, uint8_t, int *);
-extern void bgp_open_capability(struct stream *, struct peer *);
+/* Optional Parameters */
+#define BGP_OPEN_NON_EXT_OPT_LEN 255 /* Non-Ext OP Len. */
+#define BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH 255 /* Non-Ext OP Type */
+#define BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) \
+ (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS) \
+ || CHECK_FLAG(peer->sflags, PEER_STATUS_EXT_OPT_PARAMS_LENGTH))
+
+extern int bgp_open_option_parse(struct peer *peer, uint16_t length,
+ int *mp_capability);
+extern uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
+ bool ext_opt_params);
extern void bgp_capability_vty_out(struct vty *vty, struct peer *peer,
bool use_json, json_object *json_neigh);
-extern as_t peek_for_as4_capability(struct peer *, uint8_t);
+extern as_t peek_for_as4_capability(struct peer *peer, uint16_t length);
#endif /* _QUAGGA_BGP_OPEN_H */
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index de9a89523b..cc0ee9e8f2 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -106,17 +106,14 @@ int bgp_packet_set_marker(struct stream *s, uint8_t type)
* Size field is set to the size of the stream passed.
*
* @param s the stream containing the packet
- * @return the size of the stream
*/
-int bgp_packet_set_size(struct stream *s)
+void bgp_packet_set_size(struct stream *s)
{
int cp;
/* Preserve current pointer. */
cp = stream_get_endp(s);
stream_putw_at(s, BGP_MARKER_SIZE, cp);
-
- return cp;
}
/*
@@ -561,7 +558,7 @@ void bgp_keepalive_send(struct peer *peer)
bgp_packet_set_marker(s, BGP_MSG_KEEPALIVE);
/* Set packet size. */
- (void)bgp_packet_set_size(s);
+ bgp_packet_set_size(s);
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
@@ -608,11 +605,25 @@ void bgp_open_send(struct peer *peer)
stream_putw(s, send_holdtime); /* Hold Time */
stream_put_in_addr(s, &peer->local_id); /* BGP Identifier */
- /* Set capability code. */
- bgp_open_capability(s, peer);
+ /* Set capabilities */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) {
+ (void)bgp_open_capability(s, peer, true);
+ } else {
+ struct stream *tmp = stream_new(STREAM_SIZE(s));
+
+ stream_copy(tmp, s);
+ if (bgp_open_capability(tmp, peer, false)
+ > BGP_OPEN_NON_EXT_OPT_LEN) {
+ stream_free(tmp);
+ (void)bgp_open_capability(s, peer, true);
+ } else {
+ stream_copy(s, tmp);
+ stream_free(tmp);
+ }
+ }
/* Set BGP packet length. */
- (void)bgp_packet_set_size(s);
+ bgp_packet_set_size(s);
if (bgp_debug_neighbor_events(peer))
zlog_debug(
@@ -939,7 +950,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
}
/* Set packet size. */
- (void)bgp_packet_set_size(s);
+ bgp_packet_set_size(s);
if (bgp_debug_neighbor_events(peer)) {
if (!orf_refresh)
@@ -997,7 +1008,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
}
/* Set packet size. */
- (void)bgp_packet_set_size(s);
+ bgp_packet_set_size(s);
/* Add packet to the peer. */
bgp_packet_add(peer, s);
@@ -1136,7 +1147,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
{
int ret;
uint8_t version;
- uint8_t optlen;
+ uint16_t optlen;
uint16_t holdtime;
uint16_t send_holdtime;
as_t remote_as;
@@ -1157,19 +1168,40 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
memcpy(notify_data_remote_id, stream_pnt(peer->curr), 4);
remote_id.s_addr = stream_get_ipv4(peer->curr);
- /* Receive OPEN message log */
- if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s rcv OPEN, version %d, remote-as (in open) %u, holdtime %d, id %pI4",
- peer->host, version, remote_as, holdtime, &remote_id);
-
/* BEGIN to read the capability here, but dont do it yet */
mp_capability = 0;
optlen = stream_getc(peer->curr);
+ /* Extended Optional Parameters Length for BGP OPEN Message */
+ if (optlen == BGP_OPEN_NON_EXT_OPT_LEN
+ || CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) {
+ uint8_t opttype;
+
+ opttype = stream_getc(peer->curr);
+ if (opttype == BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH) {
+ optlen = stream_getw(peer->curr);
+ SET_FLAG(peer->sflags,
+ PEER_STATUS_EXT_OPT_PARAMS_LENGTH);
+ }
+ }
+
+ /* Receive OPEN message log */
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s rcv OPEN%s, version %d, remote-as (in open) %u, holdtime %d, id %pI4",
+ peer->host,
+ CHECK_FLAG(peer->sflags,
+ PEER_STATUS_EXT_OPT_PARAMS_LENGTH)
+ ? " (Extended)"
+ : "",
+ version, remote_as, holdtime, &remote_id);
+
if (optlen != 0) {
/* If not enough bytes, it is an error. */
if (STREAM_READABLE(peer->curr) < optlen) {
+ flog_err(EC_BGP_PKT_OPEN,
+ "%s: stream has not enough bytes (%u)",
+ peer->host, optlen);
bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return BGP_Stop;
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index d69c862304..280d3ec174 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -77,7 +77,7 @@ extern void bgp_update_implicit_eors(struct peer *);
extern void bgp_check_update_delay(struct bgp *);
extern int bgp_packet_set_marker(struct stream *s, uint8_t type);
-extern int bgp_packet_set_size(struct stream *s);
+extern void bgp_packet_set_size(struct stream *s);
extern int bgp_generate_updgrp_packets(struct thread *);
extern int bgp_process_packet(struct thread *);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index e51bf55696..8d0bbf75c1 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -548,6 +548,25 @@ void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
snprintf(buf, buf_len, "path %s", pi->peer->host);
}
+
+/*
+ * Get the ultimate path info.
+ */
+struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
+{
+ struct bgp_path_info *bpi_ultimate;
+
+ if (info->sub_type != BGP_ROUTE_IMPORTED)
+ return info;
+
+ for (bpi_ultimate = info;
+ bpi_ultimate->extra && bpi_ultimate->extra->parent;
+ bpi_ultimate = bpi_ultimate->extra->parent)
+ ;
+
+ return bpi_ultimate;
+}
+
/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
*/
static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
@@ -587,6 +606,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
bool old_proxy;
bool new_proxy;
bool new_origin, exist_origin;
+ struct bgp_path_info *bpi_ultimate;
*paths_eq = 0;
@@ -598,9 +618,11 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
return 0;
}
- if (debug)
- bgp_path_info_path_with_addpath_rx_str(new, new_buf,
+ if (debug) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
+ bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
sizeof(new_buf));
+ }
if (exist == NULL) {
*reason = bgp_path_selection_first;
@@ -611,7 +633,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
- bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
+ bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
sizeof(exist_buf));
zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
pfx_buf, bgp->name_pretty, new_buf, new->flags,
@@ -859,6 +882,14 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
return 0;
}
+ /* Here if these are imported routes then get ultimate pi for
+ * path compare.
+ */
+ new = bgp_get_imported_bpi_ultimate(new);
+ exist = bgp_get_imported_bpi_ultimate(exist);
+ newattr = new->attr;
+ existattr = exist->attr;
+
/* 4. AS path length check. */
if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
int exist_hops = aspath_count_hops(existattr->aspath);
@@ -2058,7 +2089,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
if ((CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
&& IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
- || (!reflect
+ || (!reflect && !transparent
&& IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
&& peer->shared_network
&& (from == bgp->peer_self
@@ -8384,7 +8415,6 @@ static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
{
int len = 0;
char buf[BUFSIZ];
- char buf2[BUFSIZ];
if (p->family == AF_INET) {
if (!json) {
@@ -8395,8 +8425,7 @@ static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
&p->u.prefix, buf,
BUFSIZ));
json_object_int_add(json, "prefixLen", p->prefixlen);
- prefix2str(p, buf2, PREFIX_STRLEN);
- json_object_string_add(json, "network", buf2);
+ json_object_string_addf(json, "network", "%pFX", p);
json_object_int_add(json, "version", dest->version);
}
} else if (p->family == AF_ETHERNET) {
@@ -8420,8 +8449,7 @@ static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
&p->u.prefix, buf,
BUFSIZ));
json_object_int_add(json, "prefixLen", p->prefixlen);
- prefix2str(p, buf2, PREFIX_STRLEN);
- json_object_string_add(json, "network", buf2);
+ json_object_string_addf(json, "network", "%pFX", p);
json_object_int_add(json, "version", dest->version);
}
}
@@ -8733,14 +8761,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
} else if (safi == SAFI_EVPN) {
if (json_paths) {
- char buf[BUFSIZ] = {0};
-
json_nexthop_global = json_object_new_object();
- json_object_string_add(json_nexthop_global, "ip",
- inet_ntop(AF_INET,
- &attr->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_nexthop_global, "ip",
+ "%pI4", &attr->nexthop);
if (path->peer->hostname)
json_object_string_add(json_nexthop_global,
@@ -8768,16 +8792,13 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
} else if (safi == SAFI_FLOWSPEC) {
if (attr->nexthop.s_addr != INADDR_ANY) {
if (json_paths) {
- char buf[BUFSIZ] = {0};
-
json_nexthop_global = json_object_new_object();
json_object_string_add(json_nexthop_global,
"afi", "ipv4");
- json_object_string_add(
- json_nexthop_global, "ip",
- inet_ntop(AF_INET, &attr->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_nexthop_global,
+ "ip", "%pI4",
+ &attr->nexthop);
if (path->peer->hostname)
json_object_string_add(
@@ -8807,14 +8828,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
} else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
if (json_paths) {
- char buf[BUFSIZ] = {0};
-
json_nexthop_global = json_object_new_object();
- json_object_string_add(json_nexthop_global, "ip",
- inet_ntop(AF_INET,
- &attr->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_nexthop_global, "ip",
+ "%pI4", &attr->nexthop);
if (path->peer->hostname)
json_object_string_add(json_nexthop_global,
@@ -8843,14 +8860,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
/* IPv6 Next Hop */
else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
- char buf[BUFSIZ];
-
if (json_paths) {
json_nexthop_global = json_object_new_object();
- json_object_string_add(
- json_nexthop_global, "ip",
- inet_ntop(AF_INET6, &attr->mp_nexthop_global,
- buf, BUFSIZ));
+ json_object_string_addf(json_nexthop_global, "ip",
+ "%pI6",
+ &attr->mp_nexthop_global);
if (path->peer->hostname)
json_object_string_add(json_nexthop_global,
@@ -8868,11 +8882,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
|| (path->peer->conf_if)) {
json_nexthop_ll = json_object_new_object();
- json_object_string_add(
- json_nexthop_ll, "ip",
- inet_ntop(AF_INET6,
- &attr->mp_nexthop_local, buf,
- BUFSIZ));
+ json_object_string_addf(
+ json_nexthop_ll, "ip", "%pI6",
+ &attr->mp_nexthop_local);
if (path->peer->hostname)
json_object_string_add(
@@ -9116,8 +9128,7 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
BUFSIZ));
json_object_int_add(json_net, "prefixLen",
p->prefixlen);
- prefix2str(p, buff, PREFIX_STRLEN);
- json_object_string_add(json_net, "network", buff);
+ json_object_string_addf(json_net, "network", "%pFX", p);
}
} else
route_vty_out_route(dest, p, vty, NULL, wide);
@@ -9125,42 +9136,27 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
/* Print attribute */
if (attr) {
if (use_json) {
- char buf[BUFSIZ] = {0};
-
if (p->family == AF_INET
&& (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
- json_object_string_add(
- json_net, "nextHop",
- inet_ntop(
- AF_INET,
- &attr->mp_nexthop_global_in,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_net, "nextHop", "%pI4",
+ &attr->mp_nexthop_global_in);
else
- json_object_string_add(
- json_net, "nextHop",
- inet_ntop(AF_INET,
- &attr->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(
+ json_net, "nextHop", "%pI4",
+ &attr->nexthop);
} else if (p->family == AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
- char buf[BUFSIZ];
-
- json_object_string_add(
- json_net, "nextHopGlobal",
- inet_ntop(AF_INET6,
- &attr->mp_nexthop_global, buf,
- BUFSIZ));
+ json_object_string_addf(
+ json_net, "nextHopGlobal", "%pI6",
+ &attr->mp_nexthop_global);
} else if (p->family == AF_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
- char buf[BUFSIZ] = {0};
-
- json_object_string_add(
- json_net, "nextHop",
- inet_ntop(AF_INET,
- &attr->mp_nexthop_global_in,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_net, "nextHop", "%pI4",
+ &attr->mp_nexthop_global_in);
}
if (attr->flag
@@ -9279,25 +9275,19 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
|| (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
- char buf[BUFSIZ] = {0};
-
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
if (json)
- json_object_string_add(
- json_out, "mpNexthopGlobalIn",
- inet_ntop(AF_INET,
- &attr->mp_nexthop_global_in,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_out, "mpNexthopGlobalIn", "%pI4",
+ &attr->mp_nexthop_global_in);
else
vty_out(vty, "%-16pI4",
&attr->mp_nexthop_global_in);
} else {
if (json)
- json_object_string_add(
- json_out, "nexthop",
- inet_ntop(AF_INET, &attr->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_out, "nexthop",
+ "%pI4", &attr->nexthop);
else
vty_out(vty, "%-16pI4", &attr->nexthop);
}
@@ -9309,11 +9299,9 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
if (json)
- json_object_string_add(
- json_out, "mpNexthopGlobalIn",
- inet_ntop(AF_INET6,
- &attr->mp_nexthop_global,
- buf_a, sizeof(buf_a)));
+ json_object_string_addf(
+ json_out, "mpNexthopGlobalIn", "%pI6",
+ &attr->mp_nexthop_global);
else
vty_out(vty, "%s",
inet_ntop(AF_INET6,
@@ -9887,14 +9875,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
if (json_paths) {
- char buf[BUFSIZ] = {0};
-
json_object_int_add(json_path, "aggregatorAs",
attr->aggregator_as);
- json_object_string_add(json_path, "aggregatorId",
- inet_ntop(AF_INET,
- &attr->aggregator_addr,
- buf, sizeof(buf)));
+ json_object_string_addf(json_path, "aggregatorId",
+ "%pI4", &attr->aggregator_addr);
} else {
vty_out(vty, ", (aggregated by %u %pI4)",
attr->aggregator_as, &attr->aggregator_addr);
@@ -9944,16 +9928,12 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
|| bn_p->family == AF_EVPN)
&& (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
- char buf[BUFSIZ] = {0};
-
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
if (json_paths) {
- json_object_string_add(
- json_nexthop_global, "ip",
- inet_ntop(AF_INET,
- &attr->mp_nexthop_global_in,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_nexthop_global, "ip", "%pI4",
+ &attr->mp_nexthop_global_in);
if (path->peer->hostname)
json_object_string_add(
@@ -9970,10 +9950,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
} else {
if (json_paths) {
- json_object_string_add(
- json_nexthop_global, "ip",
- inet_ntop(AF_INET, &attr->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_nexthop_global,
+ "ip", "%pI4",
+ &attr->nexthop);
if (path->peer->hostname)
json_object_string_add(
@@ -9995,10 +9974,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
"ipv4");
} else {
if (json_paths) {
- json_object_string_add(
- json_nexthop_global, "ip",
- inet_ntop(AF_INET6, &attr->mp_nexthop_global,
- buf, INET6_ADDRSTRLEN));
+ json_object_string_addf(json_nexthop_global, "ip",
+ "%pI6",
+ &attr->mp_nexthop_global);
if (path->peer->hostname)
json_object_string_add(json_nexthop_global,
@@ -10070,16 +10048,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " from :: ");
}
- if (json_paths) {
- char buf[BUFSIZ] = {0};
-
- json_object_string_add(json_peer, "routerId",
- inet_ntop(AF_INET,
- &bgp->router_id, buf,
- sizeof(buf)));
- } else {
+ if (json_paths)
+ json_object_string_addf(json_peer, "routerId", "%pI4",
+ &bgp->router_id);
+ else
vty_out(vty, "(%pI4)", &bgp->router_id);
- }
}
/* We RXed this path from one of our peers */
@@ -10090,10 +10063,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
sockunion2str(&path->peer->su,
buf,
SU_ADDRSTRLEN));
- json_object_string_add(json_peer, "routerId",
- inet_ntop(AF_INET,
- &path->peer->remote_id,
- buf1, sizeof(buf1)));
+ json_object_string_addf(json_peer, "routerId", "%pI4",
+ &path->peer->remote_id);
if (path->peer->hostname)
json_object_string_add(json_peer, "hostname",
@@ -10193,10 +10164,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
if (json_paths) {
json_nexthop_ll = json_object_new_object();
- json_object_string_add(
- json_nexthop_ll, "ip",
- inet_ntop(AF_INET6, &attr->mp_nexthop_local,
- buf, INET6_ADDRSTRLEN));
+ json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
+ &attr->mp_nexthop_local);
if (path->peer->hostname)
json_object_string_add(json_nexthop_ll,
@@ -10459,10 +10428,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
if (json_paths)
- json_object_string_add(
- json_path, "originatorId",
- inet_ntop(AF_INET, &attr->originator_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_path,
+ "originatorId", "%pI4",
+ &attr->originator_id);
else
vty_out(vty, " Originator: %pI4",
&attr->originator_id);
@@ -10694,21 +10662,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
-static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
- const char *prefix_list_str, afi_t afi,
- safi_t safi, enum bgp_show_type type);
-static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
- const char *filter, afi_t afi, safi_t safi,
- enum bgp_show_type type);
-static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
- const char *rmap_str, afi_t afi, safi_t safi,
- enum bgp_show_type type);
-static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
- const char *com, int exact, afi_t afi,
- safi_t safi);
-static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
- const char *prefix, afi_t afi, safi_t safi,
- enum bgp_show_type type);
static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
afi_t afi, safi_t safi, enum bgp_show_type type,
bool use_json);
@@ -11306,7 +11259,6 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
struct peer *peer;
struct listnode *node, *nnode;
char buf1[RD_ADDRSTRLEN];
- char prefix_str[BUFSIZ];
int count = 0;
int best = 0;
int suppress = 0;
@@ -11360,8 +11312,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
dest->version);
} else {
- json_object_string_add(json, "prefix",
- prefix2str(p, prefix_str, sizeof(prefix_str)));
+ json_object_string_addf(json, "prefix", "%pFX", p);
json_object_int_add(json, "version", dest->version);
}
@@ -11733,10 +11684,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
}
if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY |
- JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (!display) {
vty_out(vty, "%% Network not in table\n");
@@ -12071,45 +12019,28 @@ DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
return ret;
}
-/* BGP route print out function without JSON */
-DEFPY(show_ip_bgp, show_ip_bgp_cmd,
+DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
" [" BGP_SAFI_WITH_LABEL_CMD_STR
- "]]\
- <[all$all] dampening <parameters>\
- |route-map WORD\
- |prefix-list WORD\
- |filter-list AS_PATH_FILTER_NAME\
- |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
- |A.B.C.D/M longer-prefixes\
- |X:X::X:X/M longer-prefixes\
- >",
+ "]] [all$all] dampening parameters [json]",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
"Display the entries for all address families\n"
"Display detailed information about dampening\n"
"Display detail of configured dampening parameters\n"
- "Display routes matching the route-map\n"
- "A route-map to match on\n"
- "Display routes conforming to the prefix-list\n"
- "Prefix-list name\n"
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n"
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n"
- "Exact match of the communities\n"
- "IPv4 prefix\n"
- "Display route and more specific routes\n"
- "IPv6 prefix\n"
- "Display route and more specific routes\n")
+ JSON_STR)
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
- int exact_match = 0;
struct bgp *bgp = NULL;
int idx = 0;
uint16_t show_flags = 0;
+ bool uj = use_json(argc, argv);
+
+ if (uj) {
+ argc--;
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ }
/* [<ipv4|ipv6> [all]] */
if (all) {
@@ -12126,43 +12057,11 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
if (!idx)
return CMD_WARNING;
- if (argv_find(argv, argc, "dampening", &idx)) {
- if (argv_find(argv, argc, "parameters", &idx))
- return bgp_show_dampening_parameters(vty, afi, safi,
- show_flags);
- }
-
- if (argv_find(argv, argc, "prefix-list", &idx))
- return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
- safi, bgp_show_type_prefix_list);
-
- if (argv_find(argv, argc, "filter-list", &idx))
- return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
- safi, bgp_show_type_filter_list);
-
- if (argv_find(argv, argc, "route-map", &idx))
- return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
- safi, bgp_show_type_route_map);
-
- if (argv_find(argv, argc, "community-list", &idx)) {
- const char *clist_number_or_name = argv[++idx]->arg;
- if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
- exact_match = 1;
- return bgp_show_community_list(vty, bgp, clist_number_or_name,
- exact_match, afi, safi);
- }
- /* prefix-longer */
- if (argv_find(argv, argc, "A.B.C.D/M", &idx)
- || argv_find(argv, argc, "X:X::X:X/M", &idx))
- return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
- safi,
- bgp_show_type_prefix_longer);
-
- return CMD_WARNING;
+ return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
}
-/* BGP route print out function with JSON */
-DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
+/* BGP route print out function */
+DEFPY(show_ip_bgp, show_ip_bgp_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
" [" BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
@@ -12174,9 +12073,15 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
|accept-own|accept-own-nexthop|route-filter-v6\
|route-filter-v4|route-filter-translated-v6\
|route-filter-translated-v4] [exact-match]\
+ |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
+ |filter-list AS_PATH_FILTER_NAME\
+ |prefix-list WORD\
+ |route-map WORD\
|rpki <invalid|valid|notfound>\
|version (1-4294967295)\
|alias ALIAS_NAME\
+ |A.B.C.D/M longer-prefixes\
+ |X:X::X:X/M longer-prefixes\
] [json$uj [detail$detail] | wide$wide]",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
@@ -12201,6 +12106,16 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
"RT translated VPNv6 route filtering (well-known community)\n"
"RT translated VPNv4 route filtering (well-known community)\n"
"Exact match of the communities\n"
+ "Community-list number\n"
+ "Community-list name\n"
+ "Display routes matching the community-list\n"
+ "Exact match of the communities\n"
+ "Display routes conforming to the filter-list\n"
+ "Regular expression access list name\n"
+ "Display routes conforming to the prefix-list\n"
+ "Prefix-list name\n"
+ "Display routes matching the route-map\n"
+ "A route-map to match on\n"
"RPKI route types\n"
"A valid path as determined by rpki\n"
"A invalid path as determined by rpki\n"
@@ -12208,19 +12123,23 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
"Display prefixes with matching version numbers\n"
"Version number and above\n"
"Display prefixes with matching BGP community alias\n"
- "BGP community alias\n" JSON_STR
+ "BGP community alias\n"
+ "IPv4 prefix\n"
+ "Display route and more specific routes\n"
+ "IPv6 prefix\n"
+ "Display route and more specific routes\n"
+ JSON_STR
"Display detailed version of JSON output\n"
"Increase table width for longer prefixes\n")
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
enum bgp_show_type sh_type = bgp_show_type_normal;
+ void *output_arg = NULL;
struct bgp *bgp = NULL;
int idx = 0;
int exact_match = 0;
char *community = NULL;
- char *prefix_version = NULL;
- char *bgp_community_alias = NULL;
bool first = true;
uint16_t show_flags = 0;
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
@@ -12283,6 +12202,75 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
sh_type = bgp_show_type_community_all;
}
+ if (argv_find(argv, argc, "community-list", &idx)) {
+ const char *clist_number_or_name = argv[++idx]->arg;
+ struct community_list *list;
+
+ if (argv_find(argv, argc, "exact-match", &idx))
+ exact_match = 1;
+
+ list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
+ COMMUNITY_LIST_MASTER);
+ if (list == NULL) {
+ vty_out(vty,
+ "%% %s is not a valid community-list name\n",
+ clist_number_or_name);
+ return CMD_WARNING;
+ }
+
+ if (exact_match)
+ sh_type = bgp_show_type_community_list_exact;
+ else
+ sh_type = bgp_show_type_community_list;
+ output_arg = list;
+ }
+
+ if (argv_find(argv, argc, "filter-list", &idx)) {
+ const char *filter = argv[++idx]->arg;
+ struct as_list *as_list;
+
+ as_list = as_list_lookup(filter);
+ if (as_list == NULL) {
+ vty_out(vty,
+ "%% %s is not a valid AS-path access-list name\n",
+ filter);
+ return CMD_WARNING;
+ }
+
+ sh_type = bgp_show_type_filter_list;
+ output_arg = as_list;
+ }
+
+ if (argv_find(argv, argc, "prefix-list", &idx)) {
+ const char *prefix_list_str = argv[++idx]->arg;
+ struct prefix_list *plist;
+
+ plist = prefix_list_lookup(afi, prefix_list_str);
+ if (plist == NULL) {
+ vty_out(vty, "%% %s is not a valid prefix-list name\n",
+ prefix_list_str);
+ return CMD_WARNING;
+ }
+
+ sh_type = bgp_show_type_prefix_list;
+ output_arg = plist;
+ }
+
+ if (argv_find(argv, argc, "route-map", &idx)) {
+ const char *rmap_str = argv[++idx]->arg;
+ struct route_map *rmap;
+
+ rmap = route_map_lookup_by_name(rmap_str);
+ if (!rmap) {
+ vty_out(vty, "%% %s is not a valid route-map name\n",
+ rmap_str);
+ return CMD_WARNING;
+ }
+
+ sh_type = bgp_show_type_route_map;
+ output_arg = rmap;
+ }
+
if (argv_find(argv, argc, "rpki", &idx)) {
sh_type = bgp_show_type_rpki;
if (argv_find(argv, argc, "valid", &idx))
@@ -12294,13 +12282,28 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
/* Display prefixes with matching version numbers */
if (argv_find(argv, argc, "version", &idx)) {
sh_type = bgp_show_type_prefix_version;
- prefix_version = argv[idx + 1]->arg;
+ output_arg = argv[idx + 1]->arg;
}
/* Display prefixes with matching BGP community alias */
if (argv_find(argv, argc, "alias", &idx)) {
sh_type = bgp_show_type_community_alias;
- bgp_community_alias = argv[idx + 1]->arg;
+ output_arg = argv[idx + 1]->arg;
+ }
+
+ /* prefix-longer */
+ if (argv_find(argv, argc, "A.B.C.D/M", &idx)
+ || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
+ const char *prefix_str = argv[idx]->arg;
+ struct prefix p;
+
+ if (!str2prefix(prefix_str, &p)) {
+ vty_out(vty, "%% Malformed Prefix\n");
+ return CMD_WARNING;
+ }
+
+ sh_type = bgp_show_type_prefix_longer;
+ output_arg = &p;
}
if (!all) {
@@ -12309,17 +12312,10 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
return bgp_show_community(vty, bgp, community,
exact_match, afi, safi,
show_flags);
- else if (prefix_version)
- return bgp_show(vty, bgp, afi, safi, sh_type,
- prefix_version, show_flags,
- rpki_target_state);
- else if (bgp_community_alias)
+ else
return bgp_show(vty, bgp, afi, safi, sh_type,
- bgp_community_alias, show_flags,
+ output_arg, show_flags,
rpki_target_state);
- else
- return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
- show_flags, rpki_target_state);
} else {
/* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
* AFI_IP6 */
@@ -12354,19 +12350,9 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
bgp_show_community(vty, bgp, community,
exact_match, afi,
safi, show_flags);
- else if (prefix_version)
- return bgp_show(vty, bgp, afi, safi,
- sh_type, prefix_version,
- show_flags,
- rpki_target_state);
- else if (bgp_community_alias)
- return bgp_show(
- vty, bgp, afi, safi, sh_type,
- bgp_community_alias, show_flags,
- rpki_target_state);
else
bgp_show(vty, bgp, afi, safi, sh_type,
- NULL, show_flags,
+ output_arg, show_flags,
rpki_target_state);
if (uj)
vty_out(vty, "}\n");
@@ -12396,14 +12382,9 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
bgp_show_community(vty, bgp, community,
exact_match, afi,
safi, show_flags);
- else if (prefix_version)
- return bgp_show(vty, bgp, afi, safi,
- sh_type, prefix_version,
- show_flags,
- rpki_target_state);
else
bgp_show(vty, bgp, afi, safi, sh_type,
- NULL, show_flags,
+ output_arg, show_flags,
rpki_target_state);
if (uj)
vty_out(vty, "}\n");
@@ -12591,59 +12572,6 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
return rc;
}
-static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
- const char *prefix_list_str, afi_t afi,
- safi_t safi, enum bgp_show_type type)
-{
- struct prefix_list *plist;
- uint16_t show_flags = 0;
-
- plist = prefix_list_lookup(afi, prefix_list_str);
- if (plist == NULL) {
- vty_out(vty, "%% %s is not a valid prefix-list name\n",
- prefix_list_str);
- return CMD_WARNING;
- }
-
- return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
- RPKI_NOT_BEING_USED);
-}
-
-static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
- const char *filter, afi_t afi, safi_t safi,
- enum bgp_show_type type)
-{
- struct as_list *as_list;
- uint16_t show_flags = 0;
-
- as_list = as_list_lookup(filter);
- if (as_list == NULL) {
- vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
- filter);
- return CMD_WARNING;
- }
-
- return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
- RPKI_NOT_BEING_USED);
-}
-
-static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
- const char *rmap_str, afi_t afi, safi_t safi,
- enum bgp_show_type type)
-{
- struct route_map *rmap;
- uint16_t show_flags = 0;
-
- rmap = route_map_lookup_by_name(rmap_str);
- if (!rmap) {
- vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
- return CMD_WARNING;
- }
-
- return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
- RPKI_NOT_BEING_USED);
-}
-
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
const char *comstr, int exact, afi_t afi,
safi_t safi, uint16_t show_flags)
@@ -12666,47 +12594,6 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp,
return ret;
}
-static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
- const char *com, int exact, afi_t afi,
- safi_t safi)
-{
- struct community_list *list;
- uint16_t show_flags = 0;
-
- list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
- if (list == NULL) {
- vty_out(vty, "%% %s is not a valid community-list name\n", com);
- return CMD_WARNING;
- }
-
- return bgp_show(vty, bgp, afi, safi,
- (exact ? bgp_show_type_community_list_exact
- : bgp_show_type_community_list),
- list, show_flags, RPKI_NOT_BEING_USED);
-}
-
-static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
- const char *prefix, afi_t afi, safi_t safi,
- enum bgp_show_type type)
-{
- int ret;
- struct prefix *p;
- uint16_t show_flags = 0;
-
- p = prefix_new();
-
- ret = str2prefix(prefix, p);
- if (!ret) {
- vty_out(vty, "%% Malformed Prefix\n");
- return CMD_WARNING;
- }
-
- ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
- RPKI_NOT_BEING_USED);
- prefix_free(&p);
- return ret;
-}
-
enum bgp_stats {
BGP_STATS_MAXBITLEN = 0,
BGP_STATS_RIB,
@@ -13262,9 +13149,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
json, "recommended",
"Please report this bug, with the above command output");
}
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (peer->hostname
@@ -13435,15 +13320,12 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
json_object *json_ocode, bool wide)
{
uint64_t version = table ? table->version : 0;
- char buf[BUFSIZ] = {0};
if (*header1) {
if (json) {
json_object_int_add(json, "bgpTableVersion", version);
- json_object_string_add(json, "bgpLocalRouterId",
- inet_ntop(AF_INET,
- &bgp->router_id, buf,
- sizeof(buf)));
+ json_object_string_addf(json, "bgpLocalRouterId",
+ "%pI4", &bgp->router_id);
json_object_int_add(json, "defaultLocPrf",
bgp->default_local_pref);
json_object_int_add(json, "localAS", bgp->as);
@@ -13509,15 +13391,11 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (type == bgp_show_adj_route_advertised && subgrp
&& CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
- char buf[BUFSIZ] = {0};
-
if (use_json) {
json_object_int_add(json, "bgpTableVersion",
table->version);
- json_object_string_add(json, "bgpLocalRouterId",
- inet_ntop(AF_INET,
- &bgp->router_id, buf,
- sizeof(buf)));
+ json_object_string_addf(json, "bgpLocalRouterId",
+ "%pI4", &bgp->router_id);
json_object_int_add(json, "defaultLocPrf",
bgp->default_local_pref);
json_object_int_add(json, "localAS", bgp->as);
@@ -13831,10 +13709,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
json_object_int_add(json, "filteredPrefixCounter",
filtered_count);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
-
/*
* These fields only give up ownership to `json` when `header1`
* is used (set to zero). See code in `show_adj_route` and
@@ -13845,7 +13719,7 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
json_object_free(json_ocode);
}
- json_object_free(json);
+ vty_json(vty, json);
} else if (output_count > 0) {
if (filtered_count > 0)
vty_out(vty,
@@ -15168,10 +15042,10 @@ void bgp_route_init(void)
install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
- install_element(VIEW_NODE, &show_ip_bgp_cmd);
install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
- install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_cmd);
install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 2fd80495d9..4cc56c8649 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -633,6 +633,8 @@ extern struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
struct prefix_rd *prd);
extern struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path);
extern struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path);
+extern struct bgp_path_info *
+bgp_get_imported_bpi_ultimate(struct bgp_path_info *info);
extern void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi);
extern void bgp_path_info_extra_free(struct bgp_path_info_extra **extra);
extern void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index aa59499b04..c42e3c9b94 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -725,6 +725,57 @@ static const struct route_map_rule_cmd
route_match_ip_next_hop_prefix_list_free
};
+/* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
+static enum route_map_cmd_result_t
+route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
+ void *object)
+{
+ struct prefix_list *plist;
+ struct bgp_path_info *path;
+ struct prefix_ipv6 p;
+
+ if (prefix->family == AF_INET6) {
+ path = object;
+ p.family = AF_INET6;
+ p.prefix = path->attr->mp_nexthop_global;
+ p.prefixlen = IPV6_MAX_BITLEN;
+
+ plist = prefix_list_lookup(AFI_IP6, (char *)rule);
+ if (!plist)
+ return RMAP_NOMATCH;
+
+ if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
+ return RMAP_MATCH;
+
+ if (path->attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ p.prefix = path->attr->mp_nexthop_local;
+ if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
+ return RMAP_MATCH;
+ }
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
+{
+ return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd
+ route_match_ipv6_next_hop_prefix_list_cmd = {
+ "ipv6 next-hop prefix-list",
+ route_match_ipv6_next_hop_prefix_list,
+ route_match_ipv6_next_hop_prefix_list_compile,
+ route_match_ipv6_next_hop_prefix_list_free
+};
+
/* `match ip next-hop type <blackhole>' */
static enum route_map_cmd_result_t
@@ -1148,7 +1199,7 @@ route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
return RMAP_NOMATCH;
- if (path->extra == NULL)
+ if (path->extra == NULL || path->extra->bgp_orig == NULL)
return RMAP_NOMATCH;
if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
@@ -3023,10 +3074,60 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
route_match_ipv6_address_free
};
+/* `match ipv6 next-hop ACCESSLIST6_NAME' */
+static enum route_map_cmd_result_t
+route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
+{
+ struct bgp_path_info *path;
+ struct access_list *alist;
+ struct prefix_ipv6 p;
+
+ if (prefix->family == AF_INET6) {
+ path = object;
+ p.family = AF_INET6;
+ p.prefix = path->attr->mp_nexthop_global;
+ p.prefixlen = IPV6_MAX_BITLEN;
+
+ alist = access_list_lookup(AFI_IP6, (char *)rule);
+ if (!alist)
+ return RMAP_NOMATCH;
+
+ if (access_list_apply(alist, &p) == FILTER_PERMIT)
+ return RMAP_MATCH;
+
+ if (path->attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ p.prefix = path->attr->mp_nexthop_local;
+ if (access_list_apply(alist, &p) == FILTER_PERMIT)
+ return RMAP_MATCH;
+ }
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_compile(const char *arg)
+{
+ return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
+ "ipv6 next-hop",
+ route_match_ipv6_next_hop,
+ route_match_ipv6_next_hop_compile,
+ route_match_ipv6_next_hop_free
+};
+
/* `match ipv6 next-hop IP_ADDRESS' */
static enum route_map_cmd_result_t
-route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
+route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
+ void *object)
{
struct in6_addr *addr = rule;
struct bgp_path_info *path;
@@ -3043,7 +3144,7 @@ route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
return RMAP_NOMATCH;
}
-static void *route_match_ipv6_next_hop_compile(const char *arg)
+static void *route_match_ipv6_next_hop_address_compile(const char *arg)
{
struct in6_addr *address;
int ret;
@@ -3059,16 +3160,16 @@ static void *route_match_ipv6_next_hop_compile(const char *arg)
return address;
}
-static void route_match_ipv6_next_hop_free(void *rule)
+static void route_match_ipv6_next_hop_address_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
-static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
- "ipv6 next-hop",
- route_match_ipv6_next_hop,
- route_match_ipv6_next_hop_compile,
- route_match_ipv6_next_hop_free
+static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
+ "ipv6 next-hop address",
+ route_match_ipv6_next_hop_address,
+ route_match_ipv6_next_hop_address_compile,
+ route_match_ipv6_next_hop_address_free
};
/* `match ip next-hop IP_ADDRESS' */
@@ -6047,10 +6148,48 @@ DEFUN_YANG (no_set_aggregator_as,
DEFUN_YANG (match_ipv6_next_hop,
match_ipv6_next_hop_cmd,
- "match ipv6 next-hop X:X::X:X",
+ "match ipv6 next-hop ACCESSLIST6_NAME",
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "IPv6 access-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/list-name", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ argv[argc - 1]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_match_ipv6_next_hop,
+ no_match_ipv6_next_hop_cmd,
+ "no match ipv6 next-hop [ACCESSLIST6_NAME]",
+ NO_STR
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "IPv6 access-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (match_ipv6_next_hop_address,
+ match_ipv6_next_hop_address_cmd,
+ "match ipv6 next-hop address X:X::X:X",
MATCH_STR
IPV6_STR
"Match IPv6 next-hop address of route\n"
+ "IPv6 address\n"
"IPv6 address of next hop\n")
{
const char *xpath =
@@ -6061,18 +6200,20 @@ DEFUN_YANG (match_ipv6_next_hop,
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ argv[argc - 1]->arg);
return nb_cli_apply_changes(vty, NULL);
}
-DEFUN_YANG (no_match_ipv6_next_hop,
- no_match_ipv6_next_hop_cmd,
- "no match ipv6 next-hop X:X::X:X",
+DEFUN_YANG (no_match_ipv6_next_hop_address,
+ no_match_ipv6_next_hop_address_cmd,
+ "no match ipv6 next-hop address X:X::X:X",
NO_STR
MATCH_STR
IPV6_STR
"Match IPv6 next-hop address of route\n"
+ "IPv6 address\n"
"IPv6 address of next hop\n")
{
const char *xpath =
@@ -6082,6 +6223,62 @@ DEFUN_YANG (no_match_ipv6_next_hop,
return nb_cli_apply_changes(vty, NULL);
}
+ALIAS_HIDDEN (match_ipv6_next_hop_address,
+ match_ipv6_next_hop_old_cmd,
+ "match ipv6 next-hop X:X::X:X",
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "IPv6 address of next hop\n")
+
+ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
+ no_match_ipv6_next_hop_old_cmd,
+ "no match ipv6 next-hop X:X::X:X",
+ NO_STR
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "IPv6 address of next hop\n")
+
+DEFUN_YANG (match_ipv6_next_hop_prefix_list,
+ match_ipv6_next_hop_prefix_list_cmd,
+ "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "Match entries by prefix-list\n"
+ "IPv6 prefix-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/list-name", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ argv[argc - 1]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
+ no_match_ipv6_next_hop_prefix_list_cmd,
+ "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
+ NO_STR
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "Match entries by prefix-list\n"
+ "IPv6 prefix-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFPY_YANG (match_ipv4_next_hop,
match_ipv4_next_hop_cmd,
"match ip next-hop address A.B.C.D",
@@ -6441,6 +6638,9 @@ void bgp_route_map_init(void)
route_map_match_ip_next_hop_hook(generic_match_add);
route_map_no_match_ip_next_hop_hook(generic_match_delete);
+ route_map_match_ipv6_next_hop_hook(generic_match_add);
+ route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
+
route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
@@ -6456,6 +6656,9 @@ void bgp_route_map_init(void)
route_map_match_ipv6_next_hop_type_hook(generic_match_add);
route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
+ route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
+ route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
+
route_map_match_metric_hook(generic_match_add);
route_map_no_match_metric_hook(generic_match_delete);
@@ -6638,6 +6841,8 @@ 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_ipv6_next_hop_address_cmd);
+ route_map_install_match(&route_match_ipv6_next_hop_prefix_list_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);
@@ -6647,7 +6852,13 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index 09a6be4010..773538ee41 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -1234,7 +1234,7 @@ lib_route_map_entry_match_condition_rmap_match_condition_ipv6_address_modify(
/* Set destroy information. */
rhc->rhc_mhook = bgp_route_match_delete;
- rhc->rhc_rule = "ipv6 next-hop";
+ rhc->rhc_rule = "ipv6 next-hop address";
rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
ret = bgp_route_match_add(rhc->rhc_rmi, rhc->rhc_rule,
diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c
index 8d2cffbb47..6308936aa8 100644
--- a/bgpd/bgp_vpn.c
+++ b/bgpd/bgp_vpn.c
@@ -118,15 +118,11 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
if (header) {
if (use_json) {
- char buf[BUFSIZ] = {0};
-
json_object_int_add(
json, "bgpTableVersion", 0);
- json_object_string_add(
+ json_object_string_addf(
json, "bgpLocalRouterId",
- inet_ntop(AF_INET,
- &bgp->router_id, buf,
- sizeof(buf)));
+ "%pI4", &bgp->router_id);
json_object_int_add(
json,
"defaultLocPrf",
@@ -243,9 +239,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
json_object_object_add(json, "advertisedRoutes", json_adv);
json_object_int_add(json,
"totalPrefixCounter", output_count);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else
vty_out(vty, "\nTotal number of prefixes %ld\n", output_count);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 3725f242e1..8a63030181 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -645,10 +645,7 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
json_object_string_add(
json, "warning",
"View/Vrf is unknown");
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
else
vty_out(vty, "View/Vrf %s is unknown\n",
@@ -666,10 +663,7 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
json_object_string_add(
json, "warning",
"Default BGP instance not found");
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
else
vty_out(vty,
@@ -6308,6 +6302,30 @@ DEFUN(no_neighbor_disable_link_bw_encoding_ieee,
PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE);
}
+/* extended-optional-parameters */
+DEFUN(neighbor_extended_optional_parameters,
+ neighbor_extended_optional_parameters_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> extended-optional-parameters",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Force the extended optional parameters format for OPEN messages\n")
+{
+ int idx_peer = 1;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_EXTENDED_OPT_PARAMS);
+}
+
+DEFUN(no_neighbor_extended_optional_parameters,
+ no_neighbor_extended_optional_parameters_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> extended-optional-parameters",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Force the extended optional parameters format for OPEN messages\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_EXTENDED_OPT_PARAMS);
+}
/* enforce-first-as */
DEFUN (neighbor_enforce_first_as,
@@ -9690,10 +9708,8 @@ DEFUN (show_bgp_vrfs,
json_object_string_add(json_vrf, "type", type);
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
- json_object_string_add(json_vrf, "routerId",
- inet_ntop(AF_INET,
- &bgp->router_id, buf,
- sizeof(buf)));
+ json_object_string_addf(json_vrf, "routerId", "%pI4",
+ &bgp->router_id);
json_object_int_add(json_vrf, "numConfiguredPeers",
peers_cfg);
json_object_int_add(json_vrf, "numEstablishedPeers",
@@ -9726,9 +9742,7 @@ DEFUN (show_bgp_vrfs,
json_object_int_add(json, "totalVrfs", count);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (count)
vty_out(vty,
@@ -10260,9 +10274,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json_object_int_add(json, "dynamicPeers", dn_count);
json_object_int_add(json, "totalPeers", count);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
vty_out(vty, "%% No failed BGP neighbors found\n");
}
@@ -10290,12 +10302,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
/* Usage summary and header */
if (use_json) {
- char buf[BUFSIZ] = {0};
-
- json_object_string_add(
- json, "routerId",
- inet_ntop(AF_INET, &bgp->router_id, buf,
- sizeof(buf)));
+ json_object_string_addf(json, "routerId",
+ "%pI4",
+ &bgp->router_id);
json_object_int_add(json, "as", bgp->as);
json_object_int_add(json, "vrfId", vrf_id_ui);
json_object_string_add(
@@ -10834,9 +10843,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
if (!show_failed)
bgp_show_bestpath_json(bgp, json);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (count) {
if (filtered_count == count)
@@ -12368,10 +12375,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
p->group, &prefix);
if (range) {
- prefix2str(range, buf1, sizeof(buf1));
- json_object_string_add(
+ json_object_string_addf(
json_neigh,
- "peerSubnetRangeGroup", buf1);
+ "peerSubnetRangeGroup", "%pFX",
+ range);
}
}
} else {
@@ -12404,13 +12411,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
/* BGP Version. */
json_object_int_add(json_neigh, "bgpVersion", 4);
- json_object_string_add(
- json_neigh, "remoteRouterId",
- inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1)));
- json_object_string_add(
- json_neigh, "localRouterId",
- inet_ntop(AF_INET, &bgp->router_id, buf1,
- sizeof(buf1)));
+ json_object_string_addf(json_neigh, "remoteRouterId", "%pI4",
+ &p->remote_id);
+ json_object_string_addf(json_neigh, "localRouterId", "%pI4",
+ &bgp->router_id);
/* Confederation */
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
@@ -12517,6 +12521,14 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
"bgpTimerConfiguredKeepAliveIntervalMsecs",
bgp->default_keepalive);
}
+
+ /* Extended Optional Parameters Length for BGP OPEN Message */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
+ json_object_boolean_true_add(
+ json_neigh, "extendedOptionalParametersLength");
+ else
+ json_object_boolean_false_add(
+ json_neigh, "extendedOptionalParametersLength");
} else {
/* Administrative shutdown. */
if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)
@@ -12589,6 +12601,11 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
vty_out(vty, " Configured tcp-mss is %d", p->tcp_mss);
vty_out(vty, ", synced tcp-mss is %d\n", sync_tcp_mss);
}
+
+ /* Extended Optional Parameters Length for BGP OPEN Message */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
+ vty_out(vty,
+ " Extended Optional Parameters Length is enabled\n");
}
/* Capability. */
if (peer_established(p)) {
@@ -13999,18 +14016,12 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
/* Nexthop display. */
if (p->su_local) {
if (use_json) {
- json_object_string_add(json_neigh, "nexthop",
- inet_ntop(AF_INET,
- &p->nexthop.v4, buf1,
- sizeof(buf1)));
- json_object_string_add(json_neigh, "nexthopGlobal",
- inet_ntop(AF_INET6,
- &p->nexthop.v6_global,
- buf1, sizeof(buf1)));
- json_object_string_add(json_neigh, "nexthopLocal",
- inet_ntop(AF_INET6,
- &p->nexthop.v6_local,
- buf1, sizeof(buf1)));
+ json_object_string_addf(json_neigh, "nexthop", "%pI4",
+ &p->nexthop.v4);
+ json_object_string_addf(json_neigh, "nexthopGlobal",
+ "%pI6", &p->nexthop.v6_global);
+ json_object_string_addf(json_neigh, "nexthopLocal",
+ "%pI6", &p->nexthop.v6_local);
if (p->shared_network)
json_object_string_add(json_neigh,
"bgpConnection",
@@ -14192,13 +14203,9 @@ static int bgp_show_neighbor_graceful_restart(struct vty *vty, struct bgp *bgp,
vty_out(vty, "%% No such neighbor\n");
}
if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
-
if (json_neighbor)
json_object_free(json_neighbor);
- json_object_free(json);
+ vty_json(vty, json);
} else {
vty_out(vty, "\n");
}
@@ -14438,11 +14445,7 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name,
if (!bgp) {
if (use_json) {
json = json_object_new_object();
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else
vty_out(vty,
"%% BGP instance not found\n");
@@ -14751,11 +14754,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
if (!bgp) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
return CMD_WARNING;
}
@@ -14827,10 +14826,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
}
if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
} else {
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
@@ -14942,9 +14938,7 @@ static int bgp_show_all_instance_route_leak_vty(struct vty *vty, afi_t afi,
if (use_json) {
json_object_object_add(json, "vrfs", json_vrfs);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
return CMD_SUCCESS;
@@ -14989,9 +14983,8 @@ DEFUN (show_ip_bgp_route_leak,
vrf = NULL;
}
/* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
- if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
+ if (argv_find_and_parse_afi(argv, argc, &idx, &afi))
argv_find_and_parse_safi(argv, argc, &idx, &safi);
- }
if (!((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)) {
vty_out(vty,
@@ -15423,14 +15416,10 @@ static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
if (!bgp) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else {
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% BGP instance not found\n");
- }
return CMD_WARNING;
}
@@ -15450,12 +15439,8 @@ static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
if (group_name && !found && !uj)
vty_out(vty, "%% No such peer-group\n");
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -16688,6 +16673,11 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
addr);
+ /* extended-optional-parameters */
+ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
+ vty_out(vty, " neighbor %s extended-optional-parameters\n",
+ addr);
+
/* enforce-first-as */
if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
vty_out(vty, " neighbor %s enforce-first-as\n", addr);
@@ -17593,6 +17583,7 @@ static struct cmd_node bgp_ipv4_unicast_node = {
.node = BGP_IPV4_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv4_multicast_node = {
@@ -17600,6 +17591,7 @@ static struct cmd_node bgp_ipv4_multicast_node = {
.node = BGP_IPV4M_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv4_labeled_unicast_node = {
@@ -17607,6 +17599,7 @@ static struct cmd_node bgp_ipv4_labeled_unicast_node = {
.node = BGP_IPV4L_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv6_unicast_node = {
@@ -17614,6 +17607,7 @@ static struct cmd_node bgp_ipv6_unicast_node = {
.node = BGP_IPV6_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv6_multicast_node = {
@@ -17621,6 +17615,7 @@ static struct cmd_node bgp_ipv6_multicast_node = {
.node = BGP_IPV6M_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv6_labeled_unicast_node = {
@@ -17628,6 +17623,7 @@ static struct cmd_node bgp_ipv6_labeled_unicast_node = {
.node = BGP_IPV6L_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_vpnv4_node = {
@@ -17635,6 +17631,7 @@ static struct cmd_node bgp_vpnv4_node = {
.node = BGP_VPNV4_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_vpnv6_node = {
@@ -17642,6 +17639,7 @@ static struct cmd_node bgp_vpnv6_node = {
.node = BGP_VPNV6_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af-vpnv6)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_evpn_node = {
@@ -17649,6 +17647,7 @@ static struct cmd_node bgp_evpn_node = {
.node = BGP_EVPN_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-evpn)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_evpn_vni_node = {
@@ -17663,6 +17662,7 @@ static struct cmd_node bgp_flowspecv4_node = {
.node = BGP_FLOWSPECV4_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_flowspecv6_node = {
@@ -17670,6 +17670,7 @@ static struct cmd_node bgp_flowspecv6_node = {
.node = BGP_FLOWSPECV6_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af-vpnv6)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_srv6_node = {
@@ -18634,6 +18635,11 @@ void bgp_vty_init(void)
install_element(BGP_NODE,
&no_neighbor_disable_link_bw_encoding_ieee_cmd);
+ /* "neighbor extended-optional-parameters" commands. */
+ install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_extended_optional_parameters_cmd);
+
/* "neighbor enforce-first-as" commands. */
install_element(BGP_NODE, &neighbor_enforce_first_as_cmd);
install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index a98168d464..bbb7d5469d 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -206,10 +206,11 @@ static int bgp_ifp_destroy(struct interface *ifp)
{
struct bgp *bgp;
- bgp = bgp_lookup_by_vrf_id(ifp->vrf_id);
+ bgp = ifp->vrf->info;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf del VRF %u IF %s", ifp->vrf_id, ifp->name);
+ zlog_debug("Rx Intf del VRF %u IF %s", ifp->vrf->vrf_id,
+ ifp->name);
if (bgp) {
bgp_update_interface_nbrs(bgp, ifp, NULL);
@@ -228,12 +229,13 @@ static int bgp_ifp_up(struct interface *ifp)
struct listnode *node, *nnode;
struct bgp *bgp;
- bgp = bgp_lookup_by_vrf_id(ifp->vrf_id);
+ bgp = ifp->vrf->info;
bgp_mac_add_mac_entry(ifp);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf up VRF %u IF %s", ifp->vrf_id, ifp->name);
+ zlog_debug("Rx Intf up VRF %u IF %s", ifp->vrf->vrf_id,
+ ifp->name);
if (!bgp)
return 0;
@@ -258,12 +260,13 @@ static int bgp_ifp_down(struct interface *ifp)
struct bgp *bgp;
struct peer *peer;
- bgp = bgp_lookup_by_vrf_id(ifp->vrf_id);
+ bgp = ifp->vrf->info;
bgp_mac_del_mac_entry(ifp);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf down VRF %u IF %s", ifp->vrf_id, ifp->name);
+ zlog_debug("Rx Intf down VRF %u IF %s", ifp->vrf->vrf_id,
+ ifp->name);
if (!bgp)
return 0;
@@ -875,7 +878,7 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote,
* It's fine to not have a v6 LL when using
* update-source loopback/vrf
*/
- if (!v6_ll_avail && if_is_loopback_or_vrf(ifp))
+ if (!v6_ll_avail && if_is_loopback(ifp))
v6_ll_avail = true;
} else
/* Link-local address. */
@@ -1249,6 +1252,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
uint8_t distance;
struct peer *peer;
struct bgp_path_info *mpinfo;
+ struct bgp *bgp_orig;
uint32_t metric;
struct attr local_attr;
struct bgp_path_info local_info;
@@ -1412,13 +1416,13 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
}
}
+ BGP_ORIGINAL_UPDATE(bgp_orig, mpinfo, bgp);
+
if (nh_family == AF_INET) {
nh_updated = update_ipv4nh_for_route_install(
- nh_othervrf,
- nh_othervrf ?
- info->extra->bgp_orig : bgp,
- &mpinfo_cp->attr->nexthop,
- mpinfo_cp->attr, is_evpn, api_nh);
+ nh_othervrf, bgp_orig,
+ &mpinfo_cp->attr->nexthop, mpinfo_cp->attr,
+ is_evpn, api_nh);
} else {
ifindex_t ifindex = IFINDEX_INTERNAL;
struct in6_addr *nexthop;
@@ -1428,18 +1432,13 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
if (!nexthop)
nh_updated = update_ipv4nh_for_route_install(
- nh_othervrf,
- nh_othervrf ? info->extra->bgp_orig
- : bgp,
+ nh_othervrf, bgp_orig,
&mpinfo_cp->attr->nexthop,
mpinfo_cp->attr, is_evpn, api_nh);
else
nh_updated = update_ipv6nh_for_route_install(
- nh_othervrf,
- nh_othervrf ? info->extra->bgp_orig
- : bgp,
- nexthop, ifindex, mpinfo, info, is_evpn,
- api_nh);
+ nh_othervrf, bgp_orig, nexthop, ifindex,
+ mpinfo, info, is_evpn, api_nh);
}
/* Did we get proper nexthop info to update zebra? */
@@ -3103,9 +3102,10 @@ static int bgp_ifp_create(struct interface *ifp)
struct bgp *bgp;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf add VRF %u IF %s", ifp->vrf_id, ifp->name);
+ zlog_debug("Rx Intf add VRF %u IF %s", ifp->vrf->vrf_id,
+ ifp->name);
- bgp = bgp_lookup_by_vrf_id(ifp->vrf_id);
+ bgp = ifp->vrf->info;
if (!bgp)
return 0;
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 9c0a1d8f1f..eee3d36931 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -23,6 +23,13 @@
#include "vxlan.h"
+/* Macro to update bgp_original based on bpg_path_info */
+#define BGP_ORIGINAL_UPDATE(_bgp_orig, _mpinfo, _bgp) \
+ ((_mpinfo->extra && _mpinfo->extra->bgp_orig \
+ && _mpinfo->sub_type == BGP_ROUTE_IMPORTED) \
+ ? (_bgp_orig = _mpinfo->extra->bgp_orig) \
+ : (_bgp_orig = _bgp))
+
/* Default weight for next hop, if doing weighted ECMP. */
#define BGP_ZEBRA_DEFAULT_NHOP_WEIGHT 1
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 9316d71baf..5cc5feba3a 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4181,6 +4181,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
{PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
+ {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
@@ -7903,11 +7904,7 @@ struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
json_no,
"malformedAddressOrName",
ip_str);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_no,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json_no);
+ vty_json(vty, json_no);
} else
vty_out(vty,
"%% Malformed address or name: %s\n",
@@ -7926,10 +7923,7 @@ struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"No such neighbor in this view/vrf");
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_no, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_no);
+ vty_json(vty, json_no);
} else
vty_out(vty, "No such neighbor in this view/vrf\n");
return NULL;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 29775bccce..7c91065601 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1298,6 +1298,8 @@ struct peer {
* extended communities.
*/
#define PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE (1U << 29)
+/* force the extended format for Optional Parameters in OPEN message */
+#define PEER_FLAG_EXTENDED_OPT_PARAMS (1U << 30)
/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1384,6 +1386,8 @@ struct peer {
#define PEER_STATUS_GROUP (1U << 4) /* peer-group conf */
#define PEER_STATUS_NSF_MODE (1U << 5) /* NSF aware peer */
#define PEER_STATUS_NSF_WAIT (1U << 6) /* wait comeback peer */
+/* received extended format encoding for OPEN message */
+#define PEER_STATUS_EXT_OPT_PARAMS_LENGTH (1U << 7)
/* Peer status af flags (reset in bgp_stop) */
uint16_t af_sflags[AFI_MAX][SAFI_MAX];
diff --git a/configure.ac b/configure.ac
index 42b3b659a7..c153e4c261 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1915,6 +1915,7 @@ if test "$enable_confd" != "" -a "$enable_confd" != "no"; then
if test "$CONFD" = "/bin/false"; then
AC_MSG_ERROR([confd was not found on your system.])]
fi
+ AC_CHECK_PROG([CONFDC], [confdc], [confdc], [/bin/false], "${enable_confd}/bin")
CONFD_CFLAGS="-I${enable_confd}/include -L${enable_confd}/lib"
AC_SUBST([CONFD_CFLAGS])
CONFD_LIBS="-lconfd"
diff --git a/doc/developer/frr-release-procedure.rst b/doc/developer/frr-release-procedure.rst
index 08e3057ae6..7c10e6a8fc 100644
--- a/doc/developer/frr-release-procedure.rst
+++ b/doc/developer/frr-release-procedure.rst
@@ -6,27 +6,29 @@ FRR Release Procedure
``<version>`` - version to be released, e.g. 7.3
``origin`` - FRR upstream repository
-1. Checkout ``dev/<version>``.
+Stage 1 - Preparation
+---------------------
+
+#. Checkout the existing ``dev/<version>`` branch.
.. code-block:: console
git checkout dev/<version>
-2. Create and push a new branch called ``stable/<version>`` based on the
+#. Create and push a new branch called ``stable/<version>`` based on the
``dev/<version>`` branch.
.. code-block:: console
git checkout -b stable/<version>
- git push origin stable/<version>:refs/heads/stable/<version>
-3. Remove the development branch called ``dev/<version>``
+#. Remove the development branch called ``dev/<version>``
.. code-block:: console
git push origin --delete dev/<version>
-4. Update Changelog for Red Hat Packages:
+#. Update Changelog for Red Hat Packages:
Edit :file:`redhat/frr.spec.in` and look for the ``%changelog`` section:
@@ -47,7 +49,7 @@ FRR Release Procedure
- Add the changelog text below this entry.
-5. Update Changelog for Debian Packages:
+#. Update Changelog for Debian Packages:
Update :file:`debian/changelog`:
@@ -80,104 +82,148 @@ FRR Release Procedure
.
* Your Changes Here
-6. Change main version number:
+#. Commit the changes, adding the changelog to the commit message. Follow all
+ existing commit guidelines. The commit message should be akin to::
+
+ debian, redhat: updating changelog for new release
+
+#. Change main version number:
+
+ - Edit :file:`configure.ac` and change version in the ``AC_INIT`` command
+ to ``<version>``
+
+ Add and commit this change. This commit should be separate from the commit
+ containing the changelog. The commit message should be::
+
+ FRR Release <version>
- - Edit :file:`configure.ac` and change version in the ``AC_INIT`` command
- to ``<version>``
+ The version field should be complete; i.e. for ``8.0.0``, the version should
+ be ``8.0.0`` and not ``8.0`` or ``8``.
-7. Commit the changes, adding the changelog to the commit message. Follow all
- existing commit guidelines.
-8. Create and submit a GitHub pull request, with the ``HEAD`` set to
- ``stable/<version>`` and the base set to the upstream ``master`` branch.
- Allow NetDef CI to complete its run and verify that all package builds were
- successful.
+Stage 2 - Staging
+-----------------
-9. Create a git tag for the version:
+#. Push the stable branch to a new remote branch prefixed with ``rc``::
+
+ git push origin stable/<version>:rc/version
+
+ This will trigger the NetDEF CI, which serve as a sanity check on the
+ release branch. Verify that all tests pass and that all package builds are
+ successful. To do this, go to the NetDEF CI located here:
+
+ https://ci1.netdef.org/browse/FRR-FRR
+
+ In the top left, look for ``rc-<version>`` in the "Plan branch" dropdown.
+ Select this version. Note that it may take a few minutes for the CI to kick
+ in on this new branch and appear in the list.
+
+#. Push the stable branch:
.. code-block:: console
- git tag -a frr-<version> -m "FRRouting Release <version>"
+ git push origin stable/<version>:refs/heads/stable/<version>
-10. Push the commit and new tag.
+#. Create and push a git tag for the version:
.. code-block:: console
- git push origin stable/<version>:refs/head/stable/<version>
+ git tag -a frr-<version> -m "FRRouting Release <version>"
git push origin frr-<version>
-11. Kick off the Release build plan on the CI system for the correct release.
- Contact Martin Winter for this step. Ensure all release packages build
- successfully.
+#. Create a new branch based on ``master``, cherry-pick the commit made earlier
+ that added the changelogs, and use it to create a PR against ``master``.
+ This way ``master`` has the latest changelog for the next cycle.
+
+#. Kick off the "Release" build plan on the CI system for the correct release.
+ Contact Martin Winter for this step. Ensure all release packages build
+ successfully.
+
+#. Kick off the Snapcraft build plan for the release.
+
+
+Stage 3 - Publish
+-----------------
-12. Kick off the Snapcraft build plan for the release.
+#. Upload both the Debian and RPM packages to their respective repositories.
-13. Acquire the release RPM binary packages from Martin Winter.
+#. Coordinate with the maintainer of FRR's RPM repository to publish the RPM
+ packages on that repository. Update the repository webpage. Verify that the
+ instructions on the webpage work and that FRR is installable from the
+ repository on a Red Hat system.
-14. On GitHub, go to the <https://github.com/FRRouting/frr/releases>_ and click
- "Draft a new release". Write a release announcement. The release
- announcement should follow the template in
- ``release-announcement-template.md``, located next to this document. Check
- for spelling errors, and optionally (but preferably) have other maintainers
- proofread the announcement text.
+ Current maintainer: *Martin Winter*
- Attach **only** the binary RPM packages to the GitHub release using
- GitHub's attachment functionality. Do not attach Debian packages. Do not
- attach source tarballs - these will be generated and attached by GitHub
- automatically. Do not publish the release yet.
+#. Coordinate with the maintainer of FRR Debian package to publish the Debian
+ packages on that repository. Update the repository webpage. Verify that the
+ instructions on the webpage work and that FRR is installable from the
+ repository on a Debian system.
-15. Contact the current Debian maintainer for FRR to get new Debian packages
- built and published on our APT repository at https://deb.frrouting.net/.
- Ensure the webpage text is updated. Verify that new packages install
- successfully on a vanilla Debian installation using the instructions on the
- webpage.
+ Current maintainer: *Jafar Al-Gharaibeh*
-16. Deploy Snapcraft release (after CI system finishes the tests for snapcraft
- testplan).
+#. Log in to the Read The Docs instance. in the "FRRouting" project, navigate
+ to the "Overview" tab. Ensure there is a ``stable-<version>`` version listed
+ and that it is enabled. Go to "Admin" and then "Advanced Settings". Change
+ "Default version" to the new version. This ensures that the documentation
+ shown to visitors is that of the latest release by default.
-17. Update the Read The Docs instance to being publishing documentation built
- off the ``stable/<version>`` branch. Contact Quentin Young for this step.
+ This step must be performed by someone with administrative access to the
+ Read the Docs instance.
-18. Publish the GitHub release.
+#. On GitHub, go to the <https://github.com/FRRouting/frr/releases>_ and click
+ "Draft a new release". Write a release announcement. The release
+ announcement should follow the template in
+ ``release-announcement-template.md``, located next to this document. Check
+ for spelling errors, and optionally (but preferably) have other maintainers
+ proofread the announcement text.
-19. Clone the ``frr-www`` repository:
+ Do not attach any packages or source tarballs to the GitHub release.
- .. code-block:: console
+ Publish the release once it is reviewed.
- git clone https://github.com/FRRouting/frr-www.git
+#. Deploy Snapcraft release. Remember that this will automatically upgrade Snap
+ users.
-20. Add a new release announcement, using a previous announcement as template:
+ Current maintainer: *Martin Winter*
- .. code-block:: console
+#. Build and publish the Docker containers.
- cp <old-version>-launch.md <version>-launch.md
+ Current maintainer: *Quentin Young*
- Paste the GitHub release announcement text into this document, and **remove
- line breaks**. In other words, this::
+#. Clone the ``frr-www`` repository:
+
+ .. code-block:: console
+
+ git clone https://github.com/FRRouting/frr-www.git
+
+#. Add a new release announcement, using a previous announcement as template:
+
+ .. code-block:: console
- This is one continuous
- sentence that should be
- rendered on one line
+ cp <old-version>.md <version>.md
- Needs to be changed to this::
+ Paste the GitHub release announcement text into this document, and **remove
+ line breaks**. In other words, this::
- This is one continuous sentence that should be rendered on one line
+ This is one continuous
+ sentence that should be
+ rendered on one line
- This is very important otherwise the announcement will be unreadable on the
- website.
+ Needs to be changed to this::
- Make sure to add a link to the GitHub releases page at the top.
+ This is one continuous sentence that should be rendered on one line
- Once finished, manually add a new entry into ``index.html`` to link to this
- new announcement. Look at past commits to see how to do this.
+ This is very important otherwise the announcement will be unreadable on the
+ website.
-21. Deploy the updated ``frr-www`` on the frrouting.org web server and verify
- that the announcement text is visible.
+ Make sure to add a link to the GitHub releases page at the top.
-22. Send an email to ``announce@lists.frrouting.org``. The text of this email
- should include the text from the GitHub release.
+ Once finished, manually add a new entry into ``index.html`` to link to this
+ new announcement. Look at past commits to see how to do this.
-23. Update masters version of the changelog-auto.in
+#. Deploy the updated ``frr-www`` on the frrouting.org web server and verify
+ that the announcement text is visible.
- Take the change data and cut-n-paste the changes into the master version below
- the @VERSION@-0 lines. So we have the history of the previous release.
+#. Send an email to ``announce@lists.frrouting.org``. The text of this email
+ should include text as appropriate from the GitHub release and a link to the
+ GitHub release, Debian repository, and RPM repository.
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index db59c42773..2f8c5c01da 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1423,6 +1423,15 @@ Configuring Peers
value is carried encoded as uint32. To enable backward compatibility we
need to disable IEEE floating-point encoding option per-peer.
+.. clicmd:: neighbor PEER extended-optional-parameters
+
+ Force Extended Optional Parameters Length format to be used for OPEN messages.
+
+ By default, it's disabled. If the standard optional parameters length is
+ higher than one-octet (255), then extended format is enabled automatically.
+
+ For testing purposes, extended format can be enabled with this command.
+
.. clicmd:: neighbor PEER ebgp-multihop
Specifying ``ebgp-multihop`` allows sessions with eBGP neighbors to
@@ -3553,6 +3562,13 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
Display flap statistics of routes of the selected afi and safi selected.
+.. clicmd:: show bgp [afi] [safi] [all] dampening parameters [json]
+
+ Display details of configured dampening parameters of the selected afi and
+ safi.
+
+ If the ``json`` option is specified, output is displayed in JSON format.
+
.. clicmd:: show bgp [afi] [safi] [all] version (1-4294967295) [wide|json]
Display prefixes with matching version numbers. The version number and
@@ -3585,6 +3601,42 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
Display routes with non-natural netmasks.
+.. clicmd:: show [ip] bgp [afi] [safi] [all] prefix-list WORD [wide|json]
+
+ Display routes that match the specified prefix-list.
+
+ If ``wide`` option is specified, then the prefix table's width is increased
+ to fully display the prefix and the nexthop.
+
+ If the ``json`` option is specified, output is displayed in JSON format.
+
+.. clicmd:: show [ip] bgp [afi] [safi] [all] filter-list WORD [wide|json]
+
+ Display routes that match the specified AS-Path filter-list.
+
+ If ``wide`` option is specified, then the prefix table's width is increased
+ to fully display the prefix and the nexthop.
+
+ If the ``json`` option is specified, output is displayed in JSON format.
+
+.. clicmd:: show [ip] bgp [afi] [safi] [all] route-map WORD [wide|json]
+
+ Display routes that match the specified route-map.
+
+ If ``wide`` option is specified, then the prefix table's width is increased
+ to fully display the prefix and the nexthop.
+
+ If the ``json`` option is specified, output is displayed in JSON format.
+
+.. clicmd:: show [ip] bgp [afi] [safi] [all] <A.B.C.D/M|X:X::X:X/M> longer-prefixes [wide|json]
+
+ Displays the specified route and all more specific routes.
+
+ If ``wide`` option is specified, then the prefix table's width is increased
+ to fully display the prefix and the nexthop.
+
+ If the ``json`` option is specified, output is displayed in JSON format.
+
.. clicmd:: show [ip] bgp [afi] [safi] [all] neighbors A.B.C.D [advertised-routes|received-routes|filtered-routes] [json|wide]
Display the routes advertised to a BGP neighbor or received routes
@@ -3623,9 +3675,9 @@ attribute.
community are displayed. When `exact-match` is specified, it display only
routes that have an exact match.
-.. clicmd:: show [ip] bgp <ipv4|ipv6> community-list WORD
+.. clicmd:: show [ip] bgp <ipv4|ipv6> community-list WORD [json]
-.. clicmd:: show [ip] bgp <ipv4|ipv6> community-list WORD exact-match
+.. clicmd:: show [ip] bgp <ipv4|ipv6> community-list WORD exact-match [json]
These commands display BGP routes for the address family specified that
match the specified community list. When `exact-match` is specified, it
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index efe64b72f0..acae3eb27b 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -371,7 +371,8 @@ BGP
:t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017`
- :rfc:`8654`
:t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019`
-
+- :rfc:`9072`
+ :t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021`
OSPF
----
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index e1fe4bbbdb..01d3501333 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -144,14 +144,26 @@ Route Map Match Command
Matches the specified `prefix-len`. This is a Zebra specific command.
+.. clicmd:: match ip next-hop ACCESS_LIST
+
+ Match the next-hop according to the given access-list.
+
.. clicmd:: match ip next-hop address IPV4_ADDR
This is a BGP specific match command. Matches the specified `ipv4_addr`.
-.. clicmd:: match ipv6 next-hop IPV6_ADDR
+.. clicmd:: match ipv6 next-hop ACCESS_LIST
+
+ Match the next-hop according to the given access-list.
+
+.. clicmd:: match ipv6 next-hop address IPV6_ADDR
This is a BGP specific match command. Matches the specified `ipv6_addr`.
+.. clicmd:: match ipv6 next-hop prefix-list PREFIX_LIST
+
+ Match the next-hop according to the given prefix-list.
+
.. clicmd:: match as-path AS_PATH
Matches the specified `as_path`.
diff --git a/eigrpd/eigrp_filter.c b/eigrpd/eigrp_filter.c
index bb0cf51bd8..69c0d22aea 100644
--- a/eigrpd/eigrp_filter.c
+++ b/eigrpd/eigrp_filter.c
@@ -215,7 +215,7 @@ void eigrp_distribute_update_interface(struct interface *ifp)
struct distribute *dist;
struct eigrp *eigrp;
- eigrp = eigrp_lookup(ifp->vrf_id);
+ eigrp = eigrp_lookup(ifp->vrf->vrf_id);
if (!eigrp)
return;
dist = distribute_lookup(eigrp->distribute_ctx, ifp->name);
diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c
index 9a5fbc52b4..6b3a0afc12 100644
--- a/eigrpd/eigrp_network.c
+++ b/eigrpd/eigrp_network.c
@@ -288,7 +288,7 @@ void eigrp_if_update(struct interface *ifp)
* we need to check eac one and add the interface as approperate
*/
for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) {
- if (ifp->vrf_id != eigrp->vrf_id)
+ if (ifp->vrf->vrf_id != eigrp->vrf_id)
continue;
/* EIGRP must be on and Router-ID must be configured. */
diff --git a/eigrpd/eigrp_northbound.c b/eigrpd/eigrp_northbound.c
index 3ad711164b..a0f8452c94 100644
--- a/eigrpd/eigrp_northbound.c
+++ b/eigrpd/eigrp_northbound.c
@@ -1135,7 +1135,7 @@ static int lib_interface_eigrp_instance_create(struct nb_cb_create_args *args)
}
eigrp = eigrp_get(yang_dnode_get_uint16(args->dnode, "./asn"),
- ifp->vrf_id);
+ ifp->vrf->vrf_id);
eif = eigrp_interface_lookup(eigrp, ifp->name);
if (eif == NULL)
return NB_ERR_INCONSISTENCY;
@@ -1147,7 +1147,7 @@ static int lib_interface_eigrp_instance_create(struct nb_cb_create_args *args)
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
eigrp = eigrp_get(yang_dnode_get_uint16(args->dnode, "./asn"),
- ifp->vrf_id);
+ ifp->vrf->vrf_id);
eif = eigrp_interface_lookup(eigrp, ifp->name);
if (eif == NULL)
return NB_ERR_INCONSISTENCY;
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index 7510e310f7..a7548e2f13 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -132,7 +132,8 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj)
bfd_sess_set_ipv6_addrs(adj->bfd_session, &src_ip.ipv6,
&dst_ip.ipv6);
bfd_sess_set_interface(adj->bfd_session, adj->circuit->interface->name);
- bfd_sess_set_vrf(adj->bfd_session, adj->circuit->interface->vrf_id);
+ bfd_sess_set_vrf(adj->bfd_session,
+ adj->circuit->interface->vrf->vrf_id);
bfd_sess_set_profile(adj->bfd_session, circuit->bfd_config.profile);
bfd_sess_install(adj->bfd_session);
return;
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index d0e8637c52..a91bbd0b95 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -82,7 +82,7 @@ static void isis_circuit_enable(struct isis_circuit *circuit)
struct interface *ifp = circuit->interface;
if (!area) {
- area = isis_area_lookup(circuit->tag, ifp->vrf_id);
+ area = isis_area_lookup(circuit->tag, ifp->vrf->vrf_id);
if (area)
isis_area_add_circuit(area, circuit);
}
@@ -487,7 +487,7 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp)
circuit->circ_type = CIRCUIT_T_BROADCAST;
} else if (if_is_pointopoint(ifp)) {
circuit->circ_type = CIRCUIT_T_P2P;
- } else if (if_is_loopback_or_vrf(ifp)) {
+ } else if (if_is_loopback(ifp)) {
circuit->circ_type = CIRCUIT_T_LOOPBACK;
circuit->is_passive = 1;
} else {
@@ -1305,7 +1305,7 @@ ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive)
if (circuit->is_passive == passive)
return ferr_ok();
- if (if_is_loopback_or_vrf(circuit->interface) && !passive)
+ if (if_is_loopback(circuit->interface) && !passive)
return ferr_cfg_invalid("loopback is always passive");
if (circuit->state != C_STATE_UP) {
diff --git a/isisd/isis_ldp_sync.c b/isisd/isis_ldp_sync.c
index 9d494121c8..0c541348df 100644
--- a/isisd/isis_ldp_sync.c
+++ b/isisd/isis_ldp_sync.c
@@ -218,7 +218,7 @@ static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj)
struct isis_area *area = circuit->area;
if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)
- || circuit->interface->vrf_id != VRF_DEFAULT
+ || circuit->interface->vrf->vrf_id != VRF_DEFAULT
|| if_is_loopback(circuit->interface))
return 0;
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 07af46c04a..3674d69376 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -2479,7 +2479,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
actual_mtu =
if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
- area = isis_area_lookup(area_tag, ifp->vrf_id);
+ area = isis_area_lookup(area_tag, ifp->vrf->vrf_id);
if (area)
min_mtu = area->lsp_mtu;
else
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
index 4a884877f0..20224c73a1 100644
--- a/isisd/isis_pfpacket.c
+++ b/isisd/isis_pfpacket.c
@@ -123,15 +123,10 @@ static int open_packet_socket(struct isis_circuit *circuit)
int fd, retval = ISIS_OK;
struct vrf *vrf = NULL;
- vrf = vrf_lookup_by_id(circuit->interface->vrf_id);
+ vrf = circuit->interface->vrf;
- if (vrf == NULL) {
- zlog_warn("open_packet_socket(): failed to find vrf node");
- return ISIS_WARNING;
- }
-
- fd = vrf_socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL),
- circuit->interface->vrf_id, vrf->name);
+ fd = vrf_socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL), vrf->vrf_id,
+ vrf->name);
if (fd < 0) {
zlog_warn("open_packet_socket(): socket() failed %s",
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index f7cef43d0d..54e31f0040 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -550,13 +550,13 @@ static void sr_local_block_delete(struct isis_area *area)
*/
static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb)
{
-
mpls_label_t label;
uint32_t index;
uint32_t pos;
+ uint32_t size = srlb->end - srlb->start + 1;
/* Check if we ran out of available labels */
- if (srlb->current >= srlb->end)
+ if (srlb->current >= size)
return MPLS_INVALID_LABEL;
/* Get first available label and mark it used */
@@ -568,7 +568,7 @@ static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb)
/* Jump to the next free position */
srlb->current++;
pos = srlb->current % SRLB_BLOCK_SIZE;
- while (srlb->current < srlb->end) {
+ while (srlb->current < size) {
if (pos == 0)
index++;
if (!((1ULL << pos) & srlb->used_mark[index]))
@@ -579,6 +579,10 @@ static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb)
}
}
+ if (srlb->current == size)
+ zlog_warn(
+ "SR: Warning, SRLB is depleted and next label request will fail");
+
return label;
}
diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c
index 09b820e3f6..7bad1dca7c 100644
--- a/ldpd/ldp_vty_exec.c
+++ b/ldpd/ldp_vty_exec.c
@@ -447,7 +447,6 @@ show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
json_object *json)
{
struct ctl_adj *adj;
- char buf[PREFIX_STRLEN];
json_object *json_array;
json_object *json_adj;
@@ -467,9 +466,8 @@ show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
json_adj = json_object_new_object();
json_object_string_add(json_adj, "addressFamily",
af_name(adj->af));
- json_object_string_add(json_adj, "neighborId",
- inet_ntop(AF_INET, &adj->id, buf,
- sizeof(buf)));
+ json_object_string_addf(json_adj, "neighborId", "%pI4",
+ &adj->id);
switch(adj->type) {
case HELLO_LINK:
json_object_string_add(json_adj, "type", "link");
@@ -498,7 +496,6 @@ show_discovery_msg_json(struct imsg *imsg, struct show_params *params,
static void
show_discovery_detail_adj_json(json_object *json, struct ctl_adj *adj)
{
- char buf[PREFIX_STRLEN];
json_object *json_adj;
json_object *json_array;
@@ -509,8 +506,7 @@ show_discovery_detail_adj_json(json_object *json, struct ctl_adj *adj)
}
json_adj = json_object_new_object();
- json_object_string_add(json_adj, "lsrId", inet_ntop(AF_INET, &adj->id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_adj, "lsrId", "%pI4", &adj->id);
json_object_string_add(json_adj, "sourceAddress", log_addr(adj->af,
&adj->src_addr));
json_object_string_add(json_adj, "transportAddress", log_addr(adj->af,
@@ -532,7 +528,6 @@ show_discovery_detail_msg_json(struct imsg *imsg, struct show_params *params,
struct ctl_disc_tnbr *tnbr;
struct in_addr rtr_id;
union ldpd_addr *trans_addr;
- char buf[PREFIX_STRLEN];
json_object *json_interface;
json_object *json_target;
static json_object *json_interfaces;
@@ -542,9 +537,7 @@ show_discovery_detail_msg_json(struct imsg *imsg, struct show_params *params,
switch (imsg->hdr.type) {
case IMSG_CTL_SHOW_DISCOVERY:
rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
- json_object_string_add(json, "lsrId",
- inet_ntop(AF_INET, &rtr_id, buf,
- sizeof(buf)));
+ json_object_string_addf(json, "lsrId", "%pI4", &rtr_id);
if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
json_object_string_add(json, "transportAddressIPv4",
log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
@@ -749,7 +742,6 @@ show_nbr_msg_json(struct imsg *imsg, struct show_params *params,
json_object *json)
{
struct ctl_nbr *nbr;
- char buf[PREFIX_STRLEN];
json_object *json_array;
json_object *json_nbr;
@@ -766,9 +758,8 @@ show_nbr_msg_json(struct imsg *imsg, struct show_params *params,
json_nbr = json_object_new_object();
json_object_string_add(json_nbr, "addressFamily",
af_name(nbr->af));
- json_object_string_add(json_nbr, "neighborId",
- inet_ntop(AF_INET, &nbr->id, buf,
- sizeof(buf)));
+ json_object_string_addf(json_nbr, "neighborId", "%pI4",
+ &nbr->id);
json_object_string_add(json_nbr, "state",
nbr_state_name(nbr->nbr_state));
json_object_string_add(json_nbr, "transportAddress",
@@ -830,9 +821,7 @@ show_nbr_detail_msg_json(struct imsg *imsg, struct show_params *params,
json_object_object_add(json,
inet_ntop(AF_INET, &nbr->id, buf,
sizeof(buf)), json_nbr);
- json_object_string_add(json_nbr, "peerId",
- inet_ntop(AF_INET, &nbr->id, buf,
- sizeof(buf)));
+ json_object_string_addf(json_nbr, "peerId", "%pI4", &nbr->id);
json_object_string_add(json_nbr, "tcpLocalAddress",
log_addr(nbr->af, &nbr->laddr));
json_object_int_add(json_nbr, "tcpLocalPort",
@@ -1235,7 +1224,6 @@ show_lib_msg_json(struct imsg *imsg, struct show_params *params,
json_object *json_array;
json_object *json_lib_entry;
char dstnet[BUFSIZ];
- char buf[PREFIX_STRLEN];
switch (imsg->hdr.type) {
case IMSG_CTL_SHOW_LIB_BEGIN:
@@ -1258,9 +1246,8 @@ show_lib_msg_json(struct imsg *imsg, struct show_params *params,
snprintf(dstnet, sizeof(dstnet), "%s/%d",
log_addr(rt->af, &rt->prefix), rt->prefixlen);
json_object_string_add(json_lib_entry, "prefix", dstnet);
- json_object_string_add(json_lib_entry, "neighborId",
- inet_ntop(AF_INET, &rt->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_lib_entry, "neighborId", "%pI4",
+ &rt->nexthop);
json_object_string_add(json_lib_entry, "localLabel",
log_label(rt->local_label));
json_object_string_add(json_lib_entry, "remoteLabel",
@@ -1284,7 +1271,6 @@ show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params,
{
struct ctl_rt *rt = NULL;
char dstnet[BUFSIZ];
- char buf[PREFIX_STRLEN];
static json_object *json_lib_entry;
static json_object *json_adv_labels;
json_object *json_adv_label;
@@ -1316,18 +1302,16 @@ show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params,
rt = imsg->data;
json_adv_label = json_object_new_object();
- json_object_string_add(json_adv_label, "neighborId",
- inet_ntop(AF_INET, &rt->nexthop, buf,
- sizeof(buf)));
+ json_object_string_addf(json_adv_label, "neighborId", "%pI4",
+ &rt->nexthop);
json_object_array_add(json_adv_labels, json_adv_label);
break;
case IMSG_CTL_SHOW_LIB_RCVD:
rt = imsg->data;
json_remote_label = json_object_new_object();
- json_object_string_add(json_remote_label, "neighborId",
- inet_ntop(AF_INET, &rt->nexthop,
- buf, sizeof(buf)));
+ json_object_string_addf(json_remote_label, "neighborId", "%pI4",
+ &rt->nexthop);
json_object_string_add(json_remote_label, "label",
log_label(rt->remote_label));
json_object_int_add(json_remote_label, "inUse", rt->in_use);
@@ -1394,16 +1378,14 @@ show_l2vpn_binding_msg_json(struct imsg *imsg, struct show_params *params,
struct ctl_pw *pw;
json_object *json_pw;
char key_name[64];
- char buf[PREFIX_STRLEN];
switch (imsg->hdr.type) {
case IMSG_CTL_SHOW_L2VPN_BINDING:
pw = imsg->data;
json_pw = json_object_new_object();
- json_object_string_add(json_pw, "destination",
- inet_ntop(AF_INET, &pw->lsr_id, buf,
- sizeof(buf)));
+ json_object_string_addf(json_pw, "destination", "%pI4",
+ &pw->lsr_id);
json_object_int_add(json_pw, "vcId", pw->pwid);
/* local binding */
@@ -1481,7 +1463,6 @@ show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
json_object *json)
{
struct ctl_pw *pw;
- char buf[PREFIX_STRLEN];
json_object *json_pw;
switch (imsg->hdr.type) {
@@ -1489,9 +1470,7 @@ show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params,
pw = imsg->data;
json_pw = json_object_new_object();
- json_object_string_add(json_pw, "peerId",
- inet_ntop(AF_INET, &pw->lsr_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_pw, "peerId", "%pI4", &pw->lsr_id);
json_object_int_add(json_pw, "vcId", pw->pwid);
json_object_string_add(json_pw, "VpnName", pw->l2vpn_name);
if (pw->status == PW_FORWARDING)
@@ -1865,9 +1844,7 @@ ldp_vty_dispatch(struct vty *vty, struct imsgbuf *ibuf, enum show_command cmd,
done:
close(ibuf->fd);
if (json) {
- vty_out (vty, "%s\n",
- json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
return (ret);
@@ -2027,9 +2004,7 @@ ldp_vty_show_capabilities(struct vty *vty, const char *json)
"0x0603");
json_object_array_add(json_array, json_cap);
- vty_out (vty, "%s\n",
- json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
return (0);
}
diff --git a/lib/command.c b/lib/command.c
index ea66a17bb0..9cf93ea192 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -145,31 +145,6 @@ static struct cmd_node config_node = {
.node_exit = vty_config_node_exit,
};
-static bool vty_check_node_for_xpath_decrement(enum node_type target_node,
- enum node_type node)
-{
- /* bgp afi-safi (`address-family <afi> <safi>`) node
- * does not increment xpath_index.
- * In order to use (`router bgp`) BGP_NODE's xpath as a base,
- * retain xpath_index as 1 upon exiting from
- * afi-safi node.
- */
-
- if (target_node == BGP_NODE
- && (node == BGP_IPV4_NODE || node == BGP_IPV6_NODE
- || node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE
- || node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE
- || node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE
- || node == BGP_IPV6L_NODE || node == BGP_FLOWSPECV4_NODE
- || node == BGP_FLOWSPECV6_NODE))
- return false;
-
- if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE)
- return false;
-
- return true;
-}
-
/* This is called from main when a daemon is invoked with -v or --version. */
void print_version(const char *progname)
{
@@ -922,13 +897,15 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
* a match before calling node_exit handlers below
*/
for (i = 0; i < up_level; i++) {
+ struct cmd_node *cnode;
+
if (node <= CONFIG_NODE)
return CMD_NO_LEVEL_UP;
+ cnode = vector_slot(cmdvec, node);
node = node_parent(node);
- if (xpath_index > 0
- && vty_check_node_for_xpath_decrement(node, vty->node))
+ if (xpath_index > 0 && !cnode->no_xpath)
xpath_index--;
}
@@ -1062,12 +1039,13 @@ int cmd_execute_command(vector vline, struct vty *vty,
/* This assumes all nodes above CONFIG_NODE are childs of
* CONFIG_NODE */
while (vty->node > CONFIG_NODE) {
+ struct cmd_node *cnode = vector_slot(cmdvec, try_node);
+
try_node = node_parent(try_node);
vty->node = try_node;
- if (vty->xpath_index > 0
- && vty_check_node_for_xpath_decrement(try_node,
- onode))
+ if (vty->xpath_index > 0 && !cnode->no_xpath)
vty->xpath_index--;
+
ret = cmd_execute_command_real(vline, FILTER_RELAXED,
vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
@@ -1386,8 +1364,7 @@ void cmd_exit(struct vty *vty)
}
if (cnode->parent_node)
vty->node = cnode->parent_node;
- if (vty->xpath_index > 0
- && vty_check_node_for_xpath_decrement(vty->node, cnode->node))
+ if (vty->xpath_index > 0 && !cnode->no_xpath)
vty->xpath_index--;
}
diff --git a/lib/command.h b/lib/command.h
index e2086701ad..c888356d61 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -213,6 +213,9 @@ struct cmd_node {
/* set as soon as any command is in cmdgraph */
bool graph_built;
+
+ /* don't decrement vty->xpath_index on leaving this node */
+ bool no_xpath;
};
/* Return value of the commands. */
diff --git a/lib/ferr.c b/lib/ferr.c
index 513ef5ebec..e5b6d7552d 100644
--- a/lib/ferr.c
+++ b/lib/ferr.c
@@ -157,13 +157,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
}
}
- if (json) {
- const char *str = json_object_to_json_string_ext(
- top, JSON_C_TO_STRING_PRETTY);
- vty_out(vty, "%s\n", str);
- json_object_free(top);
- }
-
+ vty_json(vty, top);
list_delete(&errlist);
}
diff --git a/lib/filter.c b/lib/filter.c
index 9c80808fe8..fc4b578e77 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -558,18 +558,12 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
json_rule);
else {
if (json) {
- char buf[BUFSIZ];
-
- json_object_string_add(
- json_rule, "address",
- inet_ntop(AF_INET,
- &filter->addr, buf,
- sizeof(buf)));
- json_object_string_add(
- json_rule, "mask",
- inet_ntop(AF_INET,
- &filter->addr_mask,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_rule, "address", "%pI4",
+ &filter->addr);
+ json_object_string_addf(
+ json_rule, "mask", "%pI4",
+ &filter->addr_mask);
} else {
if (filter->addr_mask.s_addr
== 0xffffffff)
@@ -589,14 +583,7 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
}
}
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
-
- return CMD_SUCCESS;
+ return vty_json(vty, json);
}
/* show MAC access list - this only has MAC filters for now*/
@@ -681,21 +668,15 @@ static void config_write_access_cisco(struct vty *vty, struct filter *mfilter,
filter = &mfilter->u.cfilter;
if (json) {
- char buf[BUFSIZ];
-
json_object_boolean_add(json, "extended", !!filter->extended);
- json_object_string_add(
- json, "sourceAddress",
- inet_ntop(AF_INET, &filter->addr, buf, sizeof(buf)));
- json_object_string_add(json, "sourceMask",
- inet_ntop(AF_INET, &filter->addr_mask,
- buf, sizeof(buf)));
- json_object_string_add(
- json, "destinationAddress",
- inet_ntop(AF_INET, &filter->mask, buf, sizeof(buf)));
- json_object_string_add(json, "destinationMask",
- inet_ntop(AF_INET, &filter->mask_mask,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "sourceAddress", "%pI4",
+ &filter->addr);
+ json_object_string_addf(json, "sourceMask", "%pI4",
+ &filter->addr_mask);
+ json_object_string_addf(json, "destinationAddress", "%pI4",
+ &filter->mask);
+ json_object_string_addf(json, "destinationMask", "%pI4",
+ &filter->mask_mask);
} else {
vty_out(vty, " ip");
if (filter->addr_mask.s_addr == 0xffffffff)
@@ -730,16 +711,13 @@ static void config_write_access_zebra(struct vty *vty, struct filter *mfilter,
p = &filter->prefix;
if (json) {
- json_object_string_add(json, "prefix",
- prefix2str(p, buf, sizeof(buf)));
+ json_object_string_addf(json, "prefix", "%pFX", p);
json_object_boolean_add(json, "exact-match", !!filter->exact);
} else {
if (p->prefixlen == 0 && !filter->exact)
vty_out(vty, " any");
else if (p->family == AF_INET6 || p->family == AF_INET)
- vty_out(vty, " %s/%d%s",
- inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
- p->prefixlen,
+ vty_out(vty, " %pFX%s", p,
filter->exact ? " exact-match" : "");
else if (p->family == AF_ETHERNET) {
if (p->prefixlen == 0)
diff --git a/lib/if.c b/lib/if.c
index 6bfbdf9147..fe1d3ebb4a 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -167,7 +167,6 @@ static struct interface *if_new(struct vrf *vrf)
ifp->name[0] = '\0';
ifp->vrf = vrf;
- ifp->vrf_id = vrf->vrf_id;
ifp->connected = list_new();
ifp->connected->del = ifp_connected_free;
@@ -238,8 +237,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(old_vrf, ifp);
- ifp->vrf_id = vrf_id;
- vrf = vrf_get(ifp->vrf_id, NULL);
+ vrf = vrf_get(vrf_id, NULL);
ifp->vrf = vrf;
if (ifp->name[0] != '\0')
@@ -604,7 +602,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
if_update_to_new_vrf(ifp, vrf_id);
return ifp;
@@ -617,7 +615,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
if_update_to_new_vrf(ifp, vrf_id);
return ifp;
@@ -643,7 +641,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
* If there is already an interface with this ifindex, we will collide
* on insertion, so don't even try.
*/
- if (if_lookup_by_ifindex(ifindex, ifp->vrf_id))
+ if (if_lookup_by_ifindex(ifindex, ifp->vrf->vrf_id))
return -1;
if (ifp->ifindex != IFINDEX_INTERNAL)
@@ -713,7 +711,7 @@ int if_is_no_ptm_operative(const struct interface *ifp)
}
/* Is this loopback interface ? */
-int if_is_loopback(const struct interface *ifp)
+int if_is_loopback_exact(const struct interface *ifp)
{
/* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
* but Y on platform N?
@@ -727,9 +725,10 @@ int if_is_vrf(const struct interface *ifp)
return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
}
-bool if_is_loopback_or_vrf(const struct interface *ifp)
+/* Should this interface be treated as a loopback? */
+bool if_is_loopback(const struct interface *ifp)
{
- if (if_is_loopback(ifp) || if_is_vrf(ifp))
+ if (if_is_loopback_exact(ifp) || if_is_vrf(ifp))
return true;
return false;
@@ -806,8 +805,8 @@ static void if_dump(const struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
zlog_info(
"Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s",
- ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex,
- ifp->metric, ifp->mtu, ifp->mtu6,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6,
if_flag_dump(ifp->flags));
}
@@ -884,7 +883,7 @@ connected_log(struct connected *connected, char *str)
p = connected->address;
snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
- str, ifp->name, ifp->vrf->name, ifp->vrf_id,
+ str, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
prefix_family_str(p), p);
p = connected->destination;
diff --git a/lib/if.h b/lib/if.h
index 5f0dc27555..c8f4d9ab9d 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -295,7 +295,6 @@ struct interface {
struct route_node *node;
struct vrf *vrf;
- vrf_id_t vrf_id;
/*
* Has the end users entered `interface XXXX` from the cli in some
@@ -312,56 +311,56 @@ RB_HEAD(if_index_head, interface);
RB_PROTOTYPE(if_index_head, interface, index_entry, if_cmp_index_func)
DECLARE_QOBJ_TYPE(interface);
-#define IFNAME_RB_INSERT(vrf, ifp) \
+#define IFNAME_RB_INSERT(v, ifp) \
({ \
struct interface *_iz = \
- RB_INSERT(if_name_head, &vrf->ifaces_by_name, (ifp)); \
+ RB_INSERT(if_name_head, &v->ifaces_by_name, (ifp)); \
if (_iz) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%s): corruption detected -- interface with this " \
- "name exists already in VRF %u!", \
- __func__, (ifp)->name, (ifp)->vrf_id); \
+ "name exists already in VRF %s!", \
+ __func__, (ifp)->name, (ifp)->vrf->name); \
_iz; \
})
-#define IFNAME_RB_REMOVE(vrf, ifp) \
+#define IFNAME_RB_REMOVE(v, ifp) \
({ \
struct interface *_iz = \
- RB_REMOVE(if_name_head, &vrf->ifaces_by_name, (ifp)); \
+ RB_REMOVE(if_name_head, &v->ifaces_by_name, (ifp)); \
if (_iz == NULL) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%s): corruption detected -- interface with this " \
- "name doesn't exist in VRF %u!", \
- __func__, (ifp)->name, (ifp)->vrf_id); \
+ "name doesn't exist in VRF %s!", \
+ __func__, (ifp)->name, (ifp)->vrf->name); \
_iz; \
})
-#define IFINDEX_RB_INSERT(vrf, ifp) \
+#define IFINDEX_RB_INSERT(v, ifp) \
({ \
- struct interface *_iz = RB_INSERT( \
- if_index_head, &vrf->ifaces_by_index, (ifp)); \
+ struct interface *_iz = \
+ RB_INSERT(if_index_head, &v->ifaces_by_index, (ifp)); \
if (_iz) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%u): corruption detected -- interface with this " \
- "ifindex exists already in VRF %u!", \
- __func__, (ifp)->ifindex, (ifp)->vrf_id); \
+ "ifindex exists already in VRF %s!", \
+ __func__, (ifp)->ifindex, (ifp)->vrf->name); \
_iz; \
})
-#define IFINDEX_RB_REMOVE(vrf, ifp) \
+#define IFINDEX_RB_REMOVE(v, ifp) \
({ \
- struct interface *_iz = RB_REMOVE( \
- if_index_head, &vrf->ifaces_by_index, (ifp)); \
+ struct interface *_iz = \
+ RB_REMOVE(if_index_head, &v->ifaces_by_index, (ifp)); \
if (_iz == NULL) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%u): corruption detected -- interface with this " \
- "ifindex doesn't exist in VRF %u!", \
- __func__, (ifp)->ifindex, (ifp)->vrf_id); \
+ "ifindex doesn't exist in VRF %s!", \
+ __func__, (ifp)->ifindex, (ifp)->vrf->name); \
_iz; \
})
@@ -548,9 +547,9 @@ extern int if_is_up(const struct interface *ifp);
extern int if_is_running(const struct interface *ifp);
extern int if_is_operative(const struct interface *ifp);
extern int if_is_no_ptm_operative(const struct interface *ifp);
-extern int if_is_loopback(const struct interface *ifp);
+extern int if_is_loopback_exact(const struct interface *ifp);
extern int if_is_vrf(const struct interface *ifp);
-extern bool if_is_loopback_or_vrf(const struct interface *ifp);
+extern bool if_is_loopback(const struct interface *ifp);
extern int if_is_broadcast(const struct interface *ifp);
extern int if_is_pointopoint(const struct interface *ifp);
extern int if_is_multicast(const struct interface *ifp);
diff --git a/lib/json.c b/lib/json.c
index cfba6ea3b6..854a3d59d1 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -39,17 +39,41 @@ bool use_json(const int argc, struct cmd_token *argv[])
return false;
}
+struct json_object *json_object_new_stringv(const char *fmt, va_list args)
+{
+ struct json_object *ret;
+ char *text, buf[256];
+
+ text = vasnprintfrr(MTYPE_TMP, buf, sizeof(buf), fmt, args);
+ ret = json_object_new_string(text);
+
+ if (text != buf)
+ XFREE(MTYPE_TMP, text);
+ return ret;
+}
+
void json_array_string_add(json_object *json, const char *str)
{
json_object_array_add(json, json_object_new_string(str));
}
+void json_array_string_addv(json_object *json, const char *fmt, va_list args)
+{
+ json_object_array_add(json, json_object_new_stringv(fmt, args));
+}
+
void json_object_string_add(struct json_object *obj, const char *key,
const char *s)
{
json_object_object_add(obj, key, json_object_new_string(s));
}
+void json_object_string_addv(struct json_object *obj, const char *key,
+ const char *fmt, va_list args)
+{
+ json_object_object_add(obj, key, json_object_new_stringv(fmt, args));
+}
+
void json_object_int_add(struct json_object *obj, const char *key, int64_t i)
{
json_object_object_add(obj, key, json_object_new_int64(i));
diff --git a/lib/json.h b/lib/json.h
index fe208f4fa9..9d33ac7ae3 100644
--- a/lib/json.h
+++ b/lib/json.h
@@ -26,6 +26,7 @@ extern "C" {
#endif
#include "command.h"
+#include "printfrr.h"
#include <json-c/json.h>
/*
@@ -59,6 +60,53 @@ extern struct json_object *json_object_lock(struct json_object *obj);
extern void json_object_free(struct json_object *obj);
extern void json_array_string_add(json_object *json, const char *str);
+/* printfrr => json helpers */
+
+PRINTFRR(3, 0)
+extern void json_object_string_addv(struct json_object *obj, const char *key,
+ const char *fmt, va_list args);
+PRINTFRR(3, 4)
+static inline void json_object_string_addf(struct json_object *obj,
+ const char *key, const char *fmt,
+ ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ json_object_string_addv(obj, key, fmt, args);
+ va_end(args);
+}
+
+PRINTFRR(2, 0)
+extern void json_array_string_addv(json_object *json, const char *fmt,
+ va_list args);
+PRINTFRR(2, 3)
+static inline void json_array_string_addf(struct json_object *obj,
+ const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ json_array_string_addv(obj, fmt, args);
+ va_end(args);
+}
+
+PRINTFRR(1, 0)
+extern struct json_object *json_object_new_stringv(const char *fmt,
+ va_list args);
+PRINTFRR(1, 2)
+static inline struct json_object *json_object_new_stringf(const char *fmt, ...)
+{
+ struct json_object *ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = json_object_new_stringv(fmt, args);
+ va_end(args);
+
+ return ret;
+}
+
#define JSON_STR "JavaScript Object Notation\n"
/* NOTE: json-c lib has following commit 316da85 which
diff --git a/lib/link_state.c b/lib/link_state.c
index 7d2e6f6422..b0bc386b79 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -1010,11 +1010,11 @@ void ls_ted_del_all(struct ls_ted *ted)
return;
/* First remove Vertices, Edges and Subnets and associated Link State */
- frr_each (vertices, &ted->vertices, vertex)
+ frr_each_safe (vertices, &ted->vertices, vertex)
ls_vertex_del_all(ted, vertex);
- frr_each (edges, &ted->edges, edge)
+ frr_each_safe (edges, &ted->edges, edge)
ls_edge_del_all(ted, edge);
- frr_each (subnets, &ted->subnets, subnet)
+ frr_each_safe (subnets, &ted->subnets, subnet)
ls_subnet_del_all(ted, subnet);
/* then remove TED itself */
@@ -1031,17 +1031,17 @@ void ls_ted_clean(struct ls_ted *ted)
return;
/* First, start with Vertices */
- frr_each (vertices, &ted->vertices, vertex)
+ frr_each_safe (vertices, &ted->vertices, vertex)
if (vertex->status == ORPHAN)
ls_vertex_del_all(ted, vertex);
/* Then Edges */
- frr_each (edges, &ted->edges, edge)
+ frr_each_safe (edges, &ted->edges, edge)
if (edge->status == ORPHAN)
ls_edge_del_all(ted, edge);
/* and Subnets */
- frr_each (subnets, &ted->subnets, subnet)
+ frr_each_safe (subnets, &ted->subnets, subnet)
if (subnet->status == ORPHAN)
ls_subnet_del_all(ted, subnet);
diff --git a/lib/log_vty.c b/lib/log_vty.c
index 9911323553..621949ab57 100644
--- a/lib/log_vty.c
+++ b/lib/log_vty.c
@@ -269,14 +269,14 @@ DEFUN_HIDDEN (no_config_log_monitor,
return CMD_SUCCESS;
}
-DEFPY (debug_uid_backtrace,
- debug_uid_backtrace_cmd,
- "[no] debug unique-id UID backtrace",
- NO_STR
- DEBUG_STR
- "Options per individual log message, by unique ID\n"
- "Log message unique ID (XXXXX-XXXXX)\n"
- "Add backtrace to log when message is printed\n")
+DEFPY_NOSH (debug_uid_backtrace,
+ debug_uid_backtrace_cmd,
+ "[no] debug unique-id UID backtrace",
+ NO_STR
+ DEBUG_STR
+ "Options per individual log message, by unique ID\n"
+ "Log message unique ID (XXXXX-XXXXX)\n"
+ "Add backtrace to log when message is printed\n")
{
struct xrefdata search, *xrd;
struct xrefdata_logmsg *xrdl;
@@ -285,10 +285,9 @@ DEFPY (debug_uid_backtrace,
strlcpy(search.uid, uid, sizeof(search.uid));
xrd = xrefdata_uid_find(&xrefdata_uid, &search);
- if (!xrd) {
- vty_out(vty, "%% no log message with ID \"%s\" found\n", uid);
- return CMD_WARNING;
- }
+ if (!xrd)
+ return CMD_ERR_NOTHING_TODO;
+
if (xrd->xref->type != XREFT_LOGMSG) {
vty_out(vty, "%% ID \"%s\" is not a log message\n", uid);
return CMD_WARNING;
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index af9cd2d79a..e8c678ad71 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -1035,7 +1035,6 @@ void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh)
{
- char buf[100];
struct vrf *vrf;
json_object *json_backups = NULL;
int i;
@@ -1046,26 +1045,18 @@ void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh)
ifindex2ifname(nh->ifindex, nh->vrf_id));
break;
case NEXTHOP_TYPE_IPV4:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI4", &nh->gate.ipv4);
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI4", &nh->gate.ipv4);
json_object_string_add(j, "vrfId",
ifindex2ifname(nh->ifindex, nh->vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI6", &nh->gate.ipv6);
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI6", &nh->gate.ipv6);
json_object_string_add(j, "vrfId",
ifindex2ifname(nh->ifindex, nh->vrf_id));
break;
diff --git a/lib/northbound.c b/lib/northbound.c
index 6edd5184ef..49adea6d53 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -830,8 +830,7 @@ int nb_candidate_validate(struct nb_context *context,
struct nb_config_cbs changes;
int ret;
- if (nb_candidate_validate_yang(candidate, errmsg, sizeof(errmsg_len))
- != NB_OK)
+ if (nb_candidate_validate_yang(candidate, errmsg, errmsg_len) != NB_OK)
return NB_ERR_VALIDATION;
RB_INIT(nb_config_cbs, &changes);
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
index e62a83cee2..e1c8983fca 100644
--- a/lib/northbound_confd.c
+++ b/lib/northbound_confd.c
@@ -491,6 +491,47 @@ static void *thread_cdb_trigger_subscriptions(void *data)
return NULL;
}
+static int frr_confd_subscribe(const struct lysc_node *snode, void *arg)
+{
+ struct yang_module *module = arg;
+ struct nb_node *nb_node;
+ int *spoint;
+ int ret;
+
+ switch (snode->nodetype) {
+ case LYS_CONTAINER:
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ case LYS_LIST:
+ break;
+ default:
+ return YANG_ITER_CONTINUE;
+ }
+
+ if (CHECK_FLAG(snode->flags, LYS_CONFIG_R))
+ return YANG_ITER_CONTINUE;
+
+ nb_node = snode->priv;
+ if (!nb_node)
+ return YANG_ITER_CONTINUE;
+
+ DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'", __func__,
+ nb_node->xpath);
+
+ spoint = XMALLOC(MTYPE_CONFD, sizeof(*spoint));
+ ret = cdb_subscribe2(cdb_sub_sock, CDB_SUB_RUNNING_TWOPHASE,
+ CDB_SUB_WANT_ABORT_ON_ABORT, 3, spoint,
+ module->confd_hash, nb_node->xpath);
+ if (ret != CONFD_OK) {
+ flog_err_confd("cdb_subscribe2");
+ XFREE(MTYPE_CONFD, spoint);
+ return YANG_ITER_CONTINUE;
+ }
+
+ listnode_add(confd_spoints, spoint);
+ return YANG_ITER_CONTINUE;
+}
+
static int frr_confd_init_cdb(void)
{
struct yang_module *module;
@@ -514,8 +555,6 @@ static int frr_confd_init_cdb(void)
/* Subscribe to all loaded YANG data modules. */
confd_spoints = list_new();
RB_FOREACH (module, yang_modules, &yang_modules) {
- struct lysc_node *snode;
-
module->confd_hash = confd_str2hash(module->info->ns);
if (module->confd_hash == 0) {
flog_err(
@@ -530,42 +569,8 @@ static int frr_confd_init_cdb(void)
* entire YANG module. So we have to find the top level
* nodes ourselves and subscribe to their paths.
*/
- LY_LIST_FOR (module->info->data, snode) {
- struct nb_node *nb_node;
- int *spoint;
- int ret;
-
- switch (snode->nodetype) {
- case LYS_CONTAINER:
- case LYS_LEAF:
- case LYS_LEAFLIST:
- case LYS_LIST:
- break;
- default:
- continue;
- }
-
- if (CHECK_FLAG(snode->flags, LYS_CONFIG_R))
- continue;
-
- nb_node = snode->priv;
- if (!nb_node)
- continue;
-
- DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'",
- __func__, nb_node->xpath);
-
- spoint = XMALLOC(MTYPE_CONFD, sizeof(*spoint));
- ret = cdb_subscribe2(
- cdb_sub_sock, CDB_SUB_RUNNING_TWOPHASE,
- CDB_SUB_WANT_ABORT_ON_ABORT, 3, spoint,
- module->confd_hash, nb_node->xpath);
- if (ret != CONFD_OK) {
- flog_err_confd("cdb_subscribe2");
- XFREE(MTYPE_CONFD, spoint);
- }
- listnode_add(confd_spoints, spoint);
- }
+ yang_snodes_iterate(module->info, frr_confd_subscribe, 0,
+ module);
}
if (cdb_subscribe_done(cdb_sub_sock) != CONFD_OK) {
@@ -705,7 +710,7 @@ static int frr_confd_data_get_next(struct confd_trans_ctx *tctx,
confd_data_reply_next_key(tctx, v, keys.num,
(long)nb_next);
} else {
- char pointer_str[16];
+ char pointer_str[32];
/*
* ConfD 6.6 user guide, chapter 6.11 (Operational data
@@ -843,7 +848,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx,
const void *nb_next;
#define CONFD_OBJECTS_PER_TIME 100
struct confd_next_object objects[CONFD_OBJECTS_PER_TIME + 1];
- char pseudo_keys[CONFD_OBJECTS_PER_TIME][16];
+ char pseudo_keys[CONFD_OBJECTS_PER_TIME][32];
int nobjects = 0;
frr_confd_get_xpath(kp, xpath, sizeof(xpath));
@@ -868,7 +873,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx,
memset(objects, 0, sizeof(objects));
for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) {
struct confd_next_object *object;
- struct lysc_node *child;
+ const struct lysc_node *child;
struct yang_data *data;
size_t nvalues = 0;
@@ -1189,6 +1194,8 @@ static int frr_confd_dp_ctl_read(struct thread *thread)
thread_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl);
frr_confd_dp_read(dctx, fd);
+
+ return 0;
}
static int frr_confd_dp_worker_read(struct thread *thread)
@@ -1199,6 +1206,8 @@ static int frr_confd_dp_worker_read(struct thread *thread)
thread_add_read(master, frr_confd_dp_worker_read, dctx, fd, &t_dp_worker);
frr_confd_dp_read(dctx, fd);
+
+ return 0;
}
static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg)
diff --git a/lib/plist.c b/lib/plist.c
index a53b087a46..046ccadc09 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1010,7 +1010,6 @@ static void vty_show_prefix_entry(struct vty *vty, json_object *json, afi_t afi,
if (json) {
json_object *json_entry;
- char buf[BUFSIZ];
json_entry = json_object_new_object();
json_object_array_add(json_entries, json_entry);
@@ -1021,10 +1020,9 @@ static void vty_show_prefix_entry(struct vty *vty, json_object *json, afi_t afi,
json_object_string_add(
json_entry, "type",
prefix_list_type_str(pentry));
- json_object_string_add(
- json_entry, "prefix",
- prefix2str(&pentry->prefix, buf,
- sizeof(buf)));
+ json_object_string_addf(json_entry, "prefix",
+ "%pFX",
+ &pentry->prefix);
if (pentry->ge)
json_object_int_add(
@@ -1127,14 +1125,7 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
master, dtype, seqnum);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
-
- return CMD_SUCCESS;
+ return vty_json(vty, json);
}
static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi,
@@ -1592,9 +1583,7 @@ int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name,
json_object_object_add(json, "ipv6PrefixList",
json_prefix);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
vty_out(vty, "ip%s prefix-list %s: %d entries\n",
afi == AFI_IP ? "" : "v6", plist->name, plist->count);
diff --git a/lib/routemap.c b/lib/routemap.c
index 6227ebf158..7f733c8114 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -34,6 +34,7 @@
#include "lib_errors.h"
#include "table.h"
#include "json.h"
+#include "jhash.h"
DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map");
DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name");
@@ -47,6 +48,27 @@ DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP_DATA, "Route map dependency data");
DEFINE_QOBJ_TYPE(route_map_index);
DEFINE_QOBJ_TYPE(route_map);
+static int rmap_cmd_name_cmp(const struct route_map_rule_cmd_proxy *a,
+ const struct route_map_rule_cmd_proxy *b)
+{
+ return strcmp(a->cmd->str, b->cmd->str);
+}
+
+static uint32_t rmap_cmd_name_hash(const struct route_map_rule_cmd_proxy *item)
+{
+ return jhash(item->cmd->str, strlen(item->cmd->str), 0xbfd69320);
+}
+
+DECLARE_HASH(rmap_cmd_name, struct route_map_rule_cmd_proxy, itm,
+ rmap_cmd_name_cmp, rmap_cmd_name_hash);
+
+static struct rmap_cmd_name_head rmap_match_cmds[1] = {
+ INIT_HASH(rmap_match_cmds[0]),
+};
+static struct rmap_cmd_name_head rmap_set_cmds[1] = {
+ INIT_HASH(rmap_set_cmds[0]),
+};
+
#define IPv4_PREFIX_LIST "ip address prefix-list"
#define IPv6_PREFIX_LIST "ipv6 address prefix-list"
@@ -61,12 +83,6 @@ struct route_map_pentry_dep {
route_map_event_t event;
};
-/* Vector for route match rules. */
-static vector route_match_vec;
-
-/* Vector for route set rules. */
-static vector route_set_vec;
-
static void route_map_pfx_tbl_update(route_map_event_t event,
struct route_map_index *index, afi_t afi,
const char *plist_name);
@@ -159,6 +175,22 @@ void route_map_no_match_ip_next_hop_hook(int (*func)(
rmap_match_set_hook.no_match_ip_next_hop = func;
}
+/* match ipv6 next-hop */
+void route_map_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.match_ipv6_next_hop = func;
+}
+
+/* no match ipv6 next-hop */
+void route_map_no_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop = func;
+}
+
/* match ip next hop prefix list */
void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -250,6 +282,22 @@ void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
}
+/* match ipv6 next-hop prefix-list */
+void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.match_ipv6_next_hop_prefix_list = func;
+}
+
+/* no match ipv6 next-hop prefix-list */
+void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list = func;
+}
+
/* match metric */
void route_map_match_metric_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -1026,14 +1074,7 @@ static int vty_show_route_map(struct vty *vty, const char *name, bool use_json)
list_delete(&maplist);
}
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
-
- return CMD_SUCCESS;
+ return vty_json(vty, json);
}
/* Unused route map details */
@@ -1231,40 +1272,40 @@ static struct route_map_rule *route_map_rule_new(void)
}
/* Install rule command to the match list. */
-void route_map_install_match(const struct route_map_rule_cmd *cmd)
+void _route_map_install_match(struct route_map_rule_cmd_proxy *proxy)
{
- vector_set(route_match_vec, (void *)cmd);
+ rmap_cmd_name_add(rmap_match_cmds, proxy);
}
/* Install rule command to the set list. */
-void route_map_install_set(const struct route_map_rule_cmd *cmd)
+void _route_map_install_set(struct route_map_rule_cmd_proxy *proxy)
{
- vector_set(route_set_vec, (void *)cmd);
+ rmap_cmd_name_add(rmap_set_cmds, proxy);
}
/* Lookup rule command from match list. */
static const struct route_map_rule_cmd *route_map_lookup_match(const char *name)
{
- unsigned int i;
- const struct route_map_rule_cmd *rule;
+ struct route_map_rule_cmd refcmd = {.str = name};
+ struct route_map_rule_cmd_proxy ref = {.cmd = &refcmd};
+ struct route_map_rule_cmd_proxy *res;
- for (i = 0; i < vector_active(route_match_vec); i++)
- if ((rule = vector_slot(route_match_vec, i)) != NULL)
- if (strcmp(rule->str, name) == 0)
- return rule;
+ res = rmap_cmd_name_find(rmap_match_cmds, &ref);
+ if (res)
+ return res->cmd;
return NULL;
}
/* Lookup rule command from set list. */
static const struct route_map_rule_cmd *route_map_lookup_set(const char *name)
{
- unsigned int i;
- const struct route_map_rule_cmd *rule;
+ struct route_map_rule_cmd refcmd = {.str = name};
+ struct route_map_rule_cmd_proxy ref = {.cmd = &refcmd};
+ struct route_map_rule_cmd_proxy *res;
- for (i = 0; i < vector_active(route_set_vec); i++)
- if ((rule = vector_slot(route_set_vec, i)) != NULL)
- if (strcmp(rule->str, name) == 0)
- return rule;
+ res = rmap_cmd_name_find(rmap_set_cmds, &ref);
+ if (res)
+ return res->cmd;
return NULL;
}
@@ -3161,11 +3202,21 @@ void route_map_rule_tag_free(void *rule)
void route_map_finish(void)
{
int i;
+ struct route_map_rule_cmd_proxy *proxy;
+
+ /* these 2 hash tables have INIT_HASH initializers, so the "default"
+ * state is "initialized & empty" => fini() followed by init() to
+ * return to that same state
+ */
+ while ((proxy = rmap_cmd_name_pop(rmap_match_cmds)))
+ (void)proxy;
+ rmap_cmd_name_fini(rmap_match_cmds);
+ rmap_cmd_name_init(rmap_match_cmds);
- vector_free(route_match_vec);
- route_match_vec = NULL;
- vector_free(route_set_vec);
- route_set_vec = NULL;
+ while ((proxy = rmap_cmd_name_pop(rmap_set_cmds)))
+ (void)proxy;
+ rmap_cmd_name_fini(rmap_set_cmds);
+ rmap_cmd_name_init(rmap_set_cmds);
/*
* All protocols are setting these to NULL
@@ -3309,9 +3360,6 @@ void route_map_init(void)
{
int i;
- /* Make vector for match and set. */
- route_match_vec = vector_init(1);
- route_set_vec = vector_init(1);
route_map_master_hash =
hash_create_size(8, route_map_hash_key_make, route_map_hash_cmp,
"Route Map Master Hash");
diff --git a/lib/routemap.h b/lib/routemap.h
index f8fdc67d57..6c4916898a 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -21,6 +21,7 @@
#ifndef _ZEBRA_ROUTEMAP_H
#define _ZEBRA_ROUTEMAP_H
+#include "typesafe.h"
#include "prefix.h"
#include "memory.h"
#include "qobj.h"
@@ -243,12 +244,16 @@ DECLARE_QOBJ_TYPE(route_map);
(strmatch(C, "frr-route-map:ipv6-address-list"))
#define IS_MATCH_IPv4_NEXTHOP_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-list"))
+#define IS_MATCH_IPv6_NEXTHOP_LIST(C) \
+ (strmatch(C, "frr-route-map:ipv6-next-hop-list"))
#define IS_MATCH_IPv4_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-prefix-list"))
#define IS_MATCH_IPv6_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv6-prefix-list"))
#define IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-prefix-list"))
+#define IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(C) \
+ (strmatch(C, "frr-route-map:ipv6-next-hop-prefix-list"))
#define IS_MATCH_IPv4_NEXTHOP_TYPE(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-type"))
#define IS_MATCH_IPv6_NEXTHOP_TYPE(C) \
@@ -422,8 +427,37 @@ extern enum rmap_compile_rets
route_map_delete_set(struct route_map_index *index,
const char *set_name, const char *set_arg);
+/* struct route_map_rule_cmd is kept const in order to not have writable
+ * function pointers (which is a security benefit.) Hence, below struct is
+ * used as proxy for hashing these for by-name lookup.
+ */
+
+PREDECL_HASH(rmap_cmd_name);
+
+struct route_map_rule_cmd_proxy {
+ struct rmap_cmd_name_item itm;
+ const struct route_map_rule_cmd *cmd;
+};
+
+/* ... and just automatically create a proxy struct for each call location
+ * to route_map_install_{match,set} to avoid unnecessarily added boilerplate
+ * for each route-map user
+ */
+
+#define route_map_install_match(c) \
+ do { \
+ static struct route_map_rule_cmd_proxy proxy = {.cmd = c}; \
+ _route_map_install_match(&proxy); \
+ } while (0)
+
+#define route_map_install_set(c) \
+ do { \
+ static struct route_map_rule_cmd_proxy proxy = {.cmd = c}; \
+ _route_map_install_set(&proxy); \
+ } while (0)
+
/* Install rule command to the match list. */
-extern void route_map_install_match(const struct route_map_rule_cmd *cmd);
+extern void _route_map_install_match(struct route_map_rule_cmd_proxy *proxy);
/*
* Install rule command to the set list.
@@ -434,7 +468,7 @@ extern void route_map_install_match(const struct route_map_rule_cmd *cmd);
* in the apply command). See 'set metric' command
* as it is handled in ripd/ripngd and ospfd.
*/
-extern void route_map_install_set(const struct route_map_rule_cmd *cmd);
+extern void _route_map_install_set(struct route_map_rule_cmd_proxy *proxy);
/* Lookup route map by name. */
extern struct route_map *route_map_lookup_by_name(const char *name);
@@ -525,9 +559,16 @@ extern void route_map_match_ip_next_hop_hook(int (*func)(
char *errmsg, size_t errmsg_len));
/* no match ip next hop */
extern void route_map_no_match_ip_next_hop_hook(int (*func)(
- struct route_map_index *index, const char *command,
- const char *arg, route_map_event_t type,
- char *errmsg, size_t errmsg_len));
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* match ipv6 next hop */
+extern void route_map_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* no match ipv6 next hop */
+extern void route_map_no_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
/* match ip next hop prefix list */
extern void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -578,6 +619,14 @@ extern void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type,
char *errmsg, size_t errmsg_len));
+/* match ipv6 next-hop prefix-list */
+extern void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* no match ipv6 next-hop prefix-list */
+extern void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
/* match metric */
extern void route_map_match_metric_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -713,6 +762,33 @@ struct route_map_match_set_hooks {
route_map_event_t type,
char *errmsg, size_t errmsg_len);
+ /* match ipv6 next hop */
+ int (*match_ipv6_next_hop)(struct route_map_index *index,
+ const char *command, const char *arg,
+ route_map_event_t type, char *errmsg,
+ size_t errmsg_len);
+
+ /* no match ipv6 next hop */
+ int (*no_match_ipv6_next_hop)(struct route_map_index *index,
+ const char *command, const char *arg,
+ route_map_event_t type, char *errmsg,
+ size_t errmsg_len);
+
+ /* match ipv6 next hop prefix-list */
+ int (*match_ipv6_next_hop_prefix_list)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type,
+ char *errmsg, size_t errmsg_len);
+
+ /* no match ipv6 next-hop prefix-list */
+ int (*no_match_ipv6_next_hop_prefix_list)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type,
+ char *errmsg,
+ size_t errmsg_len);
+
/* match ip next hop prefix list */
int (*match_ip_next_hop_prefix_list)(struct route_map_index *index,
const char *command,
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index d7d4a9a81f..52fcaaba53 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -41,7 +41,7 @@
DEFPY_YANG_NOSH(
route_map, route_map_cmd,
- "route-map WORD$name <deny|permit>$action (1-65535)$sequence",
+ "route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
ROUTE_MAP_CMD_STR
ROUTE_MAP_OP_CMD_STR
ROUTE_MAP_SEQUENCE_CMD_STR)
@@ -71,7 +71,7 @@ DEFPY_YANG_NOSH(
DEFPY_YANG(
no_route_map_all, no_route_map_all_cmd,
- "no route-map WORD$name",
+ "no route-map RMAP_NAME$name",
NO_STR
ROUTE_MAP_CMD_STR)
{
@@ -86,7 +86,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_route_map, no_route_map_cmd,
- "no route-map WORD$name <deny|permit>$action (1-65535)$sequence",
+ "no route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
NO_STR
ROUTE_MAP_CMD_STR
ROUTE_MAP_OP_CMD_STR
@@ -551,6 +551,7 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(
dnode, "./rmap-match-condition/interface"));
} else if (IS_MATCH_IPv4_ADDRESS_LIST(condition)
+ || IS_MATCH_IPv6_NEXTHOP_LIST(condition)
|| IS_MATCH_IPv4_NEXTHOP_LIST(condition)) {
acl = NULL;
if ((ln = yang_dnode_get(dnode,
@@ -562,8 +563,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
if (IS_MATCH_IPv4_ADDRESS_LIST(condition))
vty_out(vty, " match ip address %s\n", acl);
- else
+ else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition))
vty_out(vty, " match ip next-hop %s\n", acl);
+ else
+ vty_out(vty, " match ipv6 next-hop %s\n", acl);
} else if (IS_MATCH_IPv4_PREFIX_LIST(condition)) {
vty_out(vty, " match ip address prefix-list %s\n",
yang_dnode_get_string(
@@ -572,6 +575,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, " match ip next-hop prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
+ } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
+ vty_out(vty, " match ipv6 next-hop prefix-list %s\n",
+ yang_dnode_get_string(
+ dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
vty_out(vty, " match ipv6 address %s\n",
yang_dnode_get_string(
@@ -791,12 +798,12 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, " match extcommunity %s\n", acl);
} else if (IS_MATCH_IPV4_NH(condition)) {
- vty_out(vty, " match ip next-hop %s\n",
+ vty_out(vty, " match ip next-hop address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:ipv4-address"));
} else if (IS_MATCH_IPV6_NH(condition)) {
- vty_out(vty, " match ipv6 next-hop %s\n",
+ vty_out(vty, " match ipv6 next-hop address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:ipv6-address"));
@@ -1440,7 +1447,7 @@ void route_map_description_show(struct vty *vty, const struct lyd_node *dnode,
DEFPY_YANG(
route_map_optimization, route_map_optimization_cmd,
- "[no] route-map WORD$name optimization",
+ "[no] route-map RMAP_NAME$name optimization",
NO_STR
ROUTE_MAP_CMD_STR
"Configure route-map optimization\n")
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 3473ca2aea..51b879959f 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -601,6 +601,16 @@ static int lib_route_map_entry_match_condition_list_name_modify(
rhc->rhc_rmi, "ip next-hop", acl,
RMAP_EVENT_FILTER_ADDED,
args->errmsg, args->errmsg_len);
+ } else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition)) {
+ if (rmap_match_set_hook.match_ipv6_next_hop == NULL)
+ return NB_OK;
+ rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_next_hop;
+ rhc->rhc_rule = "ipv6 next-hop";
+ rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
+ rv = rmap_match_set_hook.match_ipv6_next_hop(
+ rhc->rhc_rmi, "ipv6 next-hop", acl,
+ RMAP_EVENT_FILTER_ADDED, args->errmsg,
+ args->errmsg_len);
} else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition)) {
if (rmap_match_set_hook.match_ip_next_hop_prefix_list == NULL)
return NB_OK;
@@ -612,6 +622,16 @@ static int lib_route_map_entry_match_condition_list_name_modify(
rhc->rhc_rmi, "ip next-hop prefix-list", acl,
RMAP_EVENT_PLIST_ADDED,
args->errmsg, args->errmsg_len);
+ } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
+ if (rmap_match_set_hook.match_ipv6_next_hop_prefix_list == NULL)
+ return NB_OK;
+ rhc->rhc_mhook =
+ rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list;
+ rhc->rhc_rule = "ipv6 next-hop prefix-list";
+ rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
+ rv = rmap_match_set_hook.match_ipv6_next_hop_prefix_list(
+ rhc->rhc_rmi, "ipv6 next-hop prefix-list", acl,
+ RMAP_EVENT_PLIST_ADDED, args->errmsg, args->errmsg_len);
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
if (rmap_match_set_hook.match_ipv6_address == NULL)
return NB_OK;
diff --git a/lib/srv6.c b/lib/srv6.c
index ccb94b2f76..aacd30a7af 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -161,12 +161,10 @@ void srv6_locator_chunk_free(struct srv6_locator_chunk *chunk)
json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
{
- char str[256];
json_object *jo_root = NULL;
jo_root = json_object_new_object();
- prefix2str(&chunk->prefix, str, sizeof(str));
- json_object_string_add(jo_root, "prefix", str);
+ json_object_string_addf(jo_root, "prefix", "%pFX", &chunk->prefix);
json_object_string_add(jo_root, "proto",
zebra_route_string(chunk->proto));
@@ -175,7 +173,6 @@ json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
json_object *srv6_locator_json(const struct srv6_locator *loc)
{
- char str[256];
struct listnode *node;
struct srv6_locator_chunk *chunk;
json_object *jo_root = NULL;
@@ -188,8 +185,7 @@ json_object *srv6_locator_json(const struct srv6_locator *loc)
json_object_string_add(jo_root, "name", loc->name);
/* set prefix */
- prefix2str(&loc->prefix, str, sizeof(str));
- json_object_string_add(jo_root, "prefix", str);
+ json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
diff --git a/lib/vrf.c b/lib/vrf.c
index a9a5a83794..5dc4e05855 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -354,13 +354,6 @@ const char *vrf_id_to_name(vrf_id_t vrf_id)
return VRF_LOGNAME(vrf);
}
-/* Get the data pointer of the specified VRF. If not found, create one. */
-void *vrf_info_get(vrf_id_t vrf_id)
-{
- struct vrf *vrf = vrf_get(vrf_id, NULL);
- return vrf->info;
-}
-
/* Look up the data pointer of the specified VRF. */
void *vrf_info_lookup(vrf_id_t vrf_id)
{
diff --git a/lib/vrf.h b/lib/vrf.h
index 0e2e601a7e..73e324c152 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -176,8 +176,6 @@ static inline uint32_t vrf_interface_count(struct vrf *vrf)
* Utilities to obtain the user data
*/
-/* Get the data pointer of the specified VRF. If not found, create one. */
-extern void *vrf_info_get(vrf_id_t);
/* Look up the data pointer of the specified VRF. */
extern void *vrf_info_lookup(vrf_id_t);
diff --git a/lib/vty.c b/lib/vty.c
index 3df623502b..8eaf13619b 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -48,6 +48,7 @@
#include "lib_errors.h"
#include "northbound_cli.h"
#include "printfrr.h"
+#include "json.h"
#include <arpa/telnet.h>
#include <termios.h>
@@ -280,6 +281,21 @@ done:
return len;
}
+int vty_json(struct vty *vty, struct json_object *json)
+{
+ const char *text;
+
+ if (!json)
+ return CMD_SUCCESS;
+
+ text = json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
+ vty_out(vty, "%s\n", text);
+ json_object_free(json);
+
+ return CMD_SUCCESS;
+}
+
/* Output current time to the vty. */
void vty_time_print(struct vty *vty, int cr)
{
diff --git a/lib/vty.h b/lib/vty.h
index 62e2518957..9ffbce3268 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -39,6 +39,8 @@
extern "C" {
#endif
+struct json_object;
+
#define VTY_BUFSIZ 4096
#define VTY_MAXHIST 20
#define VTY_MAXDEPTH 8
@@ -321,7 +323,11 @@ extern struct vty *vty_stdio(void (*atclose)(int isexit));
extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3);
extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3);
extern void vty_endframe(struct vty *, const char *);
-bool vty_set_include(struct vty *vty, const char *regexp);
+extern bool vty_set_include(struct vty *vty, const char *regexp);
+/* returns CMD_SUCCESS so you can do a one-line "return vty_json(...)"
+ * NULL check and json_object_free() is included.
+ */
+extern int vty_json(struct vty *vty, struct json_object *json);
extern bool vty_read_config(struct nb_config *config, const char *config_file,
char *config_default_dir);
diff --git a/lib/zclient.c b/lib/zclient.c
index a6103cfee9..000dcaac8f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -4072,11 +4072,12 @@ enum zclient_send_status zclient_interface_set_master(struct zclient *client,
s = client->obuf;
stream_reset(s);
- zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER, master->vrf_id);
+ zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER,
+ master->vrf->vrf_id);
- stream_putl(s, master->vrf_id);
+ stream_putl(s, master->vrf->vrf_id);
stream_putl(s, master->ifindex);
- stream_putl(s, slave->vrf_id);
+ stream_putl(s, slave->vrf->vrf_id);
stream_putl(s, slave->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));
@@ -4163,7 +4164,7 @@ zclient_send_neigh_discovery_req(struct zclient *zclient,
s = zclient->obuf;
stream_reset(s);
- zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
stream_putc(s, p->family);
@@ -4253,7 +4254,7 @@ int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
{
int ret = 0;
- zclient_create_header(s, cmd, ifp->vrf_id);
+ zclient_create_header(s, cmd, ifp->vrf->vrf_id);
stream_putc(s, sockunion_family(in));
stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
if (out && sockunion_family(out) != AF_UNSPEC) {
@@ -4297,9 +4298,7 @@ int zclient_send_zebra_gre_request(struct zclient *client,
}
s = client->obuf;
stream_reset(s);
- zclient_create_header(s,
- ZEBRA_GRE_GET,
- ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_GRE_GET, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(client);
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 94cec0281f..1092ce13a1 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -143,13 +143,13 @@ static void nhrp_interface_update_source(struct interface *ifp)
{
struct nhrp_interface *nifp = ifp->info;
- if (!nifp->source || !nifp->nbmaifp ||
- ((ifindex_t)nifp->link_idx == nifp->nbmaifp->ifindex &&
- (nifp->link_vrf_id == nifp->nbmaifp->vrf_id)))
+ if (!nifp->source || !nifp->nbmaifp
+ || ((ifindex_t)nifp->link_idx == nifp->nbmaifp->ifindex
+ && (nifp->link_vrf_id == nifp->nbmaifp->vrf->vrf_id)))
return;
nifp->link_idx = nifp->nbmaifp->ifindex;
- nifp->link_vrf_id = nifp->nbmaifp->vrf_id;
+ nifp->link_vrf_id = nifp->nbmaifp->vrf->vrf_id;
debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d, vr %u",
ifp->name, nifp->link_idx, nifp->link_vrf_id);
nhrp_send_zebra_gre_source_set(ifp, nifp->link_idx, nifp->link_vrf_id);
@@ -414,7 +414,7 @@ static void interface_config_update_nhrp_map(struct nhrp_cache_config *cc,
return;
/* gre layer not ready */
- if (ifp->vrf_id == VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id == VRF_UNKNOWN)
return;
c = nhrp_cache_get(ifp, &cc->remote_addr, ctx->enabled ? 1 : 0);
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 76e0978cb6..698c6d0cdf 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -408,9 +408,7 @@ void nhrp_send_zebra_configure_arp(struct interface *ifp, int family)
}
s = zclient->obuf;
stream_reset(s);
- zclient_create_header(s,
- ZEBRA_CONFIGURE_ARP,
- ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_CONFIGURE_ARP, ifp->vrf->vrf_id);
stream_putc(s, family);
stream_putl(s, ifp->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));
@@ -433,9 +431,7 @@ void nhrp_send_zebra_gre_source_set(struct interface *ifp,
}
s = zclient->obuf;
stream_reset(s);
- zclient_create_header(s,
- ZEBRA_GRE_SOURCE_SET,
- ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_GRE_SOURCE_SET, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
stream_putl(s, link_idx);
stream_putl(s, link_vrf_id);
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index f35971ba8c..7e8e34a221 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -1045,12 +1045,8 @@ static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
}
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index b439f947de..99f30a4a06 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1410,7 +1410,6 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct ospf6_route *route, *match;
struct ospf6_external_info *info;
struct prefix prefix_id;
- struct route_node *node;
char ibuf[16];
struct ospf6_redist *red;
@@ -1497,13 +1496,6 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
else
ospf6_route_add_nexthop(match, ifindex, NULL);
- /* create/update binding in external_id_table */
- prefix_id.family = AF_INET;
- prefix_id.prefixlen = IPV4_MAX_BITLEN;
- prefix_id.u.prefix4.s_addr = htonl(info->id);
- node = route_node_get(ospf6->external_id_table, &prefix_id);
- node->info = match;
-
if (IS_OSPF6_DEBUG_ASBR) {
inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf,
sizeof(ibuf));
@@ -2553,10 +2545,7 @@ DEFUN(show_ipv6_ospf6_redistribute, show_ipv6_ospf6_redistribute_cmd,
if (uj) {
json_object_object_add(json, "routes",
json_array_routes);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
if (!all_vrf)
@@ -2787,7 +2776,6 @@ static void ospf6_originate_new_aggr_lsa(struct ospf6 *ospf6,
struct ospf6_external_aggr_rt *aggr)
{
struct prefix prefix_id;
- struct route_node *node;
struct ospf6_lsa *lsa = NULL;
if (IS_OSPF6_DEBUG_AGGR)
@@ -2796,13 +2784,6 @@ static void ospf6_originate_new_aggr_lsa(struct ospf6 *ospf6,
aggr->id = ospf6->external_id++;
- /* create/update binding in external_id_table */
- prefix_id.family = AF_INET;
- prefix_id.prefixlen = 32;
- prefix_id.u.prefix4.s_addr = htonl(aggr->id);
- node = route_node_get(ospf6->external_id_table, &prefix_id);
- node->info = aggr;
-
if (IS_OSPF6_DEBUG_AGGR)
zlog_debug(
"Advertise AS-External Id:%pI4 prefix %pFX metric %u",
@@ -3014,8 +2995,6 @@ static void ospf6_aggr_handle_external_info(void *data)
struct ospf6_lsa *lsa = NULL;
struct ospf6_external_info *info;
struct ospf6 *ospf6 = NULL;
- struct prefix prefix_id;
- struct route_node *node;
rt->aggr_route = NULL;
@@ -3055,13 +3034,6 @@ static void ospf6_aggr_handle_external_info(void *data)
info->id = ospf6->external_id++;
rt->path.origin.id = htonl(info->id);
- /* create/update binding in external_id_table */
- prefix_id.family = AF_INET;
- prefix_id.prefixlen = 32;
- prefix_id.u.prefix4.s_addr = htonl(info->id);
- node = route_node_get(ospf6->external_id_table, &prefix_id);
- node->info = rt;
-
(void)ospf6_originate_type5_type7_lsas(rt, ospf6);
}
@@ -3642,7 +3614,6 @@ void ospf6_handle_external_lsa_origination(struct ospf6 *ospf6,
struct ospf6_external_aggr_rt *aggr;
struct ospf6_external_info *info;
struct prefix prefix_id;
- struct route_node *node;
if (!is_default_prefix(p)) {
aggr = ospf6_external_aggr_match(ospf6,
@@ -3678,14 +3649,6 @@ void ospf6_handle_external_lsa_origination(struct ospf6 *ospf6,
*/
if (!info->id) {
info->id = ospf6->external_id++;
-
- /* create/update binding in external_id_table */
- prefix_id.family = AF_INET;
- prefix_id.prefixlen = 32;
- prefix_id.u.prefix4.s_addr = htonl(info->id);
- node = route_node_get(ospf6->external_id_table, &prefix_id);
- node->info = rt;
-
} else {
prefix_id.family = AF_INET;
prefix_id.prefixlen = 32;
diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c
index fc1e718540..c124f17e34 100644
--- a/ospf6d/ospf6_bfd.c
+++ b/ospf6d/ospf6_bfd.c
@@ -143,7 +143,7 @@ void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
bfd_sess_set_ipv6_addrs(on->bfd_session, on->ospf6_if->linklocal_addr,
&on->linklocal_addr);
bfd_sess_set_interface(on->bfd_session, oi->interface->name);
- bfd_sess_set_vrf(on->bfd_session, oi->interface->vrf_id);
+ bfd_sess_set_vrf(on->bfd_session, oi->interface->vrf->vrf_id);
bfd_sess_set_profile(on->bfd_session, oi->bfd_config.profile);
}
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 6e00bd766f..5fed6dfe17 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -151,24 +151,6 @@ void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
ospf6_lsa_originate(oi->area->ospf6, lsa);
}
-void ospf6_remove_id_from_external_id_table(struct ospf6 *ospf6,
- uint32_t id)
-{
- struct prefix prefix_id;
- struct route_node *node;
-
- /* remove binding in external_id_table */
- prefix_id.family = AF_INET;
- prefix_id.prefixlen = 32;
- prefix_id.u.prefix4.s_addr = id;
- node = route_node_lookup(ospf6->external_id_table, &prefix_id);
- assert(node);
- node->info = NULL;
- route_unlock_node(node); /* to free the lookup lock */
- route_unlock_node(node); /* to free the original lock */
-
-}
-
void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
{
uint32_t id = lsa->header->id;
@@ -177,8 +159,6 @@ void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
ospf6_lsa_purge(lsa);
- ospf6_remove_id_from_external_id_table(ospf6, id);
-
/* Delete the corresponding NSSA LSA */
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, lnode, oa)) {
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), id,
diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h
index 775d0d289d..75f3c065bb 100644
--- a/ospf6d/ospf6_flood.h
+++ b/ospf6d/ospf6_flood.h
@@ -39,8 +39,6 @@ extern void ospf6_lsa_originate_area(struct ospf6_lsa *lsa,
struct ospf6_area *oa);
extern void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
struct ospf6_interface *oi);
-void ospf6_remove_id_from_external_id_table(struct ospf6 *ospf6,
- uint32_t id);
void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa);
extern void ospf6_lsa_purge(struct ospf6_lsa *lsa);
diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c
index 4dc2d8af83..84ee35a3ed 100644
--- a/ospf6d/ospf6_gr_helper.c
+++ b/ospf6d/ospf6_gr_helper.c
@@ -1188,12 +1188,8 @@ DEFPY(show_ipv6_ospf6_gr_helper,
show_ospf6_gr_helper_details(vty, ospf6, json, uj, detail);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 4205be38ba..a0c921f419 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -127,7 +127,7 @@ static uint8_t ospf6_default_iftype(struct interface *ifp)
{
if (if_is_pointopoint(ifp))
return OSPF_IFTYPE_POINTOPOINT;
- else if (if_is_loopback_or_vrf(ifp))
+ else if (if_is_loopback(ifp))
return OSPF_IFTYPE_LOOPBACK;
else
return OSPF_IFTYPE_BROADCAST;
@@ -150,7 +150,7 @@ static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi)
: OSPF6_INTERFACE_BANDWIDTH;
}
- ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id);
+ ospf6 = oi->interface->vrf->info;
refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH;
/* A specifed ip ospf cost overrides a calculated one. */
@@ -387,7 +387,7 @@ void ospf6_interface_state_update(struct interface *ifp)
if (if_is_operative(ifp)
&& (ospf6_interface_get_linklocal_address(oi->interface)
- || if_is_loopback_or_vrf(oi->interface)))
+ || if_is_loopback(oi->interface)))
thread_execute(master, interface_up, oi, 0);
else
thread_execute(master, interface_down, oi, 0);
@@ -750,7 +750,7 @@ int interface_up(struct thread *thread)
/* check interface has a link-local address */
if (!(ospf6_interface_get_linklocal_address(oi->interface)
- || if_is_loopback_or_vrf(oi->interface))) {
+ || if_is_loopback(oi->interface))) {
zlog_warn(
"Interface %s has no link local address, can't execute [InterfaceUp]",
oi->interface->name);
@@ -819,7 +819,7 @@ int interface_up(struct thread *thread)
/* Schedule Hello */
if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)
- && !if_is_loopback_or_vrf(oi->interface)) {
+ && !if_is_loopback(oi->interface)) {
thread_add_event(master, ospf6_hello_send, oi, 0,
&oi->thread_send_hello);
}
@@ -1277,10 +1277,7 @@ static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
if (ifp == NULL) {
json_object_string_add(json, "noSuchInterface",
argv[idx_ifname]->arg);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
json_object_free(json_int);
return CMD_WARNING;
}
@@ -1294,10 +1291,7 @@ static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
json_int);
}
}
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (argc == intf_idx) {
ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
@@ -1361,11 +1355,6 @@ static int ospf6_interface_show_traffic(struct vty *vty,
struct ospf6_interface *oi = NULL;
json_object *json_interface;
- if (intf_ifp)
- vrf = vrf_lookup_by_id(intf_ifp->vrf_id);
- else
- vrf = vrf_lookup_by_id(vrf_id);
-
if (!display_once && !use_json) {
vty_out(vty, "\n");
vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
@@ -1379,6 +1368,7 @@ static int ospf6_interface_show_traffic(struct vty *vty,
}
if (intf_ifp == NULL) {
+ vrf = vrf_lookup_by_id(vrf_id);
FOR_ALL_INTERFACES (vrf, ifp) {
if (ifp->info)
oi = (struct ospf6_interface *)ifp->info;
@@ -1488,10 +1478,7 @@ static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
"No Such Interface");
json_object_string_add(json, "interface",
intf_name);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
return CMD_WARNING;
}
if (ifp->info == NULL) {
@@ -1500,10 +1487,7 @@ static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
"OSPF not enabled on this interface");
json_object_string_add(json, "interface",
intf_name);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
return 0;
}
} else {
@@ -1523,12 +1507,8 @@ static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -1685,7 +1665,7 @@ void ospf6_interface_start(struct ospf6_interface *oi)
if (oi->area)
return;
- ospf6 = ospf6_lookup_by_vrf_id(oi->interface->vrf_id);
+ ospf6 = oi->interface->vrf->info;
if (!ospf6)
return;
@@ -2315,7 +2295,7 @@ DEFUN (no_ipv6_ospf6_passive,
THREAD_OFF(oi->thread_sso);
/* don't send hellos over loopback interface */
- if (!if_is_loopback_or_vrf(oi->interface))
+ if (!if_is_loopback(oi->interface))
thread_add_event(master, ospf6_hello_send, oi, 0,
&oi->thread_send_hello);
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 6abc1c7d09..6626b4bed5 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -142,19 +142,15 @@ static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
json_object_string_add(json_loop, "type", name);
json_object_int_add(json_loop, "metric",
ntohs(lsdesc->metric));
- json_object_string_add(json_loop, "interfaceId",
- inet_ntop(AF_INET,
- &lsdesc->interface_id,
- buf, sizeof(buf)));
- json_object_string_add(
- json_loop, "neighborInterfaceId",
- inet_ntop(AF_INET,
- &lsdesc->neighbor_interface_id, buf,
- sizeof(buf)));
- json_object_string_add(
- json_loop, "neighborRouterId",
- inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_loop, "interfaceId", "%pI4",
+ (in_addr_t *)&lsdesc->interface_id);
+ json_object_string_addf(
+ json_loop, "neighborInterfaceId", "%pI4",
+ (in_addr_t *)&lsdesc->neighbor_interface_id);
+ json_object_string_addf(json_loop, "neighborRouterId",
+ "%pI4",
+ &lsdesc->neighbor_router_id);
json_object_array_add(json_arr, json_loop);
} else {
vty_out(vty, " Type: %s Metric: %d\n", name,
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 77f0f8f4e5..99d0de39cf 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -54,7 +54,7 @@ DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary");
-vector ospf6_lsa_handler_vector;
+static struct ospf6_lsa_handler *lsa_handlers[OSPF6_LSTYPE_SIZE];
struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
{
@@ -115,8 +115,13 @@ static struct ospf6_lsa_handler unknown_handler = {
void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler)
{
/* type in handler is host byte order */
- int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
- vector_set_index(ospf6_lsa_handler_vector, index, (void *)handler);
+ unsigned int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
+
+ assertf(index < array_size(lsa_handlers), "index=%x", index);
+ assertf(lsa_handlers[index] == NULL, "old=%s, new=%s",
+ lsa_handlers[index]->lh_name, handler->lh_name);
+
+ lsa_handlers[index] = handler;
}
struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
@@ -124,10 +129,8 @@ struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
struct ospf6_lsa_handler *handler = NULL;
unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
- if (index >= vector_active(ospf6_lsa_handler_vector))
- handler = &unknown_handler;
- else
- handler = vector_slot(ospf6_lsa_handler_vector, index);
+ if (index < array_size(lsa_handlers))
+ handler = lsa_handlers[index];
if (handler == NULL)
handler = &unknown_handler;
@@ -989,13 +992,11 @@ int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
void ospf6_lsa_init(void)
{
- ospf6_lsa_handler_vector = vector_init(0);
ospf6_install_lsa_handler(&unknown_handler);
}
void ospf6_lsa_terminate(void)
{
- vector_free(ospf6_lsa_handler_vector);
}
static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
@@ -1020,27 +1021,32 @@ static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
return buf;
}
-DEFPY (debug_ospf6_lsa_all,
- debug_ospf6_lsa_all_cmd,
- "[no$no] debug ospf6 lsa all",
- NO_STR
- DEBUG_STR
- OSPF6_STR
- "Debug Link State Advertisements (LSAs)\n"
- "Display for all types of LSAs\n")
+void ospf6_lsa_debug_set_all(bool val)
{
unsigned int i;
struct ospf6_lsa_handler *handler = NULL;
- for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
- handler = vector_slot(ospf6_lsa_handler_vector, i);
+ for (i = 0; i < array_size(lsa_handlers); i++) {
+ handler = lsa_handlers[i];
if (handler == NULL)
continue;
- if (!no)
+ if (val)
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
else
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
}
+}
+
+DEFPY (debug_ospf6_lsa_all,
+ debug_ospf6_lsa_all_cmd,
+ "[no$no] debug ospf6 lsa all",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug Link State Advertisements (LSAs)\n"
+ "Display for all types of LSAs\n")
+{
+ ospf6_lsa_debug_set_all(!no);
return CMD_SUCCESS;
}
@@ -1092,8 +1098,8 @@ DEFUN (debug_ospf6_lsa_type,
unsigned int i;
struct ospf6_lsa_handler *handler = NULL;
- for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
- handler = vector_slot(ospf6_lsa_handler_vector, i);
+ for (i = 0; i < array_size(lsa_handlers); i++) {
+ handler = lsa_handlers[i];
if (handler == NULL)
continue;
if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
@@ -1146,8 +1152,8 @@ DEFUN (no_debug_ospf6_lsa_type,
unsigned int i;
struct ospf6_lsa_handler *handler = NULL;
- for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
- handler = vector_slot(ospf6_lsa_handler_vector, i);
+ for (i = 0; i < array_size(lsa_handlers); i++) {
+ handler = lsa_handlers[i];
if (handler == NULL)
continue;
if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
@@ -1194,8 +1200,8 @@ int config_write_ospf6_debug_lsa(struct vty *vty)
const struct ospf6_lsa_handler *handler;
bool debug_all = true;
- for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
- handler = vector_slot(ospf6_lsa_handler_vector, i);
+ for (i = 0; i < array_size(lsa_handlers); i++) {
+ handler = lsa_handlers[i];
if (handler == NULL)
continue;
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL)
@@ -1210,8 +1216,8 @@ int config_write_ospf6_debug_lsa(struct vty *vty)
return 0;
}
- for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
- handler = vector_slot(ospf6_lsa_handler_vector, i);
+ for (i = 0; i < array_size(lsa_handlers); i++) {
+ handler = lsa_handlers[i];
if (handler == NULL)
continue;
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index c0d3cc149b..aa1150afca 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -173,8 +173,6 @@ struct ospf6_lsa_handler {
#define OSPF6_LSA_IS_KNOWN(t) \
(ospf6_get_lsa_handler(t)->lh_type != OSPF6_LSTYPE_UNKNOWN ? 1 : 0)
-extern vector ospf6_lsa_handler_vector;
-
/* Macro for LSA Origination */
/* addr is (struct prefix *) */
#define CONTINUE_IF_ADDRESS_LINKLOCAL(debug, addr) \
@@ -268,6 +266,7 @@ extern int ospf6_lsa_prohibited_duration(uint16_t type, uint32_t id,
extern void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler);
extern struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type);
+extern void ospf6_lsa_debug_set_all(bool val);
extern void ospf6_lsa_init(void);
extern void ospf6_lsa_terminate(void);
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 49a379aa17..352cb137ed 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -409,9 +409,8 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
if (ntohs(hello->hello_interval) != oi->hello_interval) {
zlog_warn(
"VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name, oi->hello_interval,
- ntohs(hello->hello_interval));
+ oi->interface->vrf->name, oi->interface->name,
+ oi->hello_interval, ntohs(hello->hello_interval));
return;
}
@@ -419,9 +418,8 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
if (ntohs(hello->dead_interval) != oi->dead_interval) {
zlog_warn(
"VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name, oi->dead_interval,
- ntohs(hello->dead_interval));
+ oi->interface->vrf->name, oi->interface->name,
+ oi->dead_interval, ntohs(hello->dead_interval));
return;
}
@@ -429,8 +427,15 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_E)
!= OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_E)) {
zlog_warn("VRF %s: IF %s E-bit mismatch",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name);
+ oi->interface->vrf->name, oi->interface->name);
+ return;
+ }
+
+ /* N-bit check */
+ if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_N)
+ != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_N)) {
+ zlog_warn("VRF %s: IF %s N-bit mismatch",
+ oi->interface->vrf->name, oi->interface->name);
return;
}
@@ -622,10 +627,8 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
memcpy(on->options, dbdesc->options,
sizeof(on->options));
} else {
- zlog_warn(
- "VRF %s: Nbr %s: Negotiation failed",
- vrf_id_to_name(on->ospf6_if->interface->vrf_id),
- on->name);
+ zlog_warn("VRF %s: Nbr %s: Negotiation failed",
+ on->ospf6_if->interface->vrf->name, on->name);
return;
}
/* fall through to exchange */
@@ -838,10 +841,8 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
memcpy(on->options, dbdesc->options,
sizeof(on->options));
} else {
- zlog_warn(
- "VRF %s: Nbr %s Negotiation failed",
- vrf_id_to_name(on->ospf6_if->interface->vrf_id),
- on->name);
+ zlog_warn("VRF %s: Nbr %s Negotiation failed",
+ on->ospf6_if->interface->vrf->name, on->name);
return;
}
break;
@@ -1008,8 +1009,8 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
/* Interface MTU check */
if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name, oi->ifmtu, ntohs(dbdesc->ifmtu));
+ oi->interface->vrf->name, oi->interface->name,
+ oi->ifmtu, ntohs(dbdesc->ifmtu));
return;
}
@@ -1515,14 +1516,12 @@ static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
if (oh->area_id == OSPF_AREA_BACKBONE)
zlog_warn(
"VRF %s: I/F %s Message may be via Virtual Link: not supported",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name);
+ oi->interface->vrf->name, oi->interface->name);
else
zlog_warn(
"VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name, &oi->area->area_id,
- &oh->area_id);
+ oi->interface->vrf->name, oi->interface->name,
+ &oi->area->area_id, &oh->area_id);
return MSG_NG;
}
@@ -1530,16 +1529,16 @@ static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
if (oh->instance_id != oi->instance_id) {
zlog_warn(
"VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name, oi->instance_id, oh->instance_id);
+ oi->interface->vrf->name, oi->interface->name,
+ oi->instance_id, oh->instance_id);
return MSG_NG;
}
/* Router-ID check */
if (oh->router_id == oi->area->ospf6->router_id) {
zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
- vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name, &oh->router_id);
+ oi->interface->vrf->name, oi->interface->name,
+ &oh->router_id);
return MSG_NG;
}
return MSG_OK;
@@ -1769,7 +1768,7 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
* Drop packet destined to another VRF.
* This happens when raw_l3mdev_accept is set to 1.
*/
- if (ospf6->vrf_id != oi->interface->vrf_id)
+ if (ospf6->vrf_id != oi->interface->vrf->vrf_id)
return OSPF6_READ_CONTINUE;
oh = (struct ospf6_header *)recvbuf;
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 3d0dde8c65..1a8fedea0c 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -1073,10 +1073,7 @@ static void ospf6_neighbor_show_detail_common(struct vty *vty,
json_object_object_add(json, "neighbors", json_array);
else
json_object_free(json_array);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
}
@@ -1148,12 +1145,8 @@ static int ospf6_neighbor_show_common(struct vty *vty, int argc,
(*showfunc)(vty, on, json, uj);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -1254,7 +1247,6 @@ DEFUN (no_debug_ospf6,
OSPF6_STR)
{
unsigned int i;
- struct ospf6_lsa_handler *handler = NULL;
OSPF6_DEBUG_ABR_OFF();
OSPF6_DEBUG_ASBR_OFF();
@@ -1264,13 +1256,7 @@ DEFUN (no_debug_ospf6,
OSPF6_DEBUG_FLOODING_OFF();
OSPF6_DEBUG_INTERFACE_OFF();
- for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
- handler = vector_slot(ospf6_lsa_handler_vector, i);
-
- if (handler != NULL) {
- UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
- }
- }
+ ospf6_lsa_debug_set_all(false);
for (i = 0; i < 6; i++)
OSPF6_DEBUG_MESSAGE_OFF(i,
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 35b567c768..f5d60d80fa 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -704,27 +704,6 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
}
if (old) {
- /* if route does not actually change, return unchanged */
- if (ospf6_route_is_identical(old, route)) {
- if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
- zlog_debug(
- "%s %p: route add %p: needless update of %p old cost %u",
- ospf6_route_table_name(table),
- (void *)table, (void *)route,
- (void *)old, old->path.cost);
- else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
- zlog_debug("%s: route add: needless update",
- ospf6_route_table_name(table));
-
- ospf6_route_delete(route);
- SET_FLAG(old->flag, OSPF6_ROUTE_ADD);
- ospf6_route_table_assert(table);
-
- /* to free the lookup lock */
- route_unlock_node(node);
- return old;
- }
-
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
zlog_debug(
"%s %p: route add %p cost %u paths %u nh %u: update of %p cost %u paths %u nh %u",
@@ -1631,12 +1610,8 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
/* Give summary of this route table */
if (summary) {
ospf6_route_show_table_summary(vty, table, json, use_json);
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -1650,12 +1625,8 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
ospf6_route_show_table_prefix(vty, &prefix, table, json,
use_json);
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -1668,12 +1639,8 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
else
ospf6_route_show_table(vty, detail, table, json, use_json);
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index fd8b6a9c1d..633b8d77cd 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -291,20 +291,13 @@ extern const char *const ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX];
#define OSPF6_ROUTE_PREFIX_STR "Display the route\n"
#define OSPF6_ROUTE_MATCH_STR "Display the route matches the prefix\n"
-#define ospf6_route_is_prefix(p, r) \
- (memcmp(p, &(r)->prefix, sizeof(struct prefix)) == 0)
+#define ospf6_route_is_prefix(p, r) (prefix_same(p, &(r)->prefix))
#define ospf6_route_is_same(ra, rb) (prefix_same(&(ra)->prefix, &(rb)->prefix))
#define ospf6_route_is_same_origin(ra, rb) \
((ra)->path.area_id == (rb)->path.area_id \
- && memcmp(&(ra)->path.origin, &(rb)->path.origin, \
- sizeof(struct ospf6_ls_origin)) \
- == 0)
-#define ospf6_route_is_identical(ra, rb) \
- ((ra)->type == (rb)->type \
- && memcmp(&(ra)->prefix, &(rb)->prefix, sizeof(struct prefix)) == 0 \
- && memcmp(&(ra)->path, &(rb)->path, sizeof(struct ospf6_path)) == 0 \
- && listcount(ra->paths) == listcount(rb->paths) \
- && ospf6_route_cmp_nexthops(ra, rb) == 0)
+ && (ra)->path.origin.type == (rb)->path.origin.type \
+ && (ra)->path.origin.id == (rb)->path.origin.id \
+ && (ra)->path.origin.adv_router == (rb)->path.origin.adv_router)
#define ospf6_route_is_best(r) (CHECK_FLAG ((r)->flag, OSPF6_ROUTE_BEST))
diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c
index fb8c5d6950..1070474d0f 100644
--- a/ospf6d/ospf6_snmp.c
+++ b/ospf6d/ospf6_snmp.c
@@ -971,8 +971,7 @@ static uint8_t *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length,
for (ALL_LIST_ELEMENTS_RO(ifslist, node, iif)) {
if (!iif->ifindex)
continue;
- oi = ospf6_interface_lookup_by_ifindex(
- iif->ifindex, iif->vrf_id);
+ oi = iif->info;
if (!oi)
continue;
if (iif->ifindex < ifindex)
@@ -1106,8 +1105,7 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length,
for (ALL_LIST_ELEMENTS_RO(ifslist, i, iif)) {
if (!iif->ifindex)
continue;
- oi = ospf6_interface_lookup_by_ifindex(iif->ifindex,
- iif->vrf_id);
+ oi = iif->info;
if (!oi)
continue;
if (iif->ifindex > ifindex
@@ -1272,8 +1270,7 @@ static uint8_t *ospfv3NbrEntry(struct variable *v, oid *name, size_t *length,
for (ALL_LIST_ELEMENTS_RO(ifslist, i, iif)) {
if (!iif->ifindex)
continue;
- oi = ospf6_interface_lookup_by_ifindex(iif->ifindex,
- iif->vrf_id);
+ oi = iif->info;
if (!oi)
continue;
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) {
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 7e9ed4160d..6bff52fc56 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -423,7 +423,6 @@ static struct ospf6 *ospf6_create(const char *name)
* 1::1, this happened because of LS ID 0.
*/
o->external_id = OSPF6_EXT_INIT_LS_ID;
- o->external_id_table = route_table_init();
o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
@@ -515,7 +514,6 @@ void ospf6_delete(struct ospf6 *o)
ospf6_route_table_delete(o->brouter_table);
ospf6_route_table_delete(o->external_table);
- route_table_finish(o->external_id_table);
ospf6_distance_reset(o);
route_table_finish(o->distance_table);
@@ -562,6 +560,8 @@ static void ospf6_disable(struct ospf6 *o)
THREAD_OFF(o->t_ospf6_receive);
THREAD_OFF(o->t_external_aggr);
THREAD_OFF(o->gr_info.t_grace_period);
+ THREAD_OFF(o->t_write);
+ THREAD_OFF(o->t_abr_task);
}
}
@@ -583,8 +583,6 @@ static int ospf6_maxage_remover(struct thread *thread)
struct listnode *i, *j, *k;
int reschedule = 0;
- o->maxage_remover = (struct thread *)NULL;
-
for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) {
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
@@ -1482,9 +1480,8 @@ DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
if (uj) {
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
- json_object_string_add(json_vrf, "routerId",
- inet_ntop(AF_INET, &router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_vrf, "routerId", "%pI4",
+ &router_id);
json_object_object_add(json_vrfs, name, json_vrf);
} else {
@@ -1499,10 +1496,7 @@ DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
json_object_object_add(json, "vrfs", json_vrfs);
json_object_int_add(json, "totalVrfs", count);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (count)
vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
@@ -2094,9 +2088,7 @@ DEFPY (show_ipv6_ospf6_external_aggregator,
}
if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
return CMD_SUCCESS;
@@ -2104,9 +2096,8 @@ DEFPY (show_ipv6_ospf6_external_aggregator,
static void ospf6_stub_router_config_write(struct vty *vty, struct ospf6 *ospf6)
{
- if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) {
+ if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER))
vty_out(vty, " stub-router administrative\n");
- }
return;
}
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 55cab72307..4cc0923e93 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -136,7 +136,6 @@ struct ospf6 {
struct ospf6_route_table *brouter_table;
struct ospf6_route_table *external_table;
- struct route_table *external_id_table;
#define OSPF6_EXT_INIT_LS_ID 1
uint32_t external_id;
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 5e6dcde991..d9f730586b 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -292,10 +292,7 @@ static void ospf6_lsdb_show_wrapper(struct vty *vty,
json_object_array_add(json_array, json_obj);
json_object_object_add(json, "asScopedLinkStateDb", json_array);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else
vty_out(vty, "\n");
}
@@ -386,12 +383,9 @@ static void ospf6_lsdb_type_show_wrapper(struct vty *vty,
assert(0);
break;
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "\n");
}
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index 982fad63ec..000c62e305 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -420,7 +420,7 @@ static void ospf_aggr_handle_external_info(void *data)
{
struct external_info *ei = (struct external_info *)data;
struct ospf_external_aggr_rt *aggr = NULL;
- struct ospf *ospf = NULL;
+ struct ospf *ospf = ei->ospf;
struct ospf_lsa *lsa = NULL;
ei->aggr_route = NULL;
@@ -431,8 +431,6 @@ static void ospf_aggr_handle_external_info(void *data)
zlog_debug("%s: Handle extrenal route(%pI4/%d)", __func__,
&ei->p.prefix, ei->p.prefixlen);
- ospf = ospf_lookup_instance(ei->instance);
-
assert(ospf);
if (!ospf_redistribute_check(ospf, ei, NULL))
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index aaacebca14..e9fb891d7e 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -280,6 +280,19 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
return 0;
}
+ /* Type-5 shouldn't be calculated if it is originated from NSSA ASBR.
+ * As per RFC 3101, expectation is to receive type-7 lsas from
+ * NSSA ASBR. Ignore calculation, if the current LSA is type-5 and
+ * originated ASBR's area is NSSA.
+ */
+ if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA)
+ && (asbr_route->u.std.external_routing != OSPF_AREA_DEFAULT)) {
+ if (IS_DEBUG_OSPF(lsa, LSA))
+ zlog_debug(
+ "Route[External]: Ignore, If type-5 LSA from NSSA area.");
+ return 0;
+ }
+
/* Else, this LSA describes an AS external path to destination
N. Examine the forwarding address specified in the AS-
external-LSA. This indicates the IP address to which
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index fab5b7d3cc..2f7556f7ff 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -1645,11 +1645,15 @@ DEFUN (no_debug_ospf,
DEBUG_OFF(nsm, NSM_EVENTS);
DEBUG_OFF(nsm, NSM_STATUS);
DEBUG_OFF(nsm, NSM_TIMERS);
+ DEBUG_OFF(event, EVENT);
DEBUG_OFF(zebra, ZEBRA);
DEBUG_OFF(zebra, ZEBRA_INTERFACE);
DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
DEBUG_OFF(defaultinfo, DEFAULTINFO);
DEBUG_OFF(ldp_sync, LDP_SYNC);
+ DEBUG_OFF(te, TE);
+ DEBUG_OFF(sr, SR);
+ DEBUG_OFF(ti_lfa, TI_LFA);
/* BFD debugging is two parts: OSPF and library. */
DEBUG_OFF(bfd, BFD_LIB);
@@ -1682,6 +1686,9 @@ DEFUN (no_debug_ospf,
TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
+ TERM_DEBUG_OFF(te, TE);
+ TERM_DEBUG_OFF(sr, SR);
+ TERM_DEBUG_OFF(ti_lfa, TI_LFA);
TERM_DEBUG_OFF(bfd, BFD_LIB);
return CMD_SUCCESS;
@@ -1792,6 +1799,18 @@ static int show_debugging_ospf_common(struct vty *vty)
if (IS_DEBUG_OSPF(gr, GR) == OSPF_DEBUG_GR)
vty_out(vty, " OSPF Graceful Restart debugging is on\n");
+ /* Show debug status for TE */
+ if (IS_DEBUG_OSPF(te, TE) == OSPF_DEBUG_TE)
+ vty_out(vty, " OSPF TE debugging is on\n");
+
+ /* Show debug status for SR */
+ if (IS_DEBUG_OSPF(sr, SR) == OSPF_DEBUG_SR)
+ vty_out(vty, " OSPF SR debugging is on\n");
+
+ /* Show debug status for TI-LFA */
+ if (IS_DEBUG_OSPF(ti_lfa, TI_LFA) == OSPF_DEBUG_TI_LFA)
+ vty_out(vty, " OSPF TI-LFA debugging is on\n");
+
if (IS_DEBUG_OSPF(bfd, BFD_LIB) == OSPF_DEBUG_BFD_LIB)
vty_out(vty,
" OSPF BFD integration library debugging is on\n");
@@ -1966,7 +1985,7 @@ static int config_write_debug(struct vty *vty)
}
/* debug ospf sr ti-lfa */
- if (IS_CONF_DEBUG_OSPF(sr, TI_LFA) == OSPF_DEBUG_TI_LFA) {
+ if (IS_CONF_DEBUG_OSPF(ti_lfa, TI_LFA) == OSPF_DEBUG_TI_LFA) {
vty_out(vty, "debug ospf%s ti-lfa\n", str);
write = 1;
}
diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c
index ea1506ea27..0e5a7e29c0 100644
--- a/ospfd/ospf_ext.c
+++ b/ospfd/ospf_ext.c
@@ -256,10 +256,10 @@ static uint32_t get_ext_link_instance_value(void)
/* Lookup Extended Prefix/Links by ifp from OspfEXT struct iflist */
static struct ext_itf *lookup_ext_by_ifp(struct interface *ifp)
{
- struct listnode *node, *nnode;
+ struct listnode *node;
struct ext_itf *exti;
- for (ALL_LIST_ELEMENTS(OspfEXT.iflist, node, nnode, exti))
+ for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
if (exti->ifp == ifp)
return exti;
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 42d31414f5..299e753ccf 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -360,9 +360,8 @@ void ospf_if_free(struct ospf_interface *oi)
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf interface %s vrf %s id %u deleted",
- __func__, oi->ifp->name,
- ospf_vrf_id_to_name(oi->ifp->vrf_id),
- oi->ifp->vrf_id);
+ __func__, oi->ifp->name, oi->ifp->vrf->name,
+ oi->ifp->vrf->vrf_id);
ospf_delete_from_if(oi->ifp, oi);
@@ -477,7 +476,7 @@ struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf,
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
continue;
- if (if_is_loopback_or_vrf(oi->ifp))
+ if (if_is_loopback(oi->ifp))
continue;
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
@@ -719,7 +718,7 @@ static int ospf_if_delete_hook(struct interface *ifp)
int ospf_if_is_enable(struct ospf_interface *oi)
{
- if (!(if_is_loopback_or_vrf(oi->ifp)))
+ if (!(if_is_loopback(oi->ifp)))
if (if_is_up(oi->ifp))
return 1;
@@ -1294,7 +1293,7 @@ uint8_t ospf_default_iftype(struct interface *ifp)
{
if (if_is_pointopoint(ifp))
return OSPF_IFTYPE_POINTOPOINT;
- else if (if_is_loopback_or_vrf(ifp))
+ else if (if_is_loopback(ifp))
return OSPF_IFTYPE_LOOPBACK;
else
return OSPF_IFTYPE_BROADCAST;
@@ -1331,10 +1330,9 @@ static int ospf_ifp_create(struct interface *ifp)
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug(
"Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d speed %u",
- ifp->name, ospf_vrf_id_to_name(ifp->vrf_id),
- ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu,
- ifp->speed);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu, ifp->speed);
assert(ifp->info);
@@ -1347,7 +1345,7 @@ static int ospf_ifp_create(struct interface *ifp)
IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
}
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
if (!ospf)
return 0;
@@ -1431,13 +1429,13 @@ static int ospf_ifp_destroy(struct interface *ifp)
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug(
"Zebra: interface delete %s vrf %s[%u] index %d flags %llx metric %d mtu %d",
- ifp->name, ospf_vrf_id_to_name(ifp->vrf_id),
- ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu);
hook_call(ospf_if_delete, ifp);
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
if (ospf) {
if (ospf_if_count_area_params(ifp) > 0)
ospf_interface_area_unset(ospf, ifp);
diff --git a/ospfd/ospf_ldp_sync.c b/ospfd/ospf_ldp_sync.c
index dbd45635b2..247ceb0a08 100644
--- a/ospfd/ospf_ldp_sync.c
+++ b/ospfd/ospf_ldp_sync.c
@@ -129,8 +129,9 @@ void ospf_ldp_sync_if_init(struct ospf_interface *oi)
* if LDP-IGP Sync is configured globally set state
* if ptop interface inform LDP LDP-SYNC is enabled
*/
- if (if_is_loopback(ifp) || (ifp->vrf_id != VRF_DEFAULT) ||
- !(CHECK_FLAG(oi->ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)))
+ if (if_is_loopback(ifp) || (ifp->vrf->vrf_id != VRF_DEFAULT)
+ || !(CHECK_FLAG(oi->ospf->ldp_sync_cmd.flags,
+ LDP_SYNC_FLAG_ENABLE)))
return;
ols_debug("ldp_sync: init if %s",ifp->name);
@@ -856,7 +857,7 @@ DEFPY (mpls_ldp_sync,
return CMD_ERR_NOTHING_TODO;
}
- if (ifp->vrf_id != VRF_DEFAULT) {
+ if (ifp->vrf->vrf_id != VRF_DEFAULT) {
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
return CMD_ERR_NOTHING_TODO;
}
@@ -897,7 +898,7 @@ DEFPY (no_mpls_ldp_sync,
return CMD_ERR_NOTHING_TODO;
}
- if (ifp->vrf_id != VRF_DEFAULT) {
+ if (ifp->vrf->vrf_id != VRF_DEFAULT) {
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
return CMD_ERR_NOTHING_TODO;
}
@@ -940,7 +941,7 @@ DEFPY (mpls_ldp_sync_holddown,
return CMD_ERR_NOTHING_TODO;
}
- if (ifp->vrf_id != VRF_DEFAULT) {
+ if (ifp->vrf->vrf_id != VRF_DEFAULT) {
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
return CMD_ERR_NOTHING_TODO;
}
@@ -978,7 +979,7 @@ DEFPY (no_mpls_ldp_sync_holddown,
return CMD_ERR_NOTHING_TODO;
}
- if (ifp->vrf_id != VRF_DEFAULT) {
+ if (ifp->vrf->vrf_id != VRF_DEFAULT) {
vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
return CMD_ERR_NOTHING_TODO;
}
@@ -1030,32 +1031,25 @@ DEFPY (show_ip_ospf_mpls_ldp_interface,
/* Display default ospf (instance 0) info */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
}
if (!CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "LDP-sync is disabled\n");
return CMD_SUCCESS;
}
ret = show_ip_ospf_mpls_ldp_interface_common(vty, ospf, intf_name,
json, uj);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index ede0ad39e6..e17e531098 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -3012,7 +3012,7 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
}
}
- if (ospf->vrf_id == VRF_DEFAULT && ospf->vrf_id != ifp->vrf_id) {
+ if (ospf->vrf_id == VRF_DEFAULT && ospf->vrf_id != ifp->vrf->vrf_id) {
/*
* We may have a situation where l3mdev_accept == 1
* let's just kindly drop the packet and move on.
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index 9a9e64cc23..181cc37f4f 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -279,17 +279,19 @@ static int sr_local_block_init(uint32_t lower_bound, uint32_t upper_bound)
*/
size = upper_bound - lower_bound + 1;
if (ospf_zebra_request_label_range(lower_bound, size)) {
- srlb->reserved = false;
+ zlog_err("SR: Error reserving SRLB [%u/%u] %u labels",
+ lower_bound, upper_bound, size);
return -1;
}
- osr_debug("SR (%s): Got new SRLB [%u/%u]", __func__, lower_bound,
- upper_bound);
+ osr_debug("SR: Got new SRLB [%u/%u], %u labels", lower_bound,
+ upper_bound, size);
/* Initialize the SRLB */
srlb->start = lower_bound;
srlb->end = upper_bound;
srlb->current = 0;
+
/* Compute the needed Used Mark number and allocate them */
srlb->max_block = size / SRLB_BLOCK_SIZE;
if ((size % SRLB_BLOCK_SIZE) != 0)
@@ -301,6 +303,31 @@ static int sr_local_block_init(uint32_t lower_bound, uint32_t upper_bound)
return 0;
}
+static int sr_global_block_init(uint32_t start, uint32_t size)
+{
+ struct sr_global_block *srgb = &OspfSR.srgb;
+
+ /* Check if already configured */
+ if (srgb->reserved)
+ return 0;
+
+ /* request chunk */
+ uint32_t end = start + size - 1;
+ if (ospf_zebra_request_label_range(start, size) < 0) {
+ zlog_err("SR: Error reserving SRGB [%u/%u], %u labels", start,
+ end, size);
+ return -1;
+ }
+
+ osr_debug("SR: Got new SRGB [%u/%u], %u labels", start, end, size);
+
+ /* success */
+ srgb->start = start;
+ srgb->size = size;
+ srgb->reserved = true;
+ return 0;
+}
+
/**
* Remove Segment Routing Local Block.
*
@@ -322,10 +349,31 @@ static void sr_local_block_delete(void)
/* Then reset SRLB structure */
if (srlb->used_mark != NULL)
XFREE(MTYPE_OSPF_SR_PARAMS, srlb->used_mark);
+
srlb->reserved = false;
}
/**
+ * Remove Segment Routing Global block
+ */
+static void sr_global_block_delete(void)
+{
+ struct sr_global_block *srgb = &OspfSR.srgb;
+
+ if (!srgb->reserved)
+ return;
+
+ osr_debug("SR (%s): Remove SRGB [%u/%u]", __func__, srgb->start,
+ srgb->start + srgb->size - 1);
+
+ ospf_zebra_release_label_range(srgb->start,
+ srgb->start + srgb->size - 1);
+
+ srgb->reserved = false;
+}
+
+
+/**
* Request a label from the Segment Routing Local Block.
*
* @return First available label on success or MPLS_INVALID_LABEL if the
@@ -337,9 +385,10 @@ mpls_label_t ospf_sr_local_block_request_label(void)
mpls_label_t label;
uint32_t index;
uint32_t pos;
+ uint32_t size = srlb->end - srlb->start + 1;
/* Check if we ran out of available labels */
- if (srlb->current >= srlb->end)
+ if (srlb->current >= size)
return MPLS_INVALID_LABEL;
/* Get first available label and mark it used */
@@ -351,7 +400,7 @@ mpls_label_t ospf_sr_local_block_request_label(void)
/* Jump to the next free position */
srlb->current++;
pos = srlb->current % SRLB_BLOCK_SIZE;
- while (srlb->current < srlb->end) {
+ while (srlb->current < size) {
if (pos == 0)
index++;
if (!((1ULL << pos) & srlb->used_mark[index]))
@@ -362,6 +411,10 @@ mpls_label_t ospf_sr_local_block_request_label(void)
}
}
+ if (srlb->current == size)
+ zlog_warn(
+ "SR: Warning, SRLB is depleted and next label request will fail");
+
return label;
}
@@ -469,16 +522,11 @@ static int ospf_sr_start(struct ospf *ospf)
* If the allocation fails, return an error to disable SR until a new
* SRLB and/or SRGB are successfully allocated.
*/
- sr_local_block_init(OspfSR.srlb.start, OspfSR.srlb.end);
- if (!OspfSR.srgb.reserved) {
- if (ospf_zebra_request_label_range(OspfSR.srgb.start,
- OspfSR.srgb.size)
- < 0) {
- OspfSR.srgb.reserved = false;
- return -1;
- } else
- OspfSR.srgb.reserved = true;
- }
+ if (sr_local_block_init(OspfSR.srlb.start, OspfSR.srlb.end) < 0)
+ return -1;
+
+ if (sr_global_block_init(OspfSR.srgb.start, OspfSR.srgb.size) < 0)
+ return -1;
/* SR is UP and ready to flood LSA */
OspfSR.status = SR_UP;
@@ -534,13 +582,10 @@ static void ospf_sr_stop(void)
/* Disable any re-attempt to connect to Label Manager */
THREAD_OFF(OspfSR.t_start_lm);
- /* Release SRGB & SRLB if active. */
- if (OspfSR.srgb.reserved) {
- ospf_zebra_release_label_range(
- OspfSR.srgb.start,
- OspfSR.srgb.start + OspfSR.srgb.size - 1);
- OspfSR.srgb.reserved = false;
- }
+ /* Release SRGB if active */
+ sr_global_block_delete();
+
+ /* Release SRLB if active */
sr_local_block_delete();
/*
@@ -581,7 +626,7 @@ int ospf_sr_init(void)
OspfSR.srgb.reserved = false;
OspfSR.srlb.start = DEFAULT_SRLB_LABEL;
- OspfSR.srlb.end = DEFAULT_SRLB_LABEL + DEFAULT_SRLB_SIZE - 1;
+ OspfSR.srlb.end = DEFAULT_SRLB_END;
OspfSR.srlb.reserved = false;
OspfSR.msd = 0;
@@ -1200,7 +1245,9 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp)
/* Search for existing Segment Prefix */
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, pref))
- if (pref->instance == srp->instance) {
+ if (pref->instance == srp->instance
+ && prefix_same((struct prefix *)&srp->prefv4,
+ &pref->prefv4)) {
found = true;
break;
}
@@ -1231,9 +1278,6 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp)
/* Replace Segment Prefix */
listnode_delete(srn->ext_prefix, pref);
XFREE(MTYPE_OSPF_SR_PARAMS, pref);
- srp->srn = srn;
- IPV4_ADDR_COPY(&srp->adv_router,
- &srn->adv_router);
listnode_add(srn->ext_prefix, srp);
ospf_zebra_update_prefix_sid(srp);
} else {
@@ -2099,6 +2143,20 @@ static int ospf_sr_enabled(struct vty *vty)
return 0;
}
+/* tell if two ranges [r1_lower, r1_upper] and [r2_lower,r2_upper] overlap */
+static bool ranges_overlap(uint32_t r1_lower, uint32_t r1_upper,
+ uint32_t r2_lower, uint32_t r2_upper)
+{
+ return !((r1_upper < r2_lower) || (r1_lower > r2_upper));
+}
+
+
+/* tell if a range is valid */
+static bool sr_range_is_valid(uint32_t lower, uint32_t upper, uint32_t min_size)
+{
+ return (upper >= lower + min_size);
+}
+
/**
* Update SRGB and/or SRLB using new CLI values.
*
@@ -2136,12 +2194,8 @@ static int update_sr_blocks(uint32_t gb_lower, uint32_t gb_upper,
/* Release old SRGB if it has changed and is active. */
if (gb_changed) {
- if (OspfSR.srgb.reserved) {
- ospf_zebra_release_label_range(
- OspfSR.srgb.start,
- OspfSR.srgb.start + OspfSR.srgb.size - 1);
- OspfSR.srgb.reserved = false;
- }
+
+ sr_global_block_delete();
/* Set new SRGB values - but do not reserve yet (we need to
* release the SRLB too) */
@@ -2155,8 +2209,8 @@ static int update_sr_blocks(uint32_t gb_lower, uint32_t gb_upper,
/* Release old SRLB if it has changed and reserve new block as needed.
*/
if (lb_changed) {
- if (OspfSR.srlb.reserved)
- sr_local_block_delete();
+
+ sr_local_block_delete();
/* Set new SRLB values */
if (sr_local_block_init(lb_lower, lb_upper) < 0) {
@@ -2175,18 +2229,11 @@ static int update_sr_blocks(uint32_t gb_lower, uint32_t gb_upper,
* allocated.
*/
if (gb_changed) {
- if (ospf_zebra_request_label_range(OspfSR.srgb.start,
- OspfSR.srgb.size)
+ if (sr_global_block_init(OspfSR.srgb.start, OspfSR.srgb.size)
< 0) {
- OspfSR.srgb.reserved = false;
ospf_sr_stop();
return -1;
- } else
- OspfSR.srgb.reserved = true;
-
- osr_debug("SR(%s): Got new SRGB [%u/%u]", __func__,
- OspfSR.srgb.start,
- OspfSR.srgb.start + OspfSR.srgb.size - 1);
+ }
}
/* Update Self SR-Node */
@@ -2227,16 +2274,29 @@ DEFUN(sr_global_label_range, sr_global_label_range_cmd,
/* Get lower and upper bound for mandatory global-block */
gb_lower = strtoul(argv[idx_gb_low]->arg, NULL, 10);
gb_upper = strtoul(argv[idx_gb_up]->arg, NULL, 10);
+
/* SRLB values are taken from vtysh if there, else use the known ones */
lb_upper = argc > idx_lb_up ? strtoul(argv[idx_lb_up]->arg, NULL, 10)
: OspfSR.srlb.end;
lb_lower = argc > idx_lb_low ? strtoul(argv[idx_lb_low]->arg, NULL, 10)
: OspfSR.srlb.start;
+ /* check correctness of input SRGB */
+ if (!sr_range_is_valid(gb_lower, gb_upper, MIN_SRGB_SIZE)) {
+ vty_out(vty, "Invalid SRGB range\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* check correctness of SRLB */
+ if (!sr_range_is_valid(lb_lower, lb_upper, MIN_SRLB_SIZE)) {
+ vty_out(vty, "Invalid SRLB range\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
/* Validate SRGB against SRLB */
- if (!((gb_upper < lb_lower) || (gb_lower > lb_upper))) {
+ if (ranges_overlap(gb_lower, gb_upper, lb_lower, lb_upper)) {
vty_out(vty,
- "New SR Global Block (%u/%u) conflict with Local Block (%u/%u)\n",
+ "New SR Global Block (%u/%u) conflicts with Local Block (%u/%u)\n",
gb_lower, gb_upper, lb_lower, lb_upper);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -2287,6 +2347,12 @@ DEFUN_HIDDEN(sr_local_label_range, sr_local_label_range_cmd,
lower = strtoul(argv[idx_low]->arg, NULL, 10);
upper = strtoul(argv[idx_up]->arg, NULL, 10);
+ /* check correctness of SRLB */
+ if (!sr_range_is_valid(lower, upper, MIN_SRLB_SIZE)) {
+ vty_out(vty, "Invalid SRLB range\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
/* Check if values have changed */
if ((OspfSR.srlb.start == lower)
&& (OspfSR.srlb.end == upper))
@@ -2294,9 +2360,10 @@ DEFUN_HIDDEN(sr_local_label_range, sr_local_label_range_cmd,
/* Validate SRLB against SRGB */
srgb_upper = OspfSR.srgb.start + OspfSR.srgb.size - 1;
- if (!((upper < OspfSR.srgb.start) || (lower > srgb_upper))) {
+
+ if (ranges_overlap(OspfSR.srgb.start, srgb_upper, lower, upper)) {
vty_out(vty,
- "New SR Local Block (%u/%u) conflict with Global Block (%u/%u)\n",
+ "New SR Local Block (%u/%u) conflicts with Global Block (%u/%u)\n",
lower, upper, OspfSR.srgb.start, srgb_upper);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -2319,10 +2386,10 @@ DEFUN_HIDDEN(no_sr_local_label_range, no_sr_local_label_range_cmd,
/* Validate SRLB against SRGB */
srgb_end = OspfSR.srgb.start + OspfSR.srgb.size - 1;
- if (!((DEFAULT_SRLB_END < OspfSR.srgb.start)
- || (DEFAULT_SRLB_LABEL > srgb_end))) {
+ if (ranges_overlap(OspfSR.srgb.start, srgb_end, DEFAULT_SRLB_LABEL,
+ DEFAULT_SRLB_END)) {
vty_out(vty,
- "New SR Local Block (%u/%u) conflict with Global Block (%u/%u)\n",
+ "New SR Local Block (%u/%u) conflicts with Global Block (%u/%u)\n",
DEFAULT_SRLB_LABEL, DEFAULT_SRLB_END, OspfSR.srgb.start,
srgb_end);
return CMD_WARNING_CONFIG_FAILED;
@@ -2412,11 +2479,15 @@ DEFUN (sr_prefix_sid,
"Upstream neighbor must replace prefix-sid with explicit null label\n")
{
int idx = 0;
- struct prefix p;
+ struct prefix p, pexist;
uint32_t index;
struct listnode *node;
- struct sr_prefix *srp, *new = NULL;
+ struct sr_prefix *srp, *exist = NULL;
struct interface *ifp;
+ bool no_php_flag = false;
+ bool exp_null = false;
+ bool index_in_use = false;
+ uint8_t desired_flags = 0;
if (!ospf_sr_enabled(vty))
return CMD_WARNING_CONFIG_FAILED;
@@ -2437,53 +2508,67 @@ DEFUN (sr_prefix_sid,
return CMD_WARNING_CONFIG_FAILED;
}
+ /* Get options */
+ no_php_flag = argv_find(argv, argc, "no-php-flag", &idx);
+ exp_null = argv_find(argv, argc, "explicit-null", &idx);
+
+ desired_flags |= no_php_flag ? EXT_SUBTLV_PREFIX_SID_NPFLG : 0;
+ desired_flags |= exp_null ? EXT_SUBTLV_PREFIX_SID_NPFLG : 0;
+ desired_flags |= exp_null ? EXT_SUBTLV_PREFIX_SID_EFLG : 0;
+
/* Search for an existing Prefix-SID */
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
+ if (prefix_same((struct prefix *)&srp->prefv4, &p))
+ exist = srp;
if (srp->sid == index) {
- if (prefix_same((struct prefix *)&srp->prefv4, &p)) {
- new = srp;
- break;
- } else {
- vty_out(vty, "Index %u is already used\n",
- index);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ index_in_use = true;
+ pexist = p;
}
}
- /* Create new Extended Prefix to SRDB if not found */
- if (new == NULL) {
- new = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
- IPV4_ADDR_COPY(&new->prefv4.prefix, &p.u.prefix4);
- new->prefv4.prefixlen = p.prefixlen;
- new->prefv4.family = p.family;
- new->sid = index;
- new->type = LOCAL_SID;
+ /* done if prefix segment already there with same index and flags */
+ if (exist && exist->sid == index && exist->flags == desired_flags)
+ return CMD_SUCCESS;
+
+ /* deny if index is already in use by a distinct prefix */
+ if (!exist && index_in_use) {
+ vty_out(vty, "Index %u is already used by %pFX\n", index,
+ &pexist);
+ return CMD_WARNING_CONFIG_FAILED;
}
/* First, remove old NHLFE if installed */
- if (srp == new && CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
- && !CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
- ospf_zebra_delete_prefix_sid(srp);
- /* Then, reset Flag & labels to handle flag update */
- new->flags = 0;
- new->label_in = 0;
- new->nhlfe.label_out = 0;
+ if (exist && CHECK_FLAG(exist->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
+ && !CHECK_FLAG(exist->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
+ ospf_zebra_delete_prefix_sid(exist);
- /* Set NO PHP flag if present and compute NHLFE */
- if (argv_find(argv, argc, "no-php-flag", &idx)) {
- SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
- new->label_in = index2label(new->sid, OspfSR.self->srgb);
- new->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
+ /* Create new Extended Prefix to SRDB if not found */
+ if (exist == NULL) {
+ srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
+ IPV4_ADDR_COPY(&srp->prefv4.prefix, &p.u.prefix4);
+ srp->prefv4.prefixlen = p.prefixlen;
+ srp->prefv4.family = p.family;
+ srp->sid = index;
+ srp->type = LOCAL_SID;
+ } else {
+ /* we work on the existing SR prefix */
+ srp = exist;
}
- /* Set EXPLICIT NULL flag is present */
- if (argv_find(argv, argc, "explicit-null", &idx)) {
- SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
- SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG);
+
+ /* Reset labels to handle flag update */
+ srp->label_in = 0;
+ srp->nhlfe.label_out = 0;
+ srp->sid = index;
+ srp->flags = desired_flags;
+
+ /* If NO PHP flag is present, compute NHLFE and set label */
+ if (no_php_flag) {
+ srp->label_in = index2label(srp->sid, OspfSR.self->srgb);
+ srp->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
}
osr_debug("SR (%s): Add new index %u to Prefix %pFX", __func__, index,
- (struct prefix *)&new->prefv4);
+ (struct prefix *)&srp->prefv4);
/* Get Interface and check if it is a Loopback */
ifp = if_lookup_prefix(&p, VRF_DEFAULT);
@@ -2494,7 +2579,8 @@ DEFUN (sr_prefix_sid,
* ready. In this case, store the prefix SID for latter
* update of this Extended Prefix
*/
- listnode_add(OspfSR.self->ext_prefix, new);
+ if (exist == NULL)
+ listnode_add(OspfSR.self->ext_prefix, srp);
zlog_info(
"Interface for prefix %pFX not found. Deferred LSA flooding",
&p);
@@ -2503,27 +2589,26 @@ DEFUN (sr_prefix_sid,
if (!if_is_loopback(ifp)) {
vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
- XFREE(MTYPE_OSPF_SR_PARAMS, new);
+ XFREE(MTYPE_OSPF_SR_PARAMS, srp);
return CMD_WARNING_CONFIG_FAILED;
}
- new->nhlfe.ifindex = ifp->ifindex;
+ srp->nhlfe.ifindex = ifp->ifindex;
- /* Add this new SR Prefix if not already found */
- if (srp != new)
- listnode_add(OspfSR.self->ext_prefix, new);
+ /* Add SR Prefix if new */
+ if (!exist)
+ listnode_add(OspfSR.self->ext_prefix, srp);
/* Update Prefix SID if SR is UP */
if (OspfSR.status == SR_UP) {
- if (CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
- && !CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
- ospf_zebra_update_prefix_sid(new);
+ if (no_php_flag && !exp_null)
+ ospf_zebra_update_prefix_sid(srp);
} else
return CMD_SUCCESS;
/* Finally, update Extended Prefix LSA id SR is UP */
- new->instance = ospf_ext_schedule_prefix_index(
- ifp, new->sid, &new->prefv4, new->flags);
- if (new->instance == 0) {
+ srp->instance = ospf_ext_schedule_prefix_index(
+ ifp, srp->sid, &srp->prefv4, srp->flags);
+ if (srp->instance == 0) {
vty_out(vty, "Unable to set index %u for prefix %pFX\n",
index, &p);
return CMD_WARNING;
@@ -2674,10 +2759,8 @@ static void show_sr_prefix(struct sbuf *sbuf, struct json_object *json,
srp->nhlfe.label_out);
json_object_string_add(json_obj, "interface",
itf ? itf->name : "-");
- json_object_string_add(
- json_obj, "nexthop",
- inet_ntop(AF_INET, &srp->nhlfe.nexthop,
- buf, sizeof(buf)));
+ json_object_string_addf(json_obj, "nexthop", "%pI4",
+ &srp->nhlfe.nexthop);
json_object_array_add(json_route, json_obj);
} else {
sbuf_push(sbuf, 0, "%20s %9s %15s\n",
@@ -2712,10 +2795,8 @@ static void show_sr_prefix(struct sbuf *sbuf, struct json_object *json,
path->srni.label_out);
json_object_string_add(json_obj, "interface",
itf ? itf->name : "-");
- json_object_string_add(
- json_obj, "nexthop",
- inet_ntop(AF_INET, &path->nexthop,
- buf, sizeof(buf)));
+ json_object_string_addf(json_obj, "nexthop", "%pI4",
+ &path->nexthop);
json_object_array_add(json_route, json_obj);
} else {
sbuf_push(sbuf, indent, "%20s %9s %15s\n",
@@ -2755,9 +2836,8 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
if (json) {
json_node = json_object_new_object();
- json_object_string_add(json_node, "routerID",
- inet_ntop(AF_INET, &srn->adv_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json_node, "routerID", "%pI4",
+ &srn->adv_router);
json_object_int_add(json_node, "srgbSize",
srn->srgb.range_size);
json_object_int_add(json_node, "srgbLabel",
@@ -2846,10 +2926,8 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
srl->nhlfe[0].label_out);
json_object_string_add(json_obj, "interface",
itf ? itf->name : "-");
- json_object_string_add(
- json_obj, "nexthop",
- inet_ntop(AF_INET, &srl->nhlfe[0].nexthop,
- buf, sizeof(buf)));
+ json_object_string_addf(json_obj, "nexthop", "%pI4",
+ &srl->nhlfe[0].nexthop);
json_object_array_add(json_link, json_obj);
/* Backup Link */
json_obj = json_object_new_object();
@@ -2862,10 +2940,8 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
srl->nhlfe[1].label_out);
json_object_string_add(json_obj, "interface",
itf ? itf->name : "-");
- json_object_string_add(
- json_obj, "nexthop",
- inet_ntop(AF_INET, &srl->nhlfe[1].nexthop,
- buf, sizeof(buf)));
+ json_object_string_addf(json_obj, "nexthop", "%pI4",
+ &srl->nhlfe[1].nexthop);
json_object_array_add(json_link, json_obj);
} else {
sbuf_push(&sbuf, 0, "%18s %21s %20s %9s %15s\n",
@@ -2925,7 +3001,6 @@ DEFUN (show_ip_opsf_srdb,
int idx = 0;
struct in_addr rid;
struct sr_node *srn;
- char buf[PREFIX_STRLEN];
bool uj = use_json(argc, argv);
json_object *json = NULL, *json_node_array = NULL;
@@ -2937,10 +3012,8 @@ DEFUN (show_ip_opsf_srdb,
if (uj) {
json = json_object_new_object();
json_node_array = json_object_new_array();
- json_object_string_add(
- json, "srdbID",
- inet_ntop(AF_INET, &OspfSR.self->adv_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "srdbID", "%pI4",
+ &OspfSR.self->adv_router);
json_object_object_add(json, "srNodes", json_node_array);
} else {
vty_out(vty,
@@ -2951,12 +3024,8 @@ DEFUN (show_ip_opsf_srdb,
if (argv_find(argv, argc, "self-originate", &idx)) {
srn = OspfSR.self;
show_sr_node(vty, json_node_array, srn);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2970,12 +3039,8 @@ DEFUN (show_ip_opsf_srdb,
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
(void *)&rid);
show_sr_node(vty, json_node_array, srn);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2984,9 +3049,7 @@ DEFUN (show_ip_opsf_srdb,
hash_iterate(OspfSR.neighbors, (void (*)(struct hash_bucket *,
void *))show_json_srdb,
(void *)json_node_array);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
hash_iterate(OspfSR.neighbors, (void (*)(struct hash_bucket *,
void *))show_vty_srdb,
diff --git a/ospfd/ospf_sr.h b/ospfd/ospf_sr.h
index d706d206fb..b153a220f5 100644
--- a/ospfd/ospf_sr.h
+++ b/ospfd/ospf_sr.h
@@ -38,7 +38,9 @@
#define SET_LABEL(label) ((label << 8) & SET_LABEL_MASK)
#define GET_LABEL(label) ((label >> 8) & GET_LABEL_MASK)
-#define OSPF_SR_DEFAULT_METRIC 1
+/* smallest configurable SRGB / SRLB sizes */
+#define MIN_SRLB_SIZE 16
+#define MIN_SRGB_SIZE 16
/* Segment Routing TLVs as per RFC 8665 */
@@ -221,7 +223,7 @@ struct sr_local_block {
enum sid_type { PREF_SID, LOCAL_SID, ADJ_SID, LAN_ADJ_SID };
/* Status of Segment Routing: Off (Disable), On (Enable), (Up) Started */
-enum sr_status { SR_OFF, SR_ON, SR_UP, SR_DOWN };
+enum sr_status { SR_OFF, SR_ON, SR_UP };
/* Structure aggregating all OSPF Segment Routing information for the node */
struct ospf_sr_db {
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index c5d1079e91..999bc49d91 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -4432,12 +4432,8 @@ DEFUN (show_ip_ospf_mpls_te_db,
ls_show_ted(OspfMplsTE.ted, vty, json, verbose);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 5b9519ea59..6979b34196 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -3043,7 +3043,6 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
struct ospf_area *area;
struct timeval result;
char timebuf[OSPF_TIME_DUMP_SIZE];
- char buf[PREFIX_STRLEN];
json_object *json_vrf = NULL;
json_object *json_areas = NULL;
@@ -3068,9 +3067,8 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
/* Show Router ID. */
if (json) {
- json_object_string_add(json_vrf, "routerId",
- inet_ntop(AF_INET, &ospf->router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_vrf, "routerId", "%pI4",
+ &ospf->router_id);
} else {
vty_out(vty, " OSPF Routing Process, Router ID: %pI4\n",
&ospf->router_id);
@@ -3388,23 +3386,17 @@ DEFUN (show_ip_ospf,
ret = show_ip_ospf_common(vty, ospf, json,
use_vrf);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else if (!ospf_output)
+ if (uj)
+ vty_json(vty, json);
+ else if (!ospf_output)
vty_out(vty, "%% OSPF instance not found\n");
return ret;
}
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
if ((ospf == NULL) || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -3413,12 +3405,9 @@ DEFUN (show_ip_ospf,
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
/* Display default ospf (instance 0) info */
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -3468,11 +3457,8 @@ DEFUN (show_ip_ospf_instance,
ret = show_ip_ospf_common(vty, ospf, json, 0);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -3533,7 +3519,6 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
int is_up;
struct ospf_neighbor *nbr;
struct route_node *rn;
- char buf[PREFIX_STRLEN];
uint32_t bandwidth = ifp->bandwidth ? ifp->bandwidth : ifp->speed;
/* Is interface up? */
@@ -3603,11 +3588,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
/* Show OSPF interface information. */
if (use_json) {
- json_object_string_add(
- json_interface_sub, "ipAddress",
- inet_ntop(AF_INET,
- &oi->address->u.prefix4,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_interface_sub, "ipAddress", "%pI4",
+ &oi->address->u.prefix4);
json_object_int_add(json_interface_sub,
"ipAddressPrefixlen",
oi->address->prefixlen);
@@ -3637,17 +3620,13 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
json_interface_sub,
"ospfIfType", dstr);
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
- json_object_string_add(
- json_interface_sub,
- "vlinkPeer",
- inet_ntop(AF_INET, &dest,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_interface_sub, "vlinkPeer",
+ "%pI4", &dest);
else
- json_object_string_add(
+ json_object_string_addf(
json_interface_sub,
- "localIfUsed",
- inet_ntop(AF_INET, &dest,
- buf, sizeof(buf)));
+ "localIfUsed", "%pI4", &dest);
} else
vty_out(vty, " %s %pI4,", dstr,
&dest);
@@ -3659,10 +3638,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
json_object_boolean_true_add(
json_interface_sub,
"mtuMismatchDetect");
- json_object_string_add(
- json_interface_sub, "routerId",
- inet_ntop(AF_INET, &ospf->router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_interface_sub, "routerId",
+ "%pI4", &ospf->router_id);
json_object_string_add(json_interface_sub,
"networkType",
ospf_network_type_str[oi->type]);
@@ -3706,17 +3683,13 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi));
if (nbr) {
if (use_json) {
- json_object_string_add(
+ json_object_string_addf(
json_interface_sub, "drId",
- inet_ntop(AF_INET,
- &nbr->router_id, buf,
- sizeof(buf)));
- json_object_string_add(
+ "%pI4", &nbr->router_id);
+ json_object_string_addf(
json_interface_sub, "drAddress",
- inet_ntop(
- AF_INET,
- &nbr->address.u.prefix4,
- buf, sizeof(buf)));
+ "%pI4",
+ &nbr->address.u.prefix4);
} else {
vty_out(vty,
" Designated Router (ID) %pI4",
@@ -3735,18 +3708,13 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
" No backup designated router on this network\n");
} else {
if (use_json) {
- json_object_string_add(
+ json_object_string_addf(
json_interface_sub, "bdrId",
- inet_ntop(AF_INET,
- &nbr->router_id,
- buf, sizeof(buf)));
- json_object_string_add(
+ "%pI4", &nbr->router_id);
+ json_object_string_addf(
json_interface_sub,
- "bdrAddress",
- inet_ntop(AF_INET,
- &nbr->address.u
- .prefix4,
- buf, sizeof(buf)));
+ "bdrAddress", "%pI4",
+ &nbr->address.u.prefix4);
} else {
vty_out(vty,
" Backup Designated Router (ID) %pI4,",
@@ -4150,24 +4118,18 @@ DEFUN (show_ip_ospf_interface,
uj);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else if (!ospf)
+ if (uj)
+ vty_json(vty, json);
+ else if (!ospf)
vty_out(vty, "%% OSPF instance not found\n");
return ret;
}
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -4179,12 +4141,9 @@ DEFUN (show_ip_ospf_interface,
/* Display default ospf (instance 0) info */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -4193,11 +4152,8 @@ DEFUN (show_ip_ospf_interface,
use_vrf, json, uj);
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4238,11 +4194,8 @@ DEFUN (show_ip_ospf_instance_interface,
ret = show_ip_ospf_interface_common(vty, ospf, intf_name, 0, json, uj);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4293,12 +4246,8 @@ DEFUN (show_ip_ospf_interface_traffic,
display_once = 1;
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4323,11 +4272,8 @@ DEFUN (show_ip_ospf_interface_traffic,
vty, ospf, intf_name, json, display_once, use_vrf, uj);
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4347,7 +4293,6 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty,
struct route_node *rn;
struct ospf_neighbor *nbr, *prev_nbr = NULL;
char msgbuf[16];
- char buf[PREFIX_STRLEN];
char timebuf[OSPF_TIME_DUMP_SIZE];
json_object *json_neighbor = NULL, *json_neigh_array = NULL;
struct timeval res = {.tv_sec = 0, .tv_usec = 0};
@@ -4447,10 +4392,9 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty,
"deadTimeMsecs",
"inactive");
}
- json_object_string_add(
- json_neighbor, "address",
- inet_ntop(AF_INET, &nbr->src,
- buf, sizeof(buf)));
+ json_object_string_addf(json_neighbor,
+ "address", "%pI4",
+ &nbr->src);
json_object_string_add(json_neighbor,
"ifaceName",
IF_NAME(oi));
@@ -4582,12 +4526,9 @@ DEFUN (show_ip_ospf_neighbor,
vty, ospf, json, uj, use_vrf);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else if (!ospf)
+ if (uj)
+ vty_json(vty, json);
+ else if (!ospf)
vty_out(vty, "OSPF instance not found\n");
return ret;
@@ -4595,12 +4536,9 @@ DEFUN (show_ip_ospf_neighbor,
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -4609,12 +4547,9 @@ DEFUN (show_ip_ospf_neighbor,
/* Display default ospf (instance 0) info */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -4669,11 +4604,8 @@ DEFUN (show_ip_ospf_instance_neighbor,
ret = show_ip_ospf_neighbor_common(vty, ospf, json, uj, 0);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4807,12 +4739,8 @@ DEFUN (show_ip_ospf_neighbor_all,
vty, ospf, json, uj, use_vrf);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4879,11 +4807,8 @@ DEFUN (show_ip_ospf_instance_neighbor_all,
ret = show_ip_ospf_neighbor_all_common(vty, ospf, json, uj, 0);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -4928,11 +4853,9 @@ static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf,
show_ip_ospf_neighbor_sub(vty, oi, json, use_json);
}
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (use_json)
+ vty_json(vty, json);
+ else
vty_out(vty, "\n");
return CMD_SUCCESS;
@@ -5028,7 +4951,6 @@ static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty,
bool use_json, json_object *json)
{
char timebuf[OSPF_TIME_DUMP_SIZE];
- char buf[PREFIX_STRLEN];
json_object *json_sub = NULL;
if (use_json)
@@ -5038,9 +4960,8 @@ static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty,
/* Show interface address. */
if (use_json)
- json_object_string_add(json_sub, "ifaceAddress",
- inet_ntop(AF_INET, &nbr_nbma->addr,
- buf, sizeof(buf)));
+ json_object_string_addf(json_sub, "ifaceAddress", "%pI4",
+ &nbr_nbma->addr);
else
vty_out(vty, " interface address %pI4\n",
&nbr_nbma->addr);
@@ -5113,7 +5034,6 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
char timebuf[OSPF_TIME_DUMP_SIZE];
json_object *json_neigh = NULL, *json_neigh_array = NULL;
char neigh_str[INET_ADDRSTRLEN] = {0};
- char buf[PREFIX_STRLEN];
if (use_json) {
if (prev_nbr &&
@@ -5150,10 +5070,8 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show interface address. */
if (use_json)
- json_object_string_add(json_neigh, "ifaceAddress",
- inet_ntop(AF_INET,
- &nbr->address.u.prefix4,
- buf, sizeof(buf)));
+ json_object_string_addf(json_neigh, "ifaceAddress", "%pI4",
+ &nbr->address.u.prefix4);
else
vty_out(vty, " interface address %pI4\n",
&nbr->address.u.prefix4);
@@ -5230,17 +5148,15 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show Designated Rotuer ID. */
if (use_json)
- json_object_string_add(json_neigh, "routerDesignatedId",
- inet_ntop(AF_INET, &nbr->d_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json_neigh, "routerDesignatedId",
+ "%pI4", &nbr->d_router);
else
vty_out(vty, " DR is %pI4,", &nbr->d_router);
/* Show Backup Designated Rotuer ID. */
if (use_json)
- json_object_string_add(json_neigh, "routerDesignatedBackupId",
- inet_ntop(AF_INET, &nbr->bd_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json_neigh, "routerDesignatedBackupId",
+ "%pI4", &nbr->bd_router);
else
vty_out(vty, " BDR is %pI4\n", &nbr->bd_router);
@@ -5439,11 +5355,9 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
}
}
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (use_json)
+ vty_json(vty, json);
+ else
vty_out(vty, "\n");
return CMD_SUCCESS;
@@ -5594,12 +5508,8 @@ DEFUN (show_ip_ospf_neighbor_detail,
ret = show_ip_ospf_neighbor_detail_common(
vty, ospf, json, uj, use_vrf);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -5666,11 +5576,8 @@ DEFUN (show_ip_ospf_instance_neighbor_detail,
ret = show_ip_ospf_neighbor_detail_common(vty, ospf, json, uj, 0);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -5783,12 +5690,8 @@ DEFUN (show_ip_ospf_neighbor_detail_all,
vty, ospf, json, uj, use_vrf);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -5856,11 +5759,8 @@ DEFUN (show_ip_ospf_instance_neighbor_detail_all,
ret = show_ip_ospf_neighbor_detail_all_common(vty, ospf, json, uj, 0);
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -5916,11 +5816,9 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty,
}
}
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (use_json)
+ vty_json(vty, json);
+ else
vty_out(vty, "\n");
return CMD_SUCCESS;
@@ -5995,7 +5893,6 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self,
struct summary_lsa *sl;
struct as_external_lsa *asel;
struct prefix_ipv4 p;
- char buf[PREFIX2STR_BUFFER];
if (lsa != NULL)
/* If self option is set, check LSA self flag. */
@@ -6018,15 +5915,11 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self,
ntohl(lsa->data->ls_seqnum));
snprintf(checksum, sizeof(checksum), "%x",
ntohs(lsa->data->checksum));
- json_object_string_add(
- json_lsa, "lsId",
- inet_ntop(AF_INET, &lsa->data->id,
- buf, sizeof(buf)));
- json_object_string_add(
- json_lsa, "advertisedRouter",
- inet_ntop(AF_INET,
- &lsa->data->adv_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json_lsa, "lsId",
+ "%pI4", &lsa->data->id);
+ json_object_string_addf(
+ json_lsa, "advertisedRouter", "%pI4",
+ &lsa->data->adv_router);
json_object_int_add(json_lsa, "lsaAge",
LS_AGE(lsa));
json_object_string_add(
@@ -6058,10 +5951,9 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self,
if (!json_lsa)
vty_out(vty, " %pFX", &p);
else {
- prefix2str(&p, buf, sizeof(buf));
- json_object_string_add(json_lsa,
- "summaryAddress",
- buf);
+ json_object_string_addf(
+ json_lsa, "summaryAddress",
+ "%pFX", &p);
}
break;
case OSPF_AS_EXTERNAL_LSA:
@@ -6083,15 +5975,14 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self,
(unsigned long)ntohl(
asel->e[0].route_tag));
else {
- prefix2str(&p, buf, sizeof(buf));
json_object_string_add(
json_lsa, "metricType",
IS_EXTERNAL_METRIC(
asel->e[0].tos)
? "E2"
: "E1");
- json_object_string_add(json_lsa,
- "route", buf);
+ json_object_string_addf(
+ json_lsa, "route", "%pFX", &p);
json_object_int_add(
json_lsa, "tag",
(unsigned long)ntohl(
@@ -6162,7 +6053,6 @@ static const char *const show_database_header[] = {
static void show_ip_ospf_database_header(struct vty *vty, struct ospf_lsa *lsa,
json_object *json)
{
- char buf[PREFIX_STRLEN];
struct router_lsa *rlsa = (struct router_lsa *)lsa->data;
if (!json) {
@@ -6243,13 +6133,10 @@ static void show_ip_ospf_database_header(struct vty *vty, struct ospf_lsa *lsa,
json_object_string_add(
json, "lsaType",
lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL));
- json_object_string_add(json, "linkStateId",
- inet_ntop(AF_INET, &lsa->data->id,
- buf, sizeof(buf)));
- json_object_string_add(json, "advertisingRouter",
- inet_ntop(AF_INET,
- &lsa->data->adv_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "linkStateId", "%pI4",
+ &lsa->data->id);
+ json_object_string_addf(json, "advertisingRouter", "%pI4",
+ &lsa->data->adv_router);
json_object_string_add(json, "lsaSeqNumber", seqnum);
json_object_string_add(json, "checksum", checksum);
json_object_int_add(json, "length", ntohs(lsa->data->length));
@@ -6478,7 +6365,6 @@ static int show_summary_asbr_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
json_object *json)
{
- char buf[PREFIX_STRLEN];
int tos = 0;
if (lsa != NULL) {
@@ -6513,10 +6399,8 @@ static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
json_object_int_add(json, "tos", tos);
json_object_int_add(json, "metric",
GET_METRIC(al->e[0].metric));
- json_object_string_add(json, "forwardAddress",
- inet_ntop(AF_INET,
- &(al->e[0].fwd_addr),
- buf, sizeof(buf)));
+ json_object_string_addf(json, "forwardAddress", "%pI4",
+ &(al->e[0].fwd_addr));
json_object_int_add(
json, "externalRouteTag",
(route_tag_t)ntohl(al->e[0].route_tag));
@@ -6530,7 +6414,6 @@ static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
static int show_as_nssa_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
json_object *json)
{
- char buf[PREFIX_STRLEN];
int tos = 0;
if (lsa != NULL) {
@@ -6566,10 +6449,8 @@ static int show_as_nssa_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
json_object_int_add(json, "tos", tos);
json_object_int_add(json, "metric",
GET_METRIC(al->e[0].metric));
- json_object_string_add(json, "nssaForwardAddress",
- inet_ntop(AF_INET,
- &al->e[0].fwd_addr,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "nssaForwardAddress",
+ "%pI4", &al->e[0].fwd_addr);
json_object_int_add(
json, "externalRouteTag",
(route_tag_t)ntohl(al->e[0].route_tag));
@@ -6961,15 +6842,11 @@ static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf,
json_lsa = json_object_new_object();
json_object_int_add(json_lsa, "linkType",
lsa->data->type);
- json_object_string_add(
- json_lsa, "linkStateId",
- inet_ntop(AF_INET, &lsa->data->id,
- buf, sizeof(buf)));
- json_object_string_add(
- json_lsa, "advertisingRouter",
- inet_ntop(AF_INET,
- &lsa->data->adv_router,
- buf, sizeof(buf)));
+ json_object_string_addf(json_lsa, "linkStateId",
+ "%pI4", &lsa->data->id);
+ json_object_string_addf(
+ json_lsa, "advertisingRouter", "%pI4",
+ &lsa->data->adv_router);
json_object_int_add(json_lsa, "lsaLockCount",
lsa->lock);
json_object_object_add(
@@ -7011,7 +6888,6 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf,
int idx_type = 4;
int type, ret;
struct in_addr id, adv_router;
- char buf[PREFIX_STRLEN];
json_object *json_vrf = NULL;
if (uj) {
@@ -7033,9 +6909,8 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf,
/* Show Router ID. */
if (uj) {
- json_object_string_add(json_vrf, "routerId",
- inet_ntop(AF_INET, &ospf->router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_vrf, "routerId", "%pI4",
+ &ospf->router_id);
} else {
vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n",
&ospf->router_id);
@@ -7249,12 +7124,8 @@ DEFUN (show_ip_ospf_instance_database_max,
show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0, json, uj);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -7285,7 +7156,6 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty,
int idx_type = 4;
int type, ret;
struct in_addr adv_router;
- char buf[PREFIX_STRLEN];
json_object *json_vrf = NULL;
if (uj) {
@@ -7307,9 +7177,8 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty,
/* Show Router ID. */
if (uj) {
- json_object_string_add(json_vrf, "routerId",
- inet_ntop(AF_INET, &ospf->router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_vrf, "routerId", "%pI4",
+ &ospf->router_id);
} else {
vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n",
&ospf->router_id);
@@ -7468,12 +7337,8 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router,
show_ip_ospf_database_type_adv_router_common(vty, ospf, 1, argc, argv,
0, json, uj);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -8125,7 +7990,7 @@ static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str,
if (nbr_str) {
struct ospf *ospf = NULL;
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
if (ospf) {
oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr);
if (oi)
@@ -8243,7 +8108,7 @@ DEFUN (no_ip_ospf_dead_interval,
if (argc == 1) {
struct ospf *ospf = NULL;
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
if (ospf) {
oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr);
if (oi)
@@ -8895,7 +8760,7 @@ DEFUN (ip_ospf_area,
areaid = argv[idx + 1]->arg;
if (!instance)
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
else
ospf = ospf_lookup_instance(instance);
@@ -8926,7 +8791,7 @@ DEFUN (ip_ospf_area,
}
if (count > 0) {
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
if (ospf)
ospf_interface_area_unset(ospf, ifp);
}
@@ -9019,7 +8884,7 @@ DEFUN (no_ip_ospf_area,
instance = strtol(argv[idx]->arg, NULL, 10);
if (!instance)
- ospf = ospf_lookup_by_vrf_id(ifp->vrf_id);
+ ospf = ifp->vrf->info;
else
ospf = ospf_lookup_instance(instance);
@@ -10082,7 +9947,6 @@ static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf,
struct ospf_route * or ;
struct listnode *pnode, *pnnode;
struct ospf_path *path;
- char buf[PREFIX_STRLEN];
json_object *json_route = NULL, *json_nexthop_array = NULL,
*json_nexthop = NULL;
@@ -10112,11 +9976,9 @@ static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf,
"N IA");
json_object_int_add(json_route, "cost",
or->cost);
- json_object_string_add(
- json_route, "area",
- inet_ntop(AF_INET,
- &or->u.std.area_id,
- buf1, sizeof(buf1)));
+ json_object_string_addf(
+ json_route, "area", "%pI4",
+ &or->u.std.area_id);
} else {
vty_out(vty,
"N IA %-18s [%d] area: %pI4\n",
@@ -10141,10 +10003,9 @@ static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf,
"N");
json_object_int_add(json_route, "cost",
or->cost);
- json_object_string_add(
- json_route, "area",
- inet_ntop(AF_INET, &or->u.std.area_id,
- buf1, sizeof(buf1)));
+ json_object_string_addf(json_route, "area",
+ "%pI4",
+ &or->u.std.area_id);
} else {
vty_out(vty, "N %-18s [%d] area: %pI4\n",
buf1, or->cost,
@@ -10195,14 +10056,10 @@ static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf,
}
} else {
if (json) {
- json_object_string_add(
+ json_object_string_addf(
json_nexthop,
- "ip",
- inet_ntop(
- AF_INET,
- &path->nexthop,
- buf,
- sizeof(buf)));
+ "ip", "%pI4",
+ &path->nexthop);
json_object_string_add(
json_nexthop,
"via",
@@ -10271,10 +10128,9 @@ static void show_ip_ospf_route_router(struct vty *vty, struct ospf *ospf,
if (json) {
json_object_int_add(json_route, "cost",
or->cost);
- json_object_string_add(
- json_route, "area",
- inet_ntop(AF_INET, &or->u.std.area_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_route, "area",
+ "%pI4",
+ &or->u.std.area_id);
if (or->path_type == OSPF_PATH_INTER_AREA)
json_object_boolean_true_add(json_route,
"IA");
@@ -10339,13 +10195,10 @@ static void show_ip_ospf_route_router(struct vty *vty, struct ospf *ospf,
}
} else {
if (json) {
- json_object_string_add(
+ json_object_string_addf(
json_nexthop,
- "ip",
- inet_ntop(
- AF_INET,
- &path->nexthop,
- buf, sizeof(buf)));
+ "ip", "%pI4",
+ &path->nexthop);
json_object_string_add(
json_nexthop,
"via",
@@ -10378,7 +10231,6 @@ static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf,
struct ospf_route *er;
struct listnode *pnode, *pnnode;
struct ospf_path *path;
- char buf[PREFIX_STRLEN];
json_object *json_route = NULL, *json_nexthop_array = NULL,
*json_nexthop = NULL;
@@ -10469,13 +10321,9 @@ static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf,
}
} else {
if (json) {
- json_object_string_add(
+ json_object_string_addf(
json_nexthop, "ip",
- inet_ntop(
- AF_INET,
- &path->nexthop,
- buf,
- sizeof(buf)));
+ "%pI4", &path->nexthop);
json_object_string_add(
json_nexthop, "via",
ifindex2ifname(
@@ -10700,11 +10548,7 @@ DEFUN (show_ip_ospf_route,
if (uj) {
/* Keep Non-pretty format */
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
+ vty_json(vty, json);
} else if (!ospf_output)
vty_out(vty, "%% OSPF instance not found\n");
@@ -10712,14 +10556,9 @@ DEFUN (show_ip_ospf_route,
}
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_PRETTY
- | JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -10728,14 +10567,9 @@ DEFUN (show_ip_ospf_route,
/* Display default ospf (instance 0) info */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_PRETTY
- | JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -10797,7 +10631,6 @@ DEFUN (show_ip_ospf_vrfs,
struct ospf *ospf = NULL;
struct listnode *node = NULL;
int count = 0;
- char buf[PREFIX_STRLEN];
static const char header[] = "Name Id RouterId ";
if (uj) {
@@ -10825,10 +10658,8 @@ DEFUN (show_ip_ospf_vrfs,
if (uj) {
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
- json_object_string_add(
- json_vrf, "routerId",
- inet_ntop(AF_INET, &ospf->router_id,
- buf, sizeof(buf)));
+ json_object_string_addf(json_vrf, "routerId", "%pI4",
+ &ospf->router_id);
json_object_object_add(json_vrfs, name, json_vrf);
@@ -10842,9 +10673,7 @@ DEFUN (show_ip_ospf_vrfs,
json_object_object_add(json, "vrfs", json_vrfs);
json_object_int_add(json, "totalVrfs", count);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
if (count)
vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
@@ -11131,12 +10960,8 @@ DEFUN (show_ip_ospf_external_aggregator,
vty, ospf, use_vrf, json, uj, detail);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return ret;
}
@@ -11144,12 +10969,9 @@ DEFUN (show_ip_ospf_external_aggregator,
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -11160,12 +10982,9 @@ DEFUN (show_ip_ospf_external_aggregator,
/* Default Vrf */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf == NULL || !ospf->oi_running) {
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- } else
+ if (uj)
+ vty_json(vty, json);
+ else
vty_out(vty, "%% OSPF instance not found\n");
return CMD_SUCCESS;
@@ -11174,11 +10993,8 @@ DEFUN (show_ip_ospf_external_aggregator,
ospf_show_summary_address(vty, ospf, use_vrf, json, uj, detail);
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -11232,7 +11048,7 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
continue;
vty_frame(vty, "!\n");
- if (ifp->vrf_id == VRF_DEFAULT)
+ if (ifp->vrf->vrf_id == VRF_DEFAULT)
vty_frame(vty, "interface %s\n", ifp->name);
else
vty_frame(vty, "interface %s vrf %s\n", ifp->name,
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index dd0a49c9bc..05433ccb95 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1443,8 +1443,8 @@ void ospf_if_update(struct ospf *ospf, struct interface *ifp)
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "%s: interface %s ifp->vrf_id %u ospf vrf %s vrf_id %u router_id %pI4",
- __func__, ifp->name, ifp->vrf_id,
+ "%s: interface %s vrf %s(%u) ospf vrf %s vrf_id %u router_id %pI4",
+ __func__, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id,
&ospf->router_id);
diff --git a/pathd/path_ted.c b/pathd/path_ted.c
index d17b5a0aab..6bfca50450 100644
--- a/pathd/path_ted.c
+++ b/pathd/path_ted.c
@@ -471,12 +471,8 @@ DEFPY (show_pahtd_ted_db,
}
/* Show the complete TED */
ls_show_ted(ted_state_g.ted, vty, json, !st_json);
- if (st_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (st_json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
diff --git a/pbrd/pbr_vrf.c b/pbrd/pbr_vrf.c
index 1b69e23ce3..c3558ab591 100644
--- a/pbrd/pbr_vrf.c
+++ b/pbrd/pbr_vrf.c
@@ -92,17 +92,6 @@ static int pbr_vrf_delete(struct vrf *vrf)
return 0;
}
-struct pbr_vrf *pbr_vrf_lookup_by_id(vrf_id_t vrf_id)
-{
- struct vrf *vrf;
-
- vrf = vrf_lookup_by_id(vrf_id);
- if (vrf)
- return ((struct pbr_vrf *)vrf->info);
-
- return NULL;
-}
-
struct pbr_vrf *pbr_vrf_lookup_by_name(const char *name)
{
struct vrf *vrf;
diff --git a/pbrd/pbr_vrf.h b/pbrd/pbr_vrf.h
index 5953387de2..e37bcd42ba 100644
--- a/pbrd/pbr_vrf.h
+++ b/pbrd/pbr_vrf.h
@@ -34,7 +34,6 @@ static inline vrf_id_t pbr_vrf_id(const struct pbr_vrf *pbr_vrf)
return pbr_vrf->vrf->vrf_id;
}
-extern struct pbr_vrf *pbr_vrf_lookup_by_id(vrf_id_t vrf_id);
extern struct pbr_vrf *pbr_vrf_lookup_by_name(const char *name);
extern bool pbr_vrf_is_valid(const struct pbr_vrf *pbr_vrf);
extern bool pbr_vrf_is_enabled(const struct pbr_vrf *pbr_vrf);
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index cac056abd0..ebcbbb7205 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -592,16 +592,12 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
vty_out(vty, "You must specify the nexthop-vrf\n");
return CMD_WARNING_CONFIG_FAILED;
}
- if (ifp->vrf_id != vrf->vrf_id) {
- struct vrf *actual;
-
- actual = vrf_lookup_by_id(ifp->vrf_id);
+ if (ifp->vrf->vrf_id != vrf->vrf_id)
vty_out(vty,
"Specified Intf %s is not in vrf %s but is in vrf %s, using actual vrf\n",
- ifp->name, vrf->name, VRF_LOGNAME(actual));
- }
+ ifp->name, vrf->name, ifp->vrf->name);
nhop.ifindex = ifp->ifindex;
- nhop.vrf_id = ifp->vrf_id;
+ nhop.vrf_id = ifp->vrf->vrf_id;
}
if (addr) {
@@ -921,7 +917,6 @@ static void vty_json_pbrms(json_object *j, struct vty *vty,
json_object *jpbrm, *nexthop_group;
char *nhg_name = pbrms->nhgrp_name ? pbrms->nhgrp_name
: pbrms->internal_nhg_name;
- char buf[PREFIX_STRLEN];
char rbuf[64];
jpbrm = json_object_new_object();
@@ -957,13 +952,9 @@ static void vty_json_pbrms(json_object *j, struct vty *vty,
json_object_string_add(jpbrm, "vrfName", pbrms->vrf_name);
if (pbrms->src)
- json_object_string_add(
- jpbrm, "matchSrc",
- prefix2str(pbrms->src, buf, sizeof(buf)));
+ json_object_string_addf(jpbrm, "matchSrc", "%pFX", pbrms->src);
if (pbrms->dst)
- json_object_string_add(
- jpbrm, "matchDst",
- prefix2str(pbrms->dst, buf, sizeof(buf)));
+ json_object_string_addf(jpbrm, "matchDst", "%pFX", pbrms->dst);
if (pbrms->mark)
json_object_int_add(jpbrm, "matchMark", pbrms->mark);
if (pbrms->dsfield & PBR_DSFIELD_DSCP)
@@ -1041,12 +1032,8 @@ DEFPY (show_pbr_map,
vty_show_pbr_map(vty, pbrm, detail);
}
- if (j) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- j, JSON_C_TO_STRING_PRETTY));
- json_object_free(j);
- }
+ if (j)
+ vty_json(vty, j);
return CMD_SUCCESS;
}
@@ -1068,11 +1055,7 @@ DEFPY(show_pbr_nexthop_group,
if (j) {
pbr_nht_json_nexthop_group(j, word);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- j, JSON_C_TO_STRING_PRETTY));
-
- json_object_free(j);
+ vty_json(vty, j);
} else
pbr_nht_show_nexthop_group(vty, word);
@@ -1146,12 +1129,8 @@ DEFPY (show_pbr_interface,
}
}
- if (j) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- j, JSON_C_TO_STRING_PRETTY));
- json_object_free(j);
- }
+ if (j)
+ vty_json(vty, j);
return CMD_SUCCESS;
}
diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c
index 8a9bb0201e..b480d4072e 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -513,7 +513,7 @@ pbr_encode_pbr_map_sequence_vrf(struct stream *s,
struct pbr_vrf *pbr_vrf;
if (pbrms->vrf_unchanged)
- pbr_vrf = pbr_vrf_lookup_by_id(ifp->vrf_id);
+ pbr_vrf = ifp->vrf->info;
else
pbr_vrf = pbr_vrf_lookup_by_name(pbrms->vrf_name);
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index c7fcbba71e..696544c8d6 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -97,7 +97,7 @@ void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp,
pim_ifp->bfd_config.min_rx, pim_ifp->bfd_config.min_tx);
bfd_sess_set_ipv4_addrs(neigh->bfd_session, NULL, &neigh->source_addr);
bfd_sess_set_interface(neigh->bfd_session, neigh->interface->name);
- bfd_sess_set_vrf(neigh->bfd_session, neigh->interface->vrf_id);
+ bfd_sess_set_vrf(neigh->bfd_session, neigh->interface->vrf->vrf_id);
bfd_sess_set_profile(neigh->bfd_session, pim_ifp->bfd_config.profile);
bfd_sess_install(neigh->bfd_session);
}
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index 4689b27034..238c19d2cc 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -35,6 +35,7 @@
#include "pim_nht.h"
#include "pim_bsm.h"
#include "pim_time.h"
+#include "pim_zebra.h"
/* Functions forward declaration */
static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout);
@@ -579,6 +580,7 @@ void pim_bsm_clear(struct pim_instance *pim)
struct rp_info *rp_all;
struct pim_upstream *up;
struct rp_info *rp_info;
+ bool upstream_updated = false;
if (pim->global_scope.current_bsr.s_addr)
pim_nht_bsr_del(pim, pim->global_scope.current_bsr);
@@ -681,8 +683,12 @@ void pim_bsm_clear(struct pim_instance *pim)
} else {
/* RP found for the group grp */
pim_upstream_update(pim, up);
+ upstream_updated = true;
}
}
+
+ if (upstream_updated)
+ pim_zebra_update_all_interfaces(pim);
}
static bool pim_bsm_send_intf(uint8_t *buf, int len, struct interface *ifp,
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 82627e5e84..501d69dbf5 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -308,14 +308,12 @@ static void json_object_pim_ifp_add(struct json_object *json,
struct interface *ifp)
{
struct pim_interface *pim_ifp;
- char buf[PREFIX_STRLEN];
pim_ifp = ifp->info;
json_object_string_add(json, "name", ifp->name);
json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
- json_object_string_add(json, "address",
- inet_ntop(AF_INET, &pim_ifp->primary_address,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "address", "%pI4",
+ &pim_ifp->primary_address);
json_object_int_add(json, "index", ifp->ifindex);
if (if_is_multicast(ifp))
@@ -489,7 +487,6 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
struct interface *ifp;
time_t now;
char buf[PREFIX_STRLEN];
- char quer_buf[PREFIX_STRLEN];
json_object *json = NULL;
json_object *json_row = NULL;
@@ -537,10 +534,9 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
"queryTimer",
query_hhmmss);
}
- json_object_string_add(
- json_row, "querierIp",
- inet_ntop(AF_INET, &igmp->querier_addr,
- quer_buf, sizeof(quer_buf)));
+ json_object_string_addf(json_row, "querierIp",
+ "%pI4",
+ &igmp->querier_addr);
json_object_object_add(json, ifp->name,
json_row);
@@ -584,7 +580,6 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
struct listnode *sock_node;
struct pim_interface *pim_ifp;
char uptime[10];
- char quer_buf[PREFIX_STRLEN];
char query_hhmmss[10];
char other_hhmmss[10];
int found_ifname = 0;
@@ -669,10 +664,9 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
igmp->t_igmp_query_timer
? "local"
: "other");
- json_object_string_add(
- json_row, "querierIp",
- inet_ntop(AF_INET, &igmp->querier_addr,
- quer_buf, sizeof(quer_buf)));
+ json_object_string_addf(json_row, "querierIp",
+ "%pI4",
+ &igmp->querier_addr);
json_object_int_add(json_row, "queryStartCount",
igmp->startup_query_count);
json_object_string_add(json_row,
@@ -928,7 +922,6 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
int mloop = 0;
int found_ifname = 0;
int print_header;
- char buf[PREFIX_STRLEN];
json_object *json = NULL;
json_object *json_row = NULL;
json_object *json_pim_neighbor = NULL;
@@ -979,11 +972,9 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
json_object_pim_ifp_add(json_row, ifp);
if (pim_ifp->update_source.s_addr != INADDR_ANY) {
- json_object_string_add(
- json_row, "useSource",
- inet_ntop(AF_INET,
- &pim_ifp->update_source,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_row, "useSource", "%pI4",
+ &pim_ifp->update_source);
}
if (pim_ifp->sec_addr_list) {
json_object *sec_list = NULL;
@@ -1407,7 +1398,6 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
int fhr = 0;
int pim_nbrs = 0;
int pim_ifchannels = 0;
- char buf[PREFIX_STRLEN];
json_object *json = NULL;
json_object *json_row = NULL;
json_object *json_tmp;
@@ -1437,10 +1427,8 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
json_object_int_add(json_row, "firstHopRouterCount", fhr);
- json_object_string_add(json_row, "pimDesignatedRouter",
- inet_ntop(AF_INET,
- &pim_ifp->pim_dr_addr, buf,
- sizeof(buf)));
+ json_object_string_addf(json_row, "pimDesignatedRouter", "%pI4",
+ &pim_ifp->pim_dr_addr);
if (pim_ifp->pim_dr_addr.s_addr
== pim_ifp->primary_address.s_addr)
@@ -5715,10 +5703,8 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
json_object_string_add(json_row, "name", ifp->name);
json_object_string_add(json_row, "state",
if_is_up(ifp) ? "up" : "down");
- json_object_string_add(
- json_row, "address",
- inet_ntop(AF_INET, &pim_ifp->primary_address,
- buf, sizeof(buf)));
+ json_object_string_addf(json_row, "address", "%pI4",
+ &pim_ifp->primary_address);
json_object_int_add(json_row, "ifIndex", ifp->ifindex);
json_object_int_add(json_row, "vif",
pim_ifp->mroute_vif_index);
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 5e311d101a..e007bdcc10 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -121,7 +121,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
pim_ifp->options = 0;
- pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
+ pim_ifp->pim = ifp->vrf->info;
pim_ifp->mroute_vif_index = -1;
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
@@ -785,12 +785,11 @@ void pim_if_addr_del_all(struct interface *ifp)
struct connected *ifc;
struct listnode *node;
struct listnode *nextnode;
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
struct pim_instance *pim;
- if (!vrf)
+ pim = ifp->vrf->info;
+ if (!pim)
return;
- pim = vrf->info;
/* PIM/IGMP enabled ? */
if (!ifp->info)
@@ -829,26 +828,6 @@ void pim_if_addr_del_all_igmp(struct interface *ifp)
}
}
-void pim_if_addr_del_all_pim(struct interface *ifp)
-{
- struct connected *ifc;
- struct listnode *node;
- struct listnode *nextnode;
-
- /* PIM/IGMP enabled ? */
- if (!ifp->info)
- return;
-
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
- struct prefix *p = ifc->address;
-
- if (p->family != AF_INET)
- continue;
-
- pim_if_addr_del_pim(ifc);
- }
-}
-
struct in_addr pim_find_primary_addr(struct interface *ifp)
{
struct connected *ifc;
@@ -857,10 +836,6 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
int v4_addrs = 0;
int v6_addrs = 0;
struct pim_interface *pim_ifp = ifp->info;
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
- if (!vrf)
- return addr;
if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
return pim_ifp->update_source;
@@ -899,10 +874,11 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
struct interface *lo_ifp;
// DBS - Come back and check here
- if (ifp->vrf_id == VRF_DEFAULT)
- lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
+ if (ifp->vrf->vrf_id == VRF_DEFAULT)
+ lo_ifp = if_lookup_by_name("lo", ifp->vrf->vrf_id);
else
- lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
+ lo_ifp = if_lookup_by_name(ifp->vrf->name,
+ ifp->vrf->vrf_id);
if (lo_ifp && (lo_ifp != ifp))
return pim_find_primary_addr(lo_ifp);
@@ -1550,13 +1526,13 @@ int pim_ifp_create(struct interface *ifp)
{
struct pim_instance *pim;
- pim = pim_get_pim_instance(ifp->vrf_id);
+ pim = ifp->vrf->info;
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
- __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
- (long)ifp->flags, ifp->metric, ifp->mtu,
- if_is_operative(ifp));
+ "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
+ __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
+ ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
+ ifp->mtu, if_is_operative(ifp));
}
if (if_is_operative(ifp)) {
@@ -1622,13 +1598,13 @@ int pim_ifp_up(struct interface *ifp)
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
- __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
- (long)ifp->flags, ifp->metric, ifp->mtu,
- if_is_operative(ifp));
+ "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
+ __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
+ ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
+ ifp->mtu, if_is_operative(ifp));
}
- pim = pim_get_pim_instance(ifp->vrf_id);
+ pim = ifp->vrf->info;
pim_ifp = ifp->info;
/*
@@ -1653,7 +1629,7 @@ int pim_ifp_up(struct interface *ifp)
struct vrf *vrf;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((table_id == vrf->data.l.table_id)
- && (ifp->vrf_id != vrf->vrf_id)) {
+ && (ifp->vrf->vrf_id != vrf->vrf_id)) {
struct interface *master = if_lookup_by_name(
vrf->name, vrf->vrf_id);
@@ -1674,10 +1650,10 @@ int pim_ifp_down(struct interface *ifp)
{
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
- __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
- (long)ifp->flags, ifp->metric, ifp->mtu,
- if_is_operative(ifp));
+ "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
+ __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
+ ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
+ ifp->mtu, if_is_operative(ifp));
}
if (!if_is_operative(ifp)) {
@@ -1710,16 +1686,16 @@ int pim_ifp_destroy(struct interface *ifp)
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
- "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
- __func__, ifp->name, ifp->ifindex, ifp->vrf_id,
- (long)ifp->flags, ifp->metric, ifp->mtu,
- if_is_operative(ifp));
+ "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
+ __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
+ ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
+ ifp->mtu, if_is_operative(ifp));
}
if (!if_is_operative(ifp))
pim_if_addr_del_all(ifp);
- pim = pim_get_pim_instance(ifp->vrf_id);
+ pim = ifp->vrf->info;
if (pim && pim->vxlan.term_if == ifp)
pim_vxlan_del_term_dev(pim);
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index 55c278d6e2..d0fd3d5925 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -193,7 +193,6 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any);
void pim_if_addr_add_all(struct interface *ifp);
void pim_if_addr_del_all(struct interface *ifp);
void pim_if_addr_del_all_igmp(struct interface *ifp);
-void pim_if_addr_del_all_pim(struct interface *ifp);
int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term);
int pim_if_del_vif(struct interface *ifp);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 86f897aed1..a17e8e89b2 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -651,18 +651,17 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
return ch;
}
-static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del)
+static void ifjoin_to_noinfo(struct pim_ifchannel *ch)
{
- pim_forward_stop(ch, !ch_del);
pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO);
+ pim_forward_stop(ch);
if (ch->upstream)
PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags);
PIM_IF_FLAG_UNSET_PROTO_PIM(ch->flags);
- if (ch_del)
- delete_on_noinfo(ch);
+ delete_on_noinfo(ch);
}
static int on_ifjoin_expiry_timer(struct thread *t)
@@ -675,7 +674,7 @@ static int on_ifjoin_expiry_timer(struct thread *t)
zlog_debug("%s: ifchannel %s expiry timer", __func__,
ch->sg_str);
- ifjoin_to_noinfo(ch, true);
+ ifjoin_to_noinfo(ch);
/* ch may have been deleted */
return 0;
@@ -714,7 +713,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
&rpf, ch->upstream, 0);
}
- ifjoin_to_noinfo(ch, true);
+ ifjoin_to_noinfo(ch);
} else {
/* If SGRpt flag is set on ifchannel, Trigger SGRpt
* message on RP path upon prune timer expiry.
@@ -1568,10 +1567,3 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
if (send_upstream_starg)
pim_jp_agg_single_upstream_send(&starup->rpf, starup, true);
}
-
-unsigned int pim_ifchannel_hash_key(const void *arg)
-{
- const struct pim_ifchannel *ch = arg;
-
- return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);
-}
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index 52f02a660b..332d40d926 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -160,6 +160,5 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
const struct pim_ifchannel *ch2);
-unsigned int pim_ifchannel_hash_key(const void *arg);
void delete_on_noinfo(struct pim_ifchannel *ch);
#endif /* PIM_IFCHANNEL_H */
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index cd905b3cbd..df773f38d0 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -141,18 +141,6 @@ struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,
return NULL;
}
-struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd)
-{
- struct listnode *sock_node;
- struct igmp_sock *igmp;
-
- for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp))
- if (fd == igmp->fd)
- return igmp;
-
- return NULL;
-}
-
static int pim_igmp_other_querier_expire(struct thread *t)
{
struct igmp_sock *igmp;
@@ -324,7 +312,7 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
return 0;
}
- if (if_address_is_local(&from, AF_INET, ifp->vrf_id)) {
+ if (if_address_is_local(&from, AF_INET, ifp->vrf->vrf_id)) {
if (PIM_DEBUG_IGMP_PACKETS)
zlog_debug("Recv IGMP query on interface: %s from ourself %s",
ifp->name, from_str);
diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h
index dfe986e8f5..1d514086f6 100644
--- a/pimd/pim_igmp.h
+++ b/pimd/pim_igmp.h
@@ -110,7 +110,6 @@ void pim_igmp_if_fini(struct pim_interface *pim_ifp);
struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,
struct in_addr ifaddr);
-struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd);
struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
struct in_addr ifaddr,
struct interface *ifp,
diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c
index d95d9dd25d..5c6f55e99d 100644
--- a/pimd/pim_jp_agg.c
+++ b/pimd/pim_jp_agg.c
@@ -368,7 +368,7 @@ void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf,
if (!up || !rpf->source_nexthop.interface ||
pim_if_connected_to_source(rpf->source_nexthop.interface,
up->sg.src) ||
- if_is_loopback_or_vrf(rpf->source_nexthop.interface))
+ if_is_loopback(rpf->source_nexthop.interface))
return;
memset(&groups, 0, sizeof(groups));
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index b9da8ec068..445c265e2c 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -371,14 +371,6 @@ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
struct pim_interface *pim_ifp;
assert(igmp);
-
- /* other querier present? */
-
- if (igmp->t_other_querier_timer)
- return;
-
- /* this is the querier */
-
assert(igmp->interface);
assert(igmp->interface->info);
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index 3df7dc41ce..30dc6b3e92 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -692,7 +692,7 @@ int pim_hello_send(struct interface *ifp, uint16_t holdtime)
{
struct pim_interface *pim_ifp = ifp->info;
- if (if_is_loopback_or_vrf(ifp))
+ if (if_is_loopback(ifp))
return 0;
if (hello_send(ifp, holdtime)) {
@@ -794,7 +794,7 @@ void pim_hello_restart_triggered(struct interface *ifp)
/*
* No need to ever start loopback or vrf device hello's
*/
- if (if_is_loopback_or_vrf(ifp))
+ if (if_is_loopback(ifp))
return;
/*
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 7ad95d9f6a..516ec2b2ee 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -413,7 +413,6 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
old_rpf.source_nexthop.interface))
pim_zebra_upstream_rpf_changed(pim, up, &old_rpf);
- pim_zebra_update_all_interfaces(pim);
}
int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
@@ -431,6 +430,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
struct prefix nht_p;
struct route_node *rn;
struct pim_upstream *up;
+ bool upstream_updated = false;
if (rp_addr.s_addr == INADDR_ANY ||
rp_addr.s_addr == INADDR_NONE)
@@ -547,10 +547,14 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
grp.u.prefix4 = up->sg.grp;
trp_info = pim_rp_find_match_group(
pim, &grp);
- if (trp_info == rp_all)
+ if (trp_info == rp_all) {
pim_upstream_update(pim, up);
+ upstream_updated = true;
+ }
}
}
+ if (upstream_updated)
+ pim_zebra_update_all_interfaces(pim);
pim_rp_check_interfaces(pim, rp_all);
pim_rp_refresh_group_to_rp_mapping(pim);
@@ -634,11 +638,16 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
grp.u.prefix4 = up->sg.grp;
trp_info = pim_rp_find_match_group(pim, &grp);
- if (trp_info == rp_info)
+ if (trp_info == rp_info) {
pim_upstream_update(pim, up);
+ upstream_updated = true;
+ }
}
}
+ if (upstream_updated)
+ pim_zebra_update_all_interfaces(pim);
+
pim_rp_check_interfaces(pim, rp_info);
pim_rp_refresh_group_to_rp_mapping(pim);
@@ -695,6 +704,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
struct bsgrp_node *bsgrp = NULL;
struct bsm_rpinfo *bsrp = NULL;
char rp_str[INET_ADDRSTRLEN];
+ bool upstream_updated = false;
if (!inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str)))
snprintf(rp_str, sizeof(rp_str), "<rp?>");
@@ -837,11 +847,16 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
}
/* RP found for the group grp */
- else
+ else {
pim_upstream_update(pim, up);
+ upstream_updated = true;
+ }
}
}
+ if (upstream_updated)
+ pim_zebra_update_all_interfaces(pim);
+
XFREE(MTYPE_PIM_RP, rp_info);
return PIM_SUCCESS;
}
@@ -854,6 +869,7 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr,
int result = 0;
struct rp_info *rp_info = NULL;
struct pim_upstream *up;
+ bool upstream_updated = false;
rn = route_node_lookup(pim->rp_table, &group);
if (!rn) {
@@ -908,11 +924,16 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr,
grp.u.prefix4 = up->sg.grp;
trp_info = pim_rp_find_match_group(pim, &grp);
- if (trp_info == rp_info)
+ if (trp_info == rp_info) {
pim_upstream_update(pim, up);
+ upstream_updated = true;
+ }
}
}
+ if (upstream_updated)
+ pim_zebra_update_all_interfaces(pim);
+
/* Register new RP addr with Zebra NHT */
nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
if (PIM_DEBUG_PIM_NHT_RP)
@@ -1228,12 +1249,9 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
json_rp_rows = json_object_new_array();
json_row = json_object_new_object();
- json_object_string_add(
- json_row, "rpAddress",
- inet_ntop(AF_INET,
- &rp_info->rp.rpf_addr.u
- .prefix4,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_row, "rpAddress", "%pI4",
+ &rp_info->rp.rpf_addr.u.prefix4);
if (rp_info->rp.source_nexthop.interface)
json_object_string_add(
json_row, "outboundInterface",
@@ -1255,10 +1273,9 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
"prefixList",
rp_info->plist);
else
- json_object_string_add(
- json_row, "group",
- prefix2str(&rp_info->group, buf,
- 48));
+ json_object_string_addf(
+ json_row, "group", "%pFX",
+ &rp_info->group);
json_object_string_add(json_row, "source",
source);
@@ -1303,9 +1320,7 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
buf, sizeof(buf)),
json_rp_rows);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
}
diff --git a/pimd/pim_static.c b/pimd/pim_static.c
index 63a9a00659..be06a25bea 100644
--- a/pimd/pim_static.c
+++ b/pimd/pim_static.c
@@ -92,7 +92,7 @@ int pim_static_add(struct pim_instance *pim, struct interface *iif,
return -4;
}
#endif
- if (iif->vrf_id != oif->vrf_id) {
+ if (iif->vrf->vrf_id != oif->vrf->vrf_id) {
return -3;
}
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 6f22937de8..05da3cb7c2 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -561,7 +561,7 @@ static void forward_off(struct pim_upstream *up)
/* scan per-interface (S,G) state */
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
- pim_forward_stop(ch, false);
+ pim_forward_stop(ch);
} /* scan iface channel list */
}
@@ -803,9 +803,8 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
if (pim_upstream_is_sg_rpt(up) && up->parent &&
!I_am_RP(pim, up->sg.grp))
send_xg_jp = true;
- else
- pim_jp_agg_single_upstream_send(&up->rpf, up,
- 0 /* prune */);
+
+ pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */);
if (send_xg_jp) {
if (PIM_DEBUG_PIM_TRACE_DETAIL)
@@ -1863,6 +1862,8 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
flag = PIM_OIF_FLAG_PROTO_IGMP;
if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
flag |= PIM_OIF_FLAG_PROTO_PIM;
+ if (starch)
+ flag |= PIM_OIF_FLAG_PROTO_STAR;
}
pim_channel_add_oif(up->channel_oil, ifp, flag,
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index e24f647923..4c8a96a84e 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -1079,7 +1079,7 @@ void pim_vxlan_add_vif(struct interface *ifp)
if (pim->vrf->vrf_id != VRF_DEFAULT)
return;
- if (if_is_loopback_or_vrf(ifp))
+ if (if_is_loopback(ifp))
pim_vxlan_set_default_iif(pim, ifp);
if (vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED &&
diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h
index ce9054cd26..d17de8e3d0 100644
--- a/pimd/pim_vxlan.h
+++ b/pimd/pim_vxlan.h
@@ -116,7 +116,7 @@ static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up)
{
return (up->sg.src.s_addr != INADDR_ANY) &&
up->rpf.source_nexthop.interface &&
- if_is_loopback_or_vrf(up->rpf.source_nexthop.interface);
+ if_is_loopback(up->rpf.source_nexthop.interface);
}
static inline bool pim_vxlan_is_term_dev_cfg(struct pim_instance *pim,
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 0ef0ad533e..3a08c6aee5 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -164,7 +164,7 @@ static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
}
if (if_is_loopback(c->ifp)) {
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) {
@@ -845,14 +845,14 @@ void pim_forward_start(struct pim_ifchannel *ch)
mask, __func__);
}
-void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
+void pim_forward_stop(struct pim_ifchannel *ch)
{
struct pim_upstream *up = ch->upstream;
if (PIM_DEBUG_PIM_TRACE) {
- zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
+ zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
__func__, ch->sg_str, ch->interface->name,
- install_it, up->channel_oil->installed);
+ up->channel_oil->installed);
}
/*
@@ -865,9 +865,6 @@ void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
else
pim_channel_del_oif(up->channel_oil, ch->interface,
PIM_OIF_FLAG_PROTO_PIM, __func__);
-
- if (install_it && !up->channel_oil->installed)
- pim_upstream_mroute_add(up->channel_oil, __func__);
}
void pim_zebra_zclient_update(struct vty *vty)
diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h
index 0f216cf5c9..349903cc67 100644
--- a/pimd/pim_zebra.h
+++ b/pimd/pim_zebra.h
@@ -42,7 +42,7 @@ void igmp_source_forward_stop(struct igmp_source *source);
void igmp_source_forward_reevaluate_all(struct pim_instance *pim);
void pim_forward_start(struct pim_ifchannel *ch);
-void pim_forward_stop(struct pim_ifchannel *ch, bool install_it);
+void pim_forward_stop(struct pim_ifchannel *ch);
void sched_rpf_cache_refresh(struct pim_instance *pim);
struct zclient *pim_zebra_zclient_get(void);
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 229104baff..7f8e89de16 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -564,8 +564,8 @@ zebra_spec_add_service fabricd 2618/tcp "Fabricd vty"
/sbin/install-info %{_infodir}/frr.info.gz %{_infodir}/dir
# Create dummy config file if they don't exist so basic functions can be used.
-if [ ! -e %{configdir}/zebra.conf ]; then
- # per daemon configs exist
+if [ ! -e %{configdir}/frr.conf ] && [ ! -e %{configdir}/zebra.conf ]; then
+ # No frr.conf and per daemon configs exist
mv %{configdir}/frr.conf.template %{configdir}/frr.conf
%if 0%{?frr_user:1}
chown %{frr_user}:%{frr_user} %{configdir}/frr.conf
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 3d128ee727..8fd64f2874 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -317,14 +317,12 @@ static int rip_ifp_down(struct interface *ifp)
rip_interface_sync(ifp);
rip_if_down(ifp);
- if (IS_RIP_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface %s vrf %s(%u) index %d flags %llx metric %d mtu %d is down",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
- }
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu);
return 0;
}
@@ -332,14 +330,12 @@ static int rip_ifp_down(struct interface *ifp)
/* Inteface link up message processing */
static int rip_ifp_up(struct interface *ifp)
{
- if (IS_RIP_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface %s vrf %s(%u) index %d flags %#llx metric %d mtu %d is up",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
- }
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu);
rip_interface_sync(ifp);
@@ -360,13 +356,12 @@ static int rip_ifp_create(struct interface *ifp)
{
rip_interface_sync(ifp);
- if (IS_RIP_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+ if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
- }
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu);
/* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp);
@@ -387,8 +382,6 @@ static int rip_ifp_create(struct interface *ifp)
static int rip_ifp_destroy(struct interface *ifp)
{
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
rip_interface_sync(ifp);
if (if_is_up(ifp)) {
rip_if_down(ifp);
@@ -397,8 +390,9 @@ static int rip_ifp_destroy(struct interface *ifp)
if (IS_RIP_DEBUG_ZEBRA)
zlog_debug(
"interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu);
return 0;
}
@@ -415,12 +409,11 @@ int rip_interface_vrf_update(ZAPI_CALLBACK_ARGS)
return 0;
if (IS_RIP_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
- ifp->name, VRF_LOGNAME(vrf), vrf_id,
- VRF_LOGNAME(nvrf), new_vrf_id);
+ ifp->name, ifp->vrf->name, vrf_id, VRF_LOGNAME(nvrf),
+ new_vrf_id);
}
if_update_to_new_vrf(ifp, new_vrf_id);
@@ -1130,16 +1123,11 @@ int rip_show_network_config(struct vty *vty, struct rip *rip)
void rip_interface_sync(struct interface *ifp)
{
- struct vrf *vrf;
-
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- if (vrf) {
- struct rip_interface *ri;
+ struct rip_interface *ri;
- ri = ifp->info;
- if (ri)
- ri->rip = vrf->info;
- }
+ ri = ifp->info;
+ if (ri)
+ ri->rip = ifp->vrf->info;
}
/* Called when interface structure allocated. */
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index dc577facc4..a6d379fda4 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -201,14 +201,12 @@ static int ripng_if_down(struct interface *ifp)
/* Inteface link up message processing. */
static int ripng_ifp_up(struct interface *ifp)
{
- if (IS_RIPNG_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"interface up %s vrf %s(%u) index %d flags %llx metric %d mtu %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
- }
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu6);
ripng_interface_sync(ifp);
@@ -230,14 +228,12 @@ static int ripng_ifp_down(struct interface *ifp)
ripng_interface_sync(ifp);
ripng_if_down(ifp);
- if (IS_RIPNG_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"interface down %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
- }
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu6);
return 0;
}
@@ -247,14 +243,12 @@ static int ripng_ifp_create(struct interface *ifp)
{
ripng_interface_sync(ifp);
- if (IS_RIPNG_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"RIPng interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
- }
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu6);
/* Check is this interface is RIP enabled or not.*/
ripng_enable_apply(ifp);
@@ -270,8 +264,6 @@ static int ripng_ifp_create(struct interface *ifp)
static int ripng_ifp_destroy(struct interface *ifp)
{
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
ripng_interface_sync(ifp);
if (if_is_up(ifp)) {
ripng_if_down(ifp);
@@ -280,8 +272,9 @@ static int ripng_ifp_destroy(struct interface *ifp)
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_debug(
"interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
- (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu6);
return 0;
}
@@ -298,12 +291,11 @@ int ripng_interface_vrf_update(ZAPI_CALLBACK_ARGS)
return 0;
if (IS_RIPNG_DEBUG_ZEBRA) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
- ifp->name, VRF_LOGNAME(vrf), vrf_id,
- VRF_LOGNAME(nvrf), new_vrf_id);
+ ifp->name, ifp->vrf->name, vrf_id, VRF_LOGNAME(nvrf),
+ new_vrf_id);
}
if_update_to_new_vrf(ifp, new_vrf_id);
@@ -896,16 +888,11 @@ static struct ripng_interface *ri_new(void)
void ripng_interface_sync(struct interface *ifp)
{
- struct vrf *vrf;
-
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- if (vrf) {
- struct ripng_interface *ri;
+ struct ripng_interface *ri;
- ri = ifp->info;
- if (ri)
- ri->ripng = vrf->info;
- }
+ ri = ifp->info;
+ if (ri)
+ ri->ripng = ifp->vrf->info;
}
static int ripng_if_new_hook(struct interface *ifp)
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index b6581cd9e6..0a323f744e 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -1065,12 +1065,8 @@ DEFUN (show_sharp_ted,
ls_show_ted(sg.ted, vty, json, verbose);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -1137,9 +1133,7 @@ DEFPY (show_sharp_segment_routing_srv6,
}
}
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- jo_locs, JSON_C_TO_STRING_PRETTY));
- json_object_free(jo_locs);
+ vty_json(vty, jo_locs);
} else {
for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
vty_out(vty, "Locator %s has %d prefix chunks\n",
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index 45c42ddcef..1d52dd30e2 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -432,13 +432,13 @@ static void static_ifindex_update_nh(struct interface *ifp, bool up,
if (up) {
if (strcmp(nh->ifname, ifp->name))
return;
- if (nh->nh_vrf_id != ifp->vrf_id)
+ if (nh->nh_vrf_id != ifp->vrf->vrf_id)
return;
nh->ifindex = ifp->ifindex;
} else {
if (nh->ifindex != ifp->ifindex)
return;
- if (nh->nh_vrf_id != ifp->vrf_id)
+ if (nh->nh_vrf_id != ifp->vrf->vrf_id)
return;
nh->ifindex = IFINDEX_INTERNAL;
}
@@ -723,7 +723,7 @@ static void static_fixup_intf_nh(struct route_table *stable,
continue;
frr_each(static_path_list, &si->path_list, pn) {
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
- if (nh->nh_vrf_id != ifp->vrf_id)
+ if (nh->nh_vrf_id != ifp->vrf->vrf_id)
continue;
if (nh->ifindex != ifp->ifindex)
@@ -750,7 +750,7 @@ void static_install_intf_nh(struct interface *ifp)
struct static_vrf *svrf = vrf->info;
/* Not needed if same vrf since happens naturally */
- if (vrf->vrf_id == ifp->vrf_id)
+ if (vrf->vrf_id == ifp->vrf->vrf_id)
continue;
/* Install any static routes configured for this interface. */
diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c
index 4bea3075c9..6ba0bf4544 100644
--- a/staticd/static_vrf.c
+++ b/staticd/static_vrf.c
@@ -123,17 +123,6 @@ struct route_table *static_vrf_static_table(afi_t afi, safi_t safi,
return svrf->stable[afi][safi];
}
-struct static_vrf *static_vrf_lookup_by_id(vrf_id_t vrf_id)
-{
- struct vrf *vrf;
-
- vrf = vrf_lookup_by_id(vrf_id);
- if (vrf)
- return ((struct static_vrf *)vrf->info);
-
- return NULL;
-}
-
struct static_vrf *static_vrf_lookup_by_name(const char *name)
{
struct vrf *vrf;
diff --git a/staticd/static_vrf.h b/staticd/static_vrf.h
index be311af8c4..885246bfaa 100644
--- a/staticd/static_vrf.h
+++ b/staticd/static_vrf.h
@@ -39,7 +39,6 @@ struct stable_info {
#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id
struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name);
-struct static_vrf *static_vrf_lookup_by_id(vrf_id_t vrf_id);
void static_vrf_init(void);
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 38b3c93d76..311aeda338 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -84,12 +84,6 @@ static int interface_address_delete(ZAPI_CALLBACK_ARGS)
static int static_ifp_up(struct interface *ifp)
{
- if (if_is_vrf(ifp)) {
- struct static_vrf *svrf = static_vrf_lookup_by_id(ifp->vrf_id);
-
- static_fixup_vrf_ids(svrf);
- }
-
/* Install any static reliant on this interface coming up */
static_install_intf_nh(ifp);
static_ifindex_update(ifp, true);
diff --git a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
index 7b9ef0a505..982a076bfb 100644
--- a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
+++ b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
#
# test_bgp_ecmp_topo1.py
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/__init__.py b/tests/topotests/bgp_extended_optional_parameters_length/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/__init__.py
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf b/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf
new file mode 100644
index 0000000000..d83013ca99
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 extended-optional-parameters
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf b/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf
new file mode 100644
index 0000000000..b29940f46a
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf b/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf
new file mode 100644
index 0000000000..e390d6ed8d
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf
@@ -0,0 +1,8 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 extended-optional-parameters
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf b/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf
new file mode 100644
index 0000000000..dc15cf756a
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ip address 172.16.16.1/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
new file mode 100644
index 0000000000..e677dc6ff6
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@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 if Extended Optional Parameters Length encoding format works
+if forced with a knob.
+https://datatracker.ietf.org/doc/html/rfc9072
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+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
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_extended_optional_parameters_length():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json"))
+ expected = {
+ "peers": {
+ "192.168.1.2": {
+ "pfxRcd": 2,
+ "pfxSnt": 2,
+ "state": "Established",
+ "peerState": "OK",
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, router)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't converge with extended-optional-parameters"
+
+ def _bgp_extended_optional_parameters_length(router):
+ output = json.loads(router.vtysh_cmd("show bgp neighbor 192.168.1.2 json"))
+ expected = {"192.168.1.2": {"extendedOptionalParametersLength": True}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_extended_optional_parameters_length, router)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't see Extended Optional Parameters Length to be used"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py
new file mode 100644
index 0000000000..290bf16fea
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py
@@ -0,0 +1,1542 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Gracefull Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 2 routers topology, r1, r2 in IBGP
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Garceful Restart on both the routers.
+
+1. Transition from Peer-level helper to Global Restarting
+2. Transition from Peer-level helper to Global inherit helper
+3. Transition from Peer-level restarting to Global inherit helper
+4. Default GR functional mode is Helper.
+5. Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+6. Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting
+ mode is enabled. Here link flap happen due to interface UP/DOWN.
+7. Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+8. Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+9. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+10. Verify that GR helper routers keeps all the routes received
+ from restarting node if both the routers are configured as
+ GR restarting node.
+11. Verify that GR helper routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node.
+12. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+13. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+14. Verify that restarting nodes reset "F" bit while sending
+ the BGP open messages after it's restarts, when BGP GR is **NOT** enabled.
+15. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+16. Transition from Global Restarting to Disable and then Global
+ Disable to Restarting.
+17. Transition from Global Helper to Disable and then Global
+ Disable to Helper.
+18. Transition from Global Restart to Helper and then Global
+ Helper to Restart, Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+19. Transition from Peer-level helper to Global Restarting,
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+20. Transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+21. Transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+22. Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+23. Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
+"""
+
+import os
+import sys
+import time
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ shutdown_bringup_interface,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"}
+NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"}
+NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"}
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 20
+PREFERRED_NEXT_HOP = "link_local"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global ADDR_TYPES
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(
+ tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
+):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in preferred_next_hop:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def BGP_GR_TC_50_p1(request):
+ """
+ Test Objective : Transition from Peer-level helper to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : Helper
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR helper node at per Peer-level for R2"
+ " and configure R2 as global restarting node."
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a helper node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bring up BGP on R2 and remove Peer-level GR config from R1 ")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R2 that R1 still advertises GR capabilities as a helper node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_51_p1(request):
+ """
+ Test Objective : Transition from Peer-level restarting to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Restart
+ GR Mode effective : GR Restart
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 as GR restarting node at per Peer-level for R2")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB & R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bring up BGP on R1 and remove Peer-level GR config")
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R2 that R1 advertises GR capabilities as a helper node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGPd on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_53_p1(request):
+ """
+ Test Objective : Default GR functional mode is Helper.
+ Global Mode : None
+ PerPeer Mode : None
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("configure R2 as global restarting node")
+
+ input_dict = {"r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}}
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step(
+ "Verify on R2 that R1 advertises GR capabilities as a helper node based on inherit"
+ )
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGPd on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_4_p0(request):
+ """
+ Test Objective : Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Helper Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : R2 goes for reload ")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info(
+ "[Phase 3] : R2 is still down, restart time {} sec."
+ "So time verify the routes are present in BGP RIB and ZEBRA ".format(
+ GR_RESTART_TIMER
+ )
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Phase 5] : R2 is about to come up now ")
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_5_1_2_p1(request):
+ """
+ Test Objective : Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting mode is enabled.
+ Here link flap happen due to interface UP/DOWN.
+
+ """
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : Now flap the link running the BGP session ")
+ # Shutdown interface
+ intf = "r2-r1-eth0"
+ shutdown_bringup_interface(tgen, "r2", intf)
+
+ # Bring up Interface
+ shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : Restart BGPd on router R2. ")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_6_1_2_p1(request):
+ """
+ Test Objective : Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" "[Restart Mode]R1-----R2[Helper Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 1] : Changing mode" "[Disable Mode]R1-----R2[Helper Mode]")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ # Verify GR stats
+ input_dict = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ # here the verify_graceful_restart fro the neighbor would be
+ # "NotReceived" as the latest GR config is not yet applied.
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : Now flap the link running the BGP session ")
+ # Shutdown interface
+ intf = "r2-r1-eth0"
+ shutdown_bringup_interface(tgen, "r2", intf)
+
+ # Bring up Interface
+ shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info("Restart BGPd on R2 ")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py
new file mode 100644
index 0000000000..0647ad5d06
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py
@@ -0,0 +1,404 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Gracefull Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 2 routers topology, r1, r2 in IBGP
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Garceful Restart on both the routers.
+
+1. Transition from Peer-level helper to Global Restarting
+2. Transition from Peer-level helper to Global inherit helper
+3. Transition from Peer-level restarting to Global inherit helper
+4. Default GR functional mode is Helper.
+5. Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+6. Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting
+ mode is enabled. Here link flap happen due to interface UP/DOWN.
+7. Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+8. Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+9. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+10. Verify that GR helper routers keeps all the routes received
+ from restarting node if both the routers are configured as
+ GR restarting node.
+11. Verify that GR helper routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node.
+12. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+13. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+14. Verify that restarting nodes reset "F" bit while sending
+ the BGP open messages after it's restarts, when BGP GR is **NOT** enabled.
+15. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+16. Transition from Global Restarting to Disable and then Global
+ Disable to Restarting.
+17. Transition from Global Helper to Disable and then Global
+ Disable to Helper.
+18. Transition from Global Restart to Helper and then Global
+ Helper to Restart, Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+19. Transition from Peer-level helper to Global Restarting,
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+20. Transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+21. Transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+22. Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+23. Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
+"""
+
+import os
+import sys
+import time
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ shutdown_bringup_interface,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"}
+NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"}
+NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"}
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 20
+PREFERRED_NEXT_HOP = "link_local"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global ADDR_TYPES
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(
+ tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
+):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in preferred_next_hop:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_TC_8_p1(request):
+ """
+ Test Objective : Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"preserve-fw-state": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : R1 goes for reload ")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Phase 3] : R1 is about to come up now ")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_f_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py
index 56f6e1a3be..0c3ff6451e 100644
--- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py
@@ -85,6 +85,9 @@ Basic Common Test steps for all the test case below :
Global Mode : None
PerPeer Mode : GR Disable
GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
"""
import os
@@ -519,1165 +522,6 @@ def BGP_GR_TC_50_p1(request):
write_test_footer(tc_name)
-def test_BGP_GR_TC_51_p1(request):
- """
- Test Objective : Transition from Peer-level restarting to Global inherit helper
- Global Mode : None
- PerPeer Mode : GR Restart
- GR Mode effective : GR Restart
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Configure R1 as GR restarting node at per Peer-level for R2")
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB & R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Bring up BGP on R1 and remove Peer-level GR config")
-
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
-
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- step("Verify on R2 that R1 advertises GR capabilities as a helper node")
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGPd on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Start BGP on R2")
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_53_p1(request):
- """
- Test Objective : Default GR functional mode is Helper.
- Global Mode : None
- PerPeer Mode : None
- GR Mode effective : GR Helper
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("configure R2 as global restarting node")
-
- input_dict = {"r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}}
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step(
- "Verify on R2 that R1 advertises GR capabilities as a helper node based on inherit"
- )
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGPd on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Start BGP on R2")
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_4_p0(request):
- """
- Test Objective : Verify that the restarting node sets "R" bit while sending the
- BGP open messages after the node restart, only if GR is enabled.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Helper Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : R2 goes for reload ")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info(
- "[Phase 3] : R2 is still down, restart time {} sec."
- "So time verify the routes are present in BGP RIB and ZEBRA ".format(
- GR_RESTART_TIMER
- )
- )
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(
- tgen, addr_type, dut, input_topo, next_hop, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Phase 5] : R2 is about to come up now ")
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_5_1_2_p1(request):
- """
- Test Objective : Verify if restarting node resets R bit in BGP open message
- during normal BGP session flaps as well, even when GR restarting mode is enabled.
- Here link flap happen due to interface UP/DOWN.
-
- """
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : Now flap the link running the BGP session ")
- # Shutdown interface
- intf = "r2-r1-eth0"
- shutdown_bringup_interface(tgen, "r2", intf)
-
- # Bring up Interface
- shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : Restart BGPd on router R2. ")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_6_1_2_p1(request):
- """
- Test Objective : Verify if restarting node resets R bit in BGP
- open message during normal BGP session flaps when GR is disabled.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" "[Restart Mode]R1-----R2[Helper Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 1] : Changing mode" "[Disable Mode]R1-----R2[Helper Mode]")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
-
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- # Verify GR stats
- input_dict = {
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- # here the verify_graceful_restart fro the neighbor would be
- # "NotReceived" as the latest GR config is not yet applied.
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : Now flap the link running the BGP session ")
- # Shutdown interface
- intf = "r2-r1-eth0"
- shutdown_bringup_interface(tgen, "r2", intf)
-
- # Bring up Interface
- shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
- tc_name, result
- )
-
- logger.info("Restart BGPd on R2 ")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_8_p1(request):
- """
- Test Objective : Verify that restarting nodes set "F" bit while sending
- the BGP open messages after it restarts, only when BGP GR is enabled.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"preserve-fw-state": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : R1 goes for reload ")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Phase 3] : R1 is about to come up now ")
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_f_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
def test_BGP_GR_TC_19_p1(request):
"""
Test Objective : Verify that GR helper routers keeps all the routes received
@@ -3904,1165 +2748,6 @@ def test_BGP_GR_TC_45_p1(request):
write_test_footer(tc_name)
-def test_BGP_GR_TC_46_p1(request):
- """
- Test Objective : transition from Peer-level helper to Global Restarting
- Global Mode : GR Restarting
- PerPeer Mode : GR Helper
- GR Mode effective : GR Helper
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step(
- "Configure R1 and R2 as GR restarting node in global"
- " and helper in per-Peer-level"
- )
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step(
- "Bring up BGP on R1 and remove Peer-level GR config"
- " from R1 following by a session reset"
- )
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_47_p1(request):
- """
- Test Objective : transition from Peer-level restart to Global Restart
- Global Mode : GR Restarting
- PerPeer Mode : GR Restarting
- GR Mode effective : GR Restarting
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Configure R1 and R2 as GR restarting node in global and per-Peer-level")
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step(
- "Bring up BGP on R1 and remove Peer-level GR"
- " config from R1 following by a session reset"
- )
-
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 still advertises GR capabilities as a restarting node")
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_48_p1(request):
- """
- Test Objective : transition from Peer-level disabled to Global Restart
- Global Mode : GR Restarting
- PerPeer Mode : GR Disabled
- GR Mode effective : GR Disabled
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step(
- "Configure R1 as GR restarting node in global level and"
- " GR Disabled in per-Peer-level"
- )
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 does't advertise any GR capabilities")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step("Verify on R2 and R1 that none of the routers keep stale entries")
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(
- tgen, addr_type, dut, input_topo, next_hop, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- step("Bring up BGP on R1 and remove Peer-level GR config from R1")
-
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_49_p1(request):
- """
- Test Objective : Peer-level inherit from Global Restarting
- Global Mode : GR Restart
- PerPeer Mode : None
- GR Mode effective : GR Restart
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Configure R1 as GR restarting node in global level")
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step(
- "Verify that R2 receives GR restarting capabilities"
- " from R1 based on inheritence"
- )
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGPd on router R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def BGP_GR_TC_52_p1(request):
- """
- Test Objective : Transition from Peer-level disbale to Global inherit helper
- Global Mode : None
- PerPeer Mode : GR Disable
- GR Mode effective : GR Disable
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step(
- "Configure R1 as GR disabled node at per Peer-level for R2"
- " & R2 as GR restarting node"
- )
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 does't advertise any GR capabilities")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 doesn't keep RIB & FIB entries."
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(
- tgen, addr_type, dut, input_topo, next_hop, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- step("Bring up BGP on R2 and remove Peer-level GR config from R1")
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step(
- "Verify on R2 that R1 advertises GR capabilities as a helper node from global inherit"
- )
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
new file mode 100644
index 0000000000..791ca37eae
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
@@ -0,0 +1,1686 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Gracefull Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 2 routers topology, r1, r2 in IBGP
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Garceful Restart on both the routers.
+
+1. Transition from Peer-level helper to Global Restarting
+2. Transition from Peer-level helper to Global inherit helper
+3. Transition from Peer-level restarting to Global inherit helper
+4. Default GR functional mode is Helper.
+5. Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+6. Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting
+ mode is enabled. Here link flap happen due to interface UP/DOWN.
+7. Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+8. Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+9. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+10. Verify that GR helper routers keeps all the routes received
+ from restarting node if both the routers are configured as
+ GR restarting node.
+11. Verify that GR helper routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node.
+12. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+13. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+14. Verify that restarting nodes reset "F" bit while sending
+ the BGP open messages after it's restarts, when BGP GR is **NOT** enabled.
+15. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+16. Transition from Global Restarting to Disable and then Global
+ Disable to Restarting.
+17. Transition from Global Helper to Disable and then Global
+ Disable to Helper.
+18. Transition from Global Restart to Helper and then Global
+ Helper to Restart, Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+19. Transition from Peer-level helper to Global Restarting,
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+20. Transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+21. Transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+22. Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+23. Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
+"""
+
+import os
+import sys
+import time
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ shutdown_bringup_interface,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"}
+NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"}
+NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"}
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 20
+PREFERRED_NEXT_HOP = "link_local"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global ADDR_TYPES
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(
+ tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
+):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in preferred_next_hop:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def BGP_GR_TC_50_p1(request):
+ """
+ Test Objective : Transition from Peer-level helper to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : Helper
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR helper node at per Peer-level for R2"
+ " and configure R2 as global restarting node."
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a helper node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bring up BGP on R2 and remove Peer-level GR config from R1 ")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R2 that R1 still advertises GR capabilities as a helper node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_46_p1(request):
+ """
+ Test Objective : transition from Peer-level helper to Global Restarting
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 and R2 as GR restarting node in global"
+ " and helper in per-Peer-level"
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step(
+ "Bring up BGP on R1 and remove Peer-level GR config"
+ " from R1 following by a session reset"
+ )
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_47_p1(request):
+ """
+ Test Objective : transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 and R2 as GR restarting node in global and per-Peer-level")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step(
+ "Bring up BGP on R1 and remove Peer-level GR"
+ " config from R1 following by a session reset"
+ )
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 still advertises GR capabilities as a restarting node")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_48_p1(request):
+ """
+ Test Objective : transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR restarting node in global level and"
+ " GR Disabled in per-Peer-level"
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 does't advertise any GR capabilities")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step("Verify on R2 and R1 that none of the routers keep stale entries")
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ step("Bring up BGP on R1 and remove Peer-level GR config from R1")
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_49_p1(request):
+ """
+ Test Objective : Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 as GR restarting node in global level")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step(
+ "Verify that R2 receives GR restarting capabilities"
+ " from R1 based on inheritence"
+ )
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGPd on router R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def BGP_GR_TC_52_p1(request):
+ """
+ Test Objective : Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR disabled node at per Peer-level for R2"
+ " & R2 as GR restarting node"
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 does't advertise any GR capabilities")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 doesn't keep RIB & FIB entries."
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ step("Bring up BGP on R2 and remove Peer-level GR config from R1")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step(
+ "Verify on R2 that R1 advertises GR capabilities as a helper node from global inherit"
+ )
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py
new file mode 100644
index 0000000000..064fde1633
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py
@@ -0,0 +1,1515 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_TC_1_2_p0(request):
+ """
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "Verify EOR Sent and Received : BGP_GR_TC_1_2 >> "
+ "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R3
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("R1 goes for reload")
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("Starting bgpd process")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+ logger.info("R1 is UP Now")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R3
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying EOR on restarting router
+ result = verify_eor(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_3_p0(request):
+ """
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Verify route download to RIB: BGP_GR_TC_3 >> "
+ "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "disable-eor": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ "timer": {"select-defer-time": GR_SELECT_DEFER_TIMER},
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r2"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("R2 goes for reload ")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info("R2 is about to come up now")
+ start_router_daemons(tgen, "r2", ["bgpd"])
+ logger.info("R2 is UP Now")
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes received from router R1
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify EOR on restarting router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER)
+ )
+ sleep(GR_SELECT_DEFER_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, "r2", input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_11_p0(request):
+ """
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+ selection process is deferred, after a peer session was restarted
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info("Verify EOR Sent after deferral timeout : BGP_GR_TC_11")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "select-defer-time": GR_SELECT_DEFER_TIMER,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "graceful-restart": {"disable-eor": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r1")
+ clear_bgp(tgen, addr_type, "r3")
+
+ result = verify_bgp_convergence_from_running_config(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("R1 goes for reload")
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("Starting bgpd process")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+ logger.info("R1 is UP Now")
+
+ for addr_type in ADDR_TYPES:
+ # Verify EOR on restarting router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "Waiting for selection deferral timer({} sec).. ".format(
+ GR_SELECT_DEFER_TIMER + 2
+ )
+ )
+ sleep(GR_SELECT_DEFER_TIMER + 2)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes received from router R1
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying EOR on restarting router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_10_p2(request):
+ """
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Test Setup: [Helper Mode]R3-----R1[Restart Mode] initialized")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "next_hop_self": True,
+ "graceful-restart": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "next_hop_self": True,
+ "graceful-restart": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ step(
+ "Verifying GR config and operational state for addr_type {}".format(
+ addr_type
+ )
+ )
+
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Killing bgpd on r1")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Starting bgpd on r1")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def BGP_GR_16_p2(request):
+ """
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Helper Mode]R3-----R1[Restart Mode]"
+ "--------R6[Helper Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_bgp_convergence_from_running_config(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_18_p1(request):
+ """
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+ restarting node's OPEN message.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r6": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Helper Mode]R6-----R1[Restart Mode]"
+ "--------R2[Helper Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r2"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Configure R1 to prevent sending EOR")
+
+ # Modify graceful-restart config to prevent sending EOR
+ input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+
+ # Modify configuration to delete routes
+ network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Modify graceful-restart config
+ input_dict_3 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
+
+ logger.info("[Step 4] : Bring up the BGPd daemon on R1 for 30" " seconds..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes
+ dut = "r2"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py
new file mode 100644
index 0000000000..4356c4d591
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py
@@ -0,0 +1,1216 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_26_p2(request):
+ """
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r1"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_28_p1(request):
+ """
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+ till SDT expiry.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "Test Case: test_BGP_GR_chaos_28 :"
+ "[Helper Mode]R3-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 1] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 2] : Kill BGPd daemon on R3..")
+
+ # Kill BGPd daemon on R3
+ kill_router_daemons(tgen, "r3", ["bgpd"])
+
+ logger.info("[Step 3] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 4] : Start BGPd daemon on R3..")
+
+ # Start BGPd daemon on R3
+ start_router_daemons(tgen, "r3", ["bgpd"])
+
+ # Verify r_bit
+ for addr_type in ADDR_TYPES:
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_29_p1(request):
+ """
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_29"
+ " BGP GR [Helper Mode]R3-----R1[Restart Mode]"
+ " and [restart-time 150]R1 initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify graceful-restart timers
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}}
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}
+ }
+ }
+ }
+
+ result = verify_graceful_restart_timers(
+ tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ dut = "r3"
+ input_dict = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER))
+
+ # Waiting for GR_RESTART_TIMER
+ sleep(GR_RESTART_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ input_dict = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Step 4] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_33_p1(request):
+ """
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+ stale entry only for GR-restarting node(next-hop is correct).
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_33 "
+ "BGP GR "
+ "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r4": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Advertise same networks from R1 and R4..")
+
+ # Api call to delete advertised networks
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": "200.0.20.1/32",
+ "no_of_network": 2,
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": "2001::1/128", "no_of_network": 2}
+ ]
+ }
+ },
+ }
+ }
+ },
+ "r4": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": "200.0.20.1/32", "no_of_network": 2}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": "2001::1/128", "no_of_network": 2}
+ ]
+ }
+ },
+ }
+ }
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ dut = "r3"
+ peer1 = "r1"
+ peer2 = "r4"
+ intf1 = topo["routers"][peer1]["links"][dut]["interface"]
+ intf2 = topo["routers"][peer2]["links"][dut]["interface"]
+
+ if addr_type == "ipv4":
+ next_hop_4 = NEXT_HOP_4
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ if addr_type == "ipv6":
+ if "link_local" in PREFERRED_NEXT_HOP:
+ next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
+ next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
+
+ next_hop_6 = [next_hop1, next_hop2]
+ else:
+ next_hop_6 = NEXT_HOP_6
+
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Kill BGPd daemon on R4
+ kill_router_daemons(tgen, "r4", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ next_hop_6 = ["fd00:0:0:1::1"]
+ if addr_type == "ipv4":
+ next_hop_4 = NEXT_HOP_4[0]
+
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ if addr_type == "ipv6":
+ if "link_local" in PREFERRED_NEXT_HOP:
+ next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
+ else:
+ next_hop_6 = NEXT_HOP_6[0]
+
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
+
+ # Verifying RIB routes
+ if addr_type == "ipv4":
+ next_hop_4 = NEXT_HOP_4[1]
+ result = verify_rib(
+ tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ if addr_type == "ipv6":
+ if "link_local" in PREFERRED_NEXT_HOP:
+ next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
+ else:
+ next_hop_6 = NEXT_HOP_6[1]
+
+ result = verify_rib(
+ tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Start BGPd daemon on R4
+ start_router_daemons(tgen, "r4", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_34_2_p1(request):
+ """
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+ stale routes.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_34 "
+ "BGP GR "
+ "[Restart Mode]R1---R3[Helper Mode]"
+ )
+
+ logger.info("[Step 1] : Configure restarting" " router R1 to prevent ")
+ logger.info("[Step 2] : Reset the session" " between R1 and R3..")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"preserve-fw-state": True, "disable-eor": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify f-bit before killing BGPd daemon
+ result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..")
+
+ # Api call to delete advertised networks
+ network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..")
+
+ # Modify graceful-restart config not to set f-bit
+ # and write to /etc/frr
+ input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
+
+ logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verify f-bit after starting BGPd daemon
+ result = verify_f_bit(
+ tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
new file mode 100644
index 0000000000..86d676dd8b
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
@@ -0,0 +1,1367 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_chaos_34_1_p1(request):
+ """
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_31 "
+ "BGP GR "
+ "[Restart Mode]R1---R3[Helper Mode]"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "preserve-fw-state": True,
+ "timer": {"restart-time": GR_RESTART_TIMER},
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 1] : Remove the preserve-fw-state command"
+ " from restarting node R1's config"
+ )
+
+ # Configure graceful-restart to set f-bit as False
+ input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ logger.info("[Step 2] : Reset the session between R1 and R3..")
+
+ # Reset sessions
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r1")
+
+ result = verify_bgp_convergence_from_running_config(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Verify f-bit after starting BGPd daemon
+ result = verify_f_bit(
+ tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Waiting for GR_RESTART_TIMER
+ logger.info("Waiting for {} sec..".format(GR_RESTART_TIMER))
+ sleep(GR_RESTART_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_dict = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_32_p1(request):
+ """
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+ that only after SDT restarting node send EOR to all helper peers
+ excluding the prefixes originated by faulty router.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_32 "
+ "BGP GR "
+ "[Restart Mode]R1---R3&R5[Helper Mode]"
+ )
+
+ logger.info(
+ "[Step 1] : Change the mode on R1 be a restarting" " node on global level"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"graceful-restart": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
+ "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
+ "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ },
+ }
+ },
+ "r5": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r5": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r5": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r5")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r5"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Kill BGPd daemon on R1..")
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Withdraw all the advertised prefixes from R5")
+
+ # Api call to delete advertised networks
+ network = {"ipv4": "105.0.20.1/32", "ipv6": "5::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r5": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 4] : Stop the helper router R5 from sending EOR" " message using CLI"
+ )
+
+ # Modify graceful-restart config to prevent sending EOR
+ input_dict_3 = {"r5": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = create_router_bgp(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ logger.info("[Step 5] : Bring up the BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verify EOR is disabled
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_37_p1(request):
+ """
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+ expiry to do the best path selection and sends an EOR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_37 "
+ "BGP GR "
+ "[Restart Mode]R1---R3[Helper Mode]"
+ )
+
+ logger.info(
+ "[Step 1] : Configure restarting router R3 to prevent " "sending an EOR.."
+ )
+
+ logger.info("[Step 2] : Reset the session between R3 and R1..")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "graceful-restart": {"disable-eor": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify EOR is disabled
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 4] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 5] : Kill BGPd daemon on R3..")
+
+ # Kill BGPd daemon on R3
+ kill_router_daemons(tgen, "r3", ["bgpd"])
+
+ # Modify graceful-restart config to prevent sending EOR
+ input_dict_2 = {"r3": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
+
+ logger.info("[Step 6] : Start BGPd daemon on R3..")
+
+ # Start BGPd daemon on R3
+ start_router_daemons(tgen, "r3", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verify r_bit
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r3")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify EOR is send from R1 to R3
+ input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_30_p1(request):
+ """
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_30 "
+ "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"preserve-fw-state": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ dut = "r1"
+ input_dict = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Withdraw advertised prefixes from R3...")
+
+ # Api call to delete advertised networks
+ network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 4] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ input_dict = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_15_p2(request):
+ """
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r6": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Helper Mode]R6-----R1[Restart Mode]"
+ "--------R2[Helper Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def BGP_GR_TC_7_p1(request):
+ """
+ Verify that BGP restarting node deletes all the routes received from peer
+ if BGP Graceful capability is not present in BGP Open message from the
+ peer
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Verify route download to RIB: BGP_GR_TC_7 >> "
+ "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("R1 goes for reload")
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Change the configuration on router R1
+ input_dict_2 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ # Change the configuration on R1
+ network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("R1 is about to come up now")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+ logger.info("R1 is UP Now")
+
+ # Wait for RIB stale timeout
+ logger.info("Verify routes are not present" "in restart router")
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
new file mode 100644
index 0000000000..889f47f377
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
@@ -0,0 +1,1024 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
+# in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+These tests have been broken up into 4 sub python scripts because
+the totality of run time for this script was greater than 10 minutes
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_TC_23_p1(request):
+ """
+ Verify that helper routers are deleting stale routes after stale route
+ timer's expiry. If all the routes are not received from restating node
+ after restart.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "Verify Stale Routes are deleted on helper: BGP_GR_TC_23 >> "
+ "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"stalepath-time": GR_STALEPATH_TIMER}},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("R2 goes for reload")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ # Modify configuration to delete routes and include disable-eor
+ input_dict_3 = {"r2": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+
+ # Modify configuration to delete routes and include disable-eor
+ network = {"ipv4": "102.0.20.1/32", "ipv6": "2::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 3,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("BGPd comes up for r2")
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ # Wait for stalepath timer
+ logger.info("Waiting for stalepath timer({} sec..)".format(GR_STALEPATH_TIMER))
+ sleep(GR_STALEPATH_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r2")
+
+ # Verifying RIB routes
+ dut = "r1"
+ network = {"ipv4": "102.0.20.4/32", "ipv6": "2::4/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {"network": network[addr_type], "no_of_network": 2}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ # Verify EOR on helper router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_20_p1(request):
+ """
+ Test Objective : Verify that GR routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_21_p2(request):
+ """
+ Test Objective : VVerify BGP-GR feature when helper node is
+ a transit router for it's eBGP peers.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r6": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
+ "--------R6[Helper Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes after bringing up BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_22_p2(request):
+ """
+ Test Objective : Verify BGP-GR feature when helper node
+ is a transit router for it's iBGP peers.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart-disable": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart-disable": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
+ "--------R3[Helper Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
deleted file mode 100644
index 52ad7813c5..0000000000
--- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
+++ /dev/null
@@ -1,4358 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2019 by VMware, Inc. ("VMware")
-# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF")
-# in this file.
-#
-# 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 VMWARE DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
-#
-
-"""
-Following tests are covered to test BGP Graceful Restart functionality.
-Basic Common Test steps for all the test case below :
-- Create topology (setup module)
- Creating 7 routers topology
-- Bring up topology
-- Verify for bgp to converge
-- Configure BGP Graceful Restart on both the routers.
-
-TC_1_2:
- Verify that EOR message is sent out only after initial convergence
- Verify whether EOR message is received from all the peers after restart
-TC_3:
- Verify the selection deferral timer functionality when EOR is not sent
- by the helper router
-TC_11:
- Verify that selection-deferral timer sets the maximum time to
- avoid deadlock during which the best-path
-TC_10:
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
-TC_15:
- Test Objective : Test GR scenarios by enabling Graceful Restart
- for multiple address families..
-TC_16:
- Test Objective : Verify BGP-GR feature when restarting node
- is a transit router for it's iBGP peers.
-TC_18:
- Test Objective : Verify that GR helper router deletes stale routes
- received from restarting node, if GR capability is not present in
-TC_19:
- Test Objective : Verify that GR routers keeps all the routes
- received from restarting node if both the routers are
-TC_26:
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
-TC_28:
- Test Objective : Verify if helper node goes down before restarting
- node comes up online, helper node sets the R-bit to avoid dead-lock
-TC_29:
- Test Objective : Change timers on the fly, and
- verify if it takes immediate effect.
-TC_33:
- Test Objective : Helper router receives same prefixes from two
- different routers (GR-restarting and GR-disabled). Keeps the
-TC_34_1:
- Test Objective : Restarting node doesn't preserve forwarding
- state, helper router should not keep the stale entries.
-TC_34_2:
- Test Objective : Restarting node doesn't preserve the forwarding
- state verify the behaviour on helper node, if it still keeps the
-TC_32:
- Test Objective : Restarting node is connected to multiple helper
- nodes, one of them doesn't send EOR to restarting router. Verify
-TC_37:
- Test Objective : Verify if helper node restarts before sending the
- EOR message, restarting node doesn't wait until stale path timer
-TC_30:
- Test Objective : Restarting node removes stale routes from Zebra
- after receiving an EOR from helper router.
-
-"""
-
-import os
-import sys
-import time
-import pytest
-from time import sleep
-
-# Save the Current Working Directory to find configuration files.
-CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join("../"))
-sys.path.append(os.path.join("../lib/"))
-
-# pylint: disable=C0413
-# Import topogen and topotest helpers
-from lib.topogen import Topogen, get_topogen
-from lib.topolog import logger
-
-# Required to instantiate the topology builder class.
-
-# Import topoJson from lib, to create topology and initial configuration
-from lib.topojson import build_config_from_json
-from lib.bgp import (
- clear_bgp,
- verify_bgp_rib,
- verify_graceful_restart,
- create_router_bgp,
- verify_r_bit,
- verify_eor,
- verify_f_bit,
- verify_bgp_convergence,
- verify_gr_address_family,
- modify_bgp_config_when_bgpd_down,
- verify_graceful_restart_timers,
- verify_bgp_convergence_from_running_config,
-)
-
-from lib.common_config import (
- write_test_header,
- reset_config_on_routers,
- start_topology,
- kill_router_daemons,
- start_router_daemons,
- verify_rib,
- check_address_types,
- write_test_footer,
- check_router_status,
- step,
- get_frr_ipv6_linklocal,
- required_linux_kernel_version,
-)
-
-pytestmark = [pytest.mark.bgpd]
-
-
-# Global variables
-BGP_CONVERGENCE = False
-GR_RESTART_TIMER = 5
-GR_SELECT_DEFER_TIMER = 5
-GR_STALEPATH_TIMER = 5
-PREFERRED_NEXT_HOP = "link_local"
-NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
-NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
-
-
-def setup_module(mod):
- """
- Sets up the pytest environment
-
- * `mod`: module name
- """
-
- # Required linux kernel version for this suite to run.
- result = required_linux_kernel_version("4.16")
- if result is not True:
- pytest.skip("Kernel requirements are not met")
-
- global ADDR_TYPES
-
- testsuite_run_time = time.asctime(time.localtime(time.time()))
- logger.info("Testsuite start time: {}".format(testsuite_run_time))
- logger.info("=" * 40)
-
- logger.info("Running setup_module to create topology")
-
- # This function initiates the topology build with Topogen...
- json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
- tgen = Topogen(json_file, mod.__name__)
- global topo
- topo = tgen.json_topo
- # ... and here it calls Mininet initialization functions.
-
- # Starting topology, create tmp files which are loaded to routers
- # to start deamons and then start routers
- start_topology(tgen)
-
- # Creating configuration from JSON
- build_config_from_json(tgen, topo)
-
- # Api call verify whether BGP is converged
- ADDR_TYPES = check_address_types()
-
- for addr_type in ADDR_TYPES:
- BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error:" " {}".format(
- BGP_CONVERGENCE
- )
-
- logger.info("Running setup_module() done")
-
-
-def teardown_module(mod):
- """
- Teardown the pytest environment
-
- * `mod`: module name
- """
-
- logger.info("Running teardown_module to delete topology")
-
- tgen = get_topogen()
-
- # Stop toplogy and Remove tmp files
- tgen.stop_topology()
-
- logger.info(
- "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
- )
- logger.info("=" * 40)
-
-
-def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
- """
- This function groups the repetitive function calls into one function.
- """
-
- logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
-
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- return True
-
-
-def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
- """
- This function returns link_local or global next_hop per address-family
- """
-
- intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
- if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
- next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
- else:
- next_hop = next_hop_dict[addr_type]
-
- return next_hop
-
-
-def test_BGP_GR_TC_1_2_p0(request):
- """
- Verify that EOR message is sent out only after initial convergence
- Verify whether EOR message is received from all the peers after restart
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "Verify EOR Sent and Received : BGP_GR_TC_1_2 >> "
- "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R3
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("R1 goes for reload")
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("Starting bgpd process")
- start_router_daemons(tgen, "r1", ["bgpd"])
- logger.info("R1 is UP Now")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R3
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying EOR on restarting router
- result = verify_eor(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_3_p0(request):
- """
- Verify the selection deferral timer functionality when EOR is not sent
- by the helper router
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Verify route download to RIB: BGP_GR_TC_3 >> "
- "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "disable-eor": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- "timer": {"select-defer-time": GR_SELECT_DEFER_TIMER},
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R1
- dut = "r2"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("R2 goes for reload ")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info("R2 is about to come up now")
- start_router_daemons(tgen, "r2", ["bgpd"])
- logger.info("R2 is UP Now")
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes received from router R1
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify EOR on restarting router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- logger.info(
- "Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER)
- )
- sleep(GR_SELECT_DEFER_TIMER)
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, "r2", input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_11_p0(request):
- """
- Verify that selection-deferral timer sets the maximum time to
- avoid deadlock during which the best-path
- selection process is deferred, after a peer session was restarted
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info("Verify EOR Sent after deferral timeout : BGP_GR_TC_11")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "select-defer-time": GR_SELECT_DEFER_TIMER,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "graceful-restart": {"disable-eor": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
- clear_bgp(tgen, addr_type, "r3")
-
- result = verify_bgp_convergence_from_running_config(tgen, topo)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("R1 goes for reload")
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("Starting bgpd process")
- start_router_daemons(tgen, "r1", ["bgpd"])
- logger.info("R1 is UP Now")
-
- for addr_type in ADDR_TYPES:
- # Verify EOR on restarting router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- logger.info(
- "Waiting for selection deferral timer({} sec).. ".format(
- GR_SELECT_DEFER_TIMER + 2
- )
- )
- sleep(GR_SELECT_DEFER_TIMER + 2)
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes received from router R1
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying EOR on restarting router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_10_p2(request):
- """
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Test Setup: [Helper Mode]R3-----R1[Restart Mode] initialized")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "next_hop_self": True,
- "graceful-restart": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "next_hop_self": True,
- "graceful-restart": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- step(
- "Verifying GR config and operational state for addr_type {}".format(
- addr_type
- )
- )
-
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Killing bgpd on r1")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Starting bgpd on r1")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def BGP_GR_16_p2(request):
- """
- Test Objective : Verify BGP-GR feature when restarting node
- is a transit router for it's iBGP peers.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Helper Mode]R3-----R1[Restart Mode]"
- "--------R6[Helper Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_bgp_convergence_from_running_config(tgen, topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_18_p1(request):
- """
- Test Objective : Verify that GR helper router deletes stale routes
- received from restarting node, if GR capability is not present in
- restarting node's OPEN message.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r6": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Helper Mode]R6-----R1[Restart Mode]"
- "--------R2[Helper Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r2"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Configure R1 to prevent sending EOR")
-
- # Modify graceful-restart config to prevent sending EOR
- input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
-
- # Modify configuration to delete routes
- network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_3 = {
- "r1": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Modify graceful-restart config
- input_dict_3 = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- }
- }
- },
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
-
- logger.info("[Step 4] : Bring up the BGPd daemon on R1 for 30" " seconds..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r6: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes
- dut = "r2"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_26_p2(request):
- """
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r3", peer="r1"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_28_p1(request):
- """
- Test Objective : Verify if helper node goes down before restarting
- node comes up online, helper node sets the R-bit to avoid dead-lock
- till SDT expiry.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "Test Case: test_BGP_GR_chaos_28 :"
- "[Helper Mode]R3-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 1] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 2] : Kill BGPd daemon on R3..")
-
- # Kill BGPd daemon on R3
- kill_router_daemons(tgen, "r3", ["bgpd"])
-
- logger.info("[Step 3] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 4] : Start BGPd daemon on R3..")
-
- # Start BGPd daemon on R3
- start_router_daemons(tgen, "r3", ["bgpd"])
-
- # Verify r_bit
- for addr_type in ADDR_TYPES:
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_29_p1(request):
- """
- Test Objective : Change timers on the fly, and
- verify if it takes immediate effect.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_29"
- " BGP GR [Helper Mode]R3-----R1[Restart Mode]"
- " and [restart-time 150]R1 initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify graceful-restart timers
- input_dict_2 = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}}
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}
- }
- }
- }
-
- result = verify_graceful_restart_timers(
- tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- dut = "r3"
- input_dict = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER))
-
- # Waiting for GR_RESTART_TIMER
- sleep(GR_RESTART_TIMER)
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- input_dict = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Step 4] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_33_p1(request):
- """
- Test Objective : Helper router receives same prefixes from two
- different routers (GR-restarting and GR-disabled). Keeps the
- stale entry only for GR-restarting node(next-hop is correct).
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_33 "
- "BGP GR "
- "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r4": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Advertise same networks from R1 and R4..")
-
- # Api call to delete advertised networks
- input_dict_2 = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "advertise_networks": [
- {
- "network": "200.0.20.1/32",
- "no_of_network": 2,
- }
- ]
- }
- },
- "ipv6": {
- "unicast": {
- "advertise_networks": [
- {"network": "2001::1/128", "no_of_network": 2}
- ]
- }
- },
- }
- }
- },
- "r4": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "advertise_networks": [
- {"network": "200.0.20.1/32", "no_of_network": 2}
- ]
- }
- },
- "ipv6": {
- "unicast": {
- "advertise_networks": [
- {"network": "2001::1/128", "no_of_network": 2}
- ]
- }
- },
- }
- }
- },
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- dut = "r3"
- peer1 = "r1"
- peer2 = "r4"
- intf1 = topo["routers"][peer1]["links"][dut]["interface"]
- intf2 = topo["routers"][peer2]["links"][dut]["interface"]
-
- if addr_type == "ipv4":
- next_hop_4 = NEXT_HOP_4
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- if addr_type == "ipv6":
- if "link_local" in PREFERRED_NEXT_HOP:
- next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
- next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
-
- next_hop_6 = [next_hop1, next_hop2]
- else:
- next_hop_6 = NEXT_HOP_6
-
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- # Kill BGPd daemon on R4
- kill_router_daemons(tgen, "r4", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- next_hop_6 = ["fd00:0:0:1::1"]
- if addr_type == "ipv4":
- next_hop_4 = NEXT_HOP_4[0]
-
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- if addr_type == "ipv6":
- if "link_local" in PREFERRED_NEXT_HOP:
- next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
- else:
- next_hop_6 = NEXT_HOP_6[0]
-
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
-
- # Verifying RIB routes
- if addr_type == "ipv4":
- next_hop_4 = NEXT_HOP_4[1]
- result = verify_rib(
- tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- if addr_type == "ipv6":
- if "link_local" in PREFERRED_NEXT_HOP:
- next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
- else:
- next_hop_6 = NEXT_HOP_6[1]
-
- result = verify_rib(
- tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- # Start BGPd daemon on R4
- start_router_daemons(tgen, "r4", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_34_2_p1(request):
- """
- Test Objective : Restarting node doesn't preserve the forwarding
- state verify the behaviour on helper node, if it still keeps the
- stale routes.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_34 "
- "BGP GR "
- "[Restart Mode]R1---R3[Helper Mode]"
- )
-
- logger.info("[Step 1] : Configure restarting" " router R1 to prevent ")
- logger.info("[Step 2] : Reset the session" " between R1 and R3..")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"preserve-fw-state": True, "disable-eor": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify f-bit before killing BGPd daemon
- result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 3] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..")
-
- # Api call to delete advertised networks
- network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r1": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..")
-
- # Modify graceful-restart config not to set f-bit
- # and write to /etc/frr
- input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
-
- logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verify f-bit after starting BGPd daemon
- result = verify_f_bit(
- tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes after starting BGPd daemon
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_34_1_p1(request):
- """
- Test Objective : Restarting node doesn't preserve forwarding
- state, helper router should not keep the stale entries.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_31 "
- "BGP GR "
- "[Restart Mode]R1---R3[Helper Mode]"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "preserve-fw-state": True,
- "timer": {"restart-time": GR_RESTART_TIMER},
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 1] : Remove the preserve-fw-state command"
- " from restarting node R1's config"
- )
-
- # Configure graceful-restart to set f-bit as False
- input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- logger.info("[Step 2] : Reset the session between R1 and R3..")
-
- # Reset sessions
- for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
-
- result = verify_bgp_convergence_from_running_config(tgen, topo)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- # Verify f-bit after starting BGPd daemon
- result = verify_f_bit(
- tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Step 3] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- # Waiting for GR_RESTART_TIMER
- logger.info("Waiting for {} sec..".format(GR_RESTART_TIMER))
- sleep(GR_RESTART_TIMER)
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_dict = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_32_p1(request):
- """
- Test Objective : Restarting node is connected to multiple helper
- nodes, one of them doesn't send EOR to restarting router. Verify
- that only after SDT restarting node send EOR to all helper peers
- excluding the prefixes originated by faulty router.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_32 "
- "BGP GR "
- "[Restart Mode]R1---R3&R5[Helper Mode]"
- )
-
- logger.info(
- "[Step 1] : Change the mode on R1 be a restarting" " node on global level"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"graceful-restart": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
- "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
- "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- },
- }
- },
- "r5": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r5": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r5": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r5")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r5"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Kill BGPd daemon on R1..")
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Withdraw all the advertised prefixes from R5")
-
- # Api call to delete advertised networks
- network = {"ipv4": "105.0.20.1/32", "ipv6": "5::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r5": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 4] : Stop the helper router R5 from sending EOR" " message using CLI"
- )
-
- # Modify graceful-restart config to prevent sending EOR
- input_dict_3 = {"r5": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = create_router_bgp(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- logger.info("[Step 5] : Bring up the BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verify EOR is disabled
- result = verify_eor(
- tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes after starting BGPd daemon
- input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_37_p1(request):
- """
- Test Objective : Verify if helper node restarts before sending the
- EOR message, restarting node doesn't wait until stale path timer
- expiry to do the best path selection and sends an EOR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_37 "
- "BGP GR "
- "[Restart Mode]R1---R3[Helper Mode]"
- )
-
- logger.info(
- "[Step 1] : Configure restarting router R3 to prevent " "sending an EOR.."
- )
-
- logger.info("[Step 2] : Reset the session between R3 and R1..")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "graceful-restart": {"disable-eor": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify EOR is disabled
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 3] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 4] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 5] : Kill BGPd daemon on R3..")
-
- # Kill BGPd daemon on R3
- kill_router_daemons(tgen, "r3", ["bgpd"])
-
- # Modify graceful-restart config to prevent sending EOR
- input_dict_2 = {"r3": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
-
- logger.info("[Step 6] : Start BGPd daemon on R3..")
-
- # Start BGPd daemon on R3
- start_router_daemons(tgen, "r3", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verify r_bit
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r3")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify EOR is send from R1 to R3
- input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = verify_eor(
- tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_30_p1(request):
- """
- Test Objective : Restarting node removes stale routes from Zebra
- after receiving an EOR from helper router.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_30 "
- "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"preserve-fw-state": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- dut = "r1"
- input_dict = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Withdraw advertised prefixes from R3...")
-
- # Api call to delete advertised networks
- network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict = {
- "r3": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
- )
-
- logger.info("[Step 4] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- input_dict = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_15_p2(request):
- """
- Test Objective : Test GR scenarios by enabling Graceful Restart
- for multiple address families..
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r6": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Helper Mode]R6-----R1[Restart Mode]"
- "--------R2[Helper Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def BGP_GR_TC_7_p1(request):
- """
- Verify that BGP restarting node deletes all the routes received from peer
- if BGP Graceful capability is not present in BGP Open message from the
- peer
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Verify route download to RIB: BGP_GR_TC_7 >> "
- "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("R1 goes for reload")
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- # Change the configuration on router R1
- input_dict_2 = {
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- # Change the configuration on R1
- network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r3": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("R1 is about to come up now")
- start_router_daemons(tgen, "r1", ["bgpd"])
- logger.info("R1 is UP Now")
-
- # Wait for RIB stale timeout
- logger.info("Verify routes are not present" "in restart router")
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_23_p1(request):
- """
- Verify that helper routers are deleting stale routes after stale route
- timer's expiry. If all the routes are not received from restating node
- after restart.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "Verify Stale Routes are deleted on helper: BGP_GR_TC_23 >> "
- "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"stalepath-time": GR_STALEPATH_TIMER}},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("R2 goes for reload")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- # Modify configuration to delete routes and include disable-eor
- input_dict_3 = {"r2": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
-
- # Modify configuration to delete routes and include disable-eor
- network = {"ipv4": "102.0.20.1/32", "ipv6": "2::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_3 = {
- "r2": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 3,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("BGPd comes up for r2")
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- # Wait for stalepath timer
- logger.info("Waiting for stalepath timer({} sec..)".format(GR_STALEPATH_TIMER))
- sleep(GR_STALEPATH_TIMER)
-
- for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r2")
-
- # Verifying RIB routes
- dut = "r1"
- network = {"ipv4": "102.0.20.4/32", "ipv6": "2::4/128"}
- for addr_type in ADDR_TYPES:
- input_dict_1 = {
- "r1": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {"network": network[addr_type], "no_of_network": 2}
- ]
- }
- }
- }
- }
- }
- }
-
- # Verify EOR on helper router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_20_p1(request):
- """
- Test Objective : Verify that GR routers delete all the routes
- received from a node if both the routers are configured as GR
- helper node
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_21_p2(request):
- """
- Test Objective : VVerify BGP-GR feature when helper node is
- a transit router for it's eBGP peers.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r6": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
- "--------R6[Helper Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes after bringing up BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_22_p2(request):
- """
- Test Objective : Verify BGP-GR feature when helper node
- is a transit router for it's iBGP peers.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart-disable": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart-disable": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
- "--------R3[Helper Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-if __name__ == "__main__":
- args = ["-s"] + sys.argv[1:]
- sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
index c1a9499cbe..25951281a7 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
@@ -294,16 +294,16 @@ luCommand(
"1 available, best",
"wait",
"Ensure 99.0.0.4 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r1",
'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 5.1.0.0/24"',
"2 available, best",
"wait",
"Ensure 5.1.0.0 shows up",
- 10
- )
+ 10,
+)
want_r1_remote_cust1_routes = [
{"p": "5.1.0.0/24", "n": "3.3.3.3", "bp": False},
{"p": "5.1.0.0/24", "n": "99.0.0.1", "bp": True},
@@ -316,9 +316,9 @@ want_r1_remote_cust1_routes = [
{"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.1.0/24", "n": "4.4.4.4", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.1", "bp": True},
- {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False},
+ {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": True},
{"p": "6.0.2.0/24", "n": "4.4.4.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.1", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.1", "bp": False},
{"p": "99.0.0.1/32", "n": "192.168.1.2", "bp": True},
{"p": "99.0.0.2/32", "n": "3.3.3.3"},
{"p": "99.0.0.3/32", "n": "4.4.4.4"},
@@ -338,16 +338,16 @@ luCommand(
"1 available, best",
"wait",
"Ensure 99.0.0.4 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r3",
'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 5.1.0.0/24"',
"2 available, best",
"wait",
"Ensure 5.1.0.0 shows up",
- 10
- )
+ 10,
+)
want_r3_remote_cust1_routes = [
{"p": "5.1.0.0/24", "n": "1.1.1.1", "bp": True},
{"p": "5.1.0.0/24", "n": "99.0.0.2", "bp": False},
@@ -360,9 +360,9 @@ want_r3_remote_cust1_routes = [
{"p": "6.0.1.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.1.0/24", "n": "4.4.4.4", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.2", "bp": False},
- {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False},
+ {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.2.0/24", "n": "4.4.4.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.2", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.2", "bp": False},
{"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.3/32", "n": "4.4.4.4", "bp": True},
{"p": "99.0.0.4/32", "n": "4.4.4.4", "bp": True},
@@ -382,24 +382,24 @@ luCommand(
"1 available, best",
"wait",
"Ensure 99.0.0.4 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r4",
'vtysh -c "show bgp vrf r4-cust1 ipv4 uni 5.1.0.0/24"',
"2 available, best",
"wait",
"Ensure 5.1.0.0 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r4",
'vtysh -c "show bgp vrf r4-cust1 ipv4 uni 99.0.0.2/32"',
"1 available, best",
"wait",
"Ensure 99.0.0.2 shows up",
- 10
- )
+ 10,
+)
want_r4_remote_cust1_routes = [
{"p": "5.1.0.0/24", "n": "1.1.1.1", "bp": True},
{"p": "5.1.0.0/24", "n": "3.3.3.3", "bp": False},
@@ -409,10 +409,10 @@ want_r4_remote_cust1_routes = [
{"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False},
+ {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": False},
{"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.2/32", "n": "3.3.3.3", "bp": True},
{"p": "99.0.0.3/32", "n": "192.168.1.2", "bp": True},
@@ -436,9 +436,9 @@ want_r4_remote_cust2_routes = [
{"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False},
+ {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": False},
{"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": False},
{"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.2/32", "n": "3.3.3.3", "bp": True},
@@ -632,8 +632,8 @@ luCommand(
luCommand(
"ce1",
'vtysh -c "show bgp ipv4 uni 6.0.2.0"',
- "1 available, best .*192.168.1.1.* Local.* 99.0.0.1 from 0.0.0.0 .99.0.0.1"
- + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .First path received"
+ "2 available, best .*192.168.1.1.* Local.* 99.0.0.1 from 0.0.0.0 .99.0.0.1"
+ + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .Weight"
+ ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:11",
"pass",
"Redundant route 2 details",
@@ -641,8 +641,8 @@ luCommand(
luCommand(
"ce2",
'vtysh -c "show bgp ipv4 uni 6.0.2.0"',
- "1 available, best .*192.168.1.1.* Local.* 99.0.0.2 from 0.0.0.0 .99.0.0.2"
- + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .First path received"
+ "2 available, best .*192.168.1.1.* Local.* 99.0.0.2 from 0.0.0.0 .99.0.0.2"
+ + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .Weight"
+ ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:12",
"pass",
"Redundant route 2 details",
@@ -661,7 +661,7 @@ luCommand(
'vtysh -c "show bgp ipv4 uni 6.0.2.0"',
"2 available, best .*192.168.1.1.* Local.* 192.168.1.1 from 192.168.1.1 .192.168.1.1"
+ ".* Origin IGP, metric 100, localpref 100, valid, internal"
- + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:14",
+ + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:11",
"pass",
"Redundant route 2 details",
)
@@ -670,7 +670,7 @@ luCommand(
'vtysh -c "show bgp vrf ce4-cust2 ipv4 6.0.2.0"',
"2 available, best .*192.168.2.1.* Local.* 192.168.2.1 from 192.168.2.1 .192.168.2.1"
+ ".* Origin IGP, metric 100, localpref 100, valid, internal"
- + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:13",
+ + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:11",
"pass",
"Redundant route 2 details",
)
diff --git a/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf
new file mode 100644
index 0000000000..c2a49252d6
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf
@@ -0,0 +1,32 @@
+!
+ipv6 access-list nh1 permit 2001:db8:1::/64
+ipv6 access-list nh2 permit 2001:db8:2::/64
+ipv6 access-list nh3 permit 2001:db8:3::/64
+!
+ipv6 prefix-list nh4 permit 2001:db8:5::/64 le 128
+!
+router bgp 65001
+ bgp router-id 10.10.10.1
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8::2 remote-as external
+ address-family ipv6 unicast
+ neighbor 2001:db8::2 activate
+ neighbor 2001:db8::2 route-map r2 in
+ exit-address-family
+!
+route-map r2 permit 10
+ match ipv6 next-hop nh1
+ set community 65002:1
+route-map r2 permit 20
+ match ipv6 next-hop nh2
+ set community 65002:2
+route-map r2 permit 30
+ match ipv6 next-hop nh3
+ set community 65002:3
+route-map r2 permit 40
+ match ipv6 next-hop address 2001:db8:4::1
+ set community 65002:4
+route-map r2 permit 50
+ match ipv6 next-hop prefix-list nh4
+ set community 65002:5
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf
new file mode 100644
index 0000000000..1d4374bd8f
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r1-eth0
+ ipv6 address 2001:db8::1/64
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf
new file mode 100644
index 0000000000..19dcf3664b
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf
@@ -0,0 +1,33 @@
+!
+router bgp 65002
+ bgp router-id 10.10.10.2
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8::1 remote-as external
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8::1 activate
+ neighbor 2001:db8::1 route-map r1 out
+ exit-address-family
+!
+ipv6 prefix-list p1 permit 2001:db8:1::1/128
+ipv6 prefix-list p2 permit 2001:db8:2::1/128
+ipv6 prefix-list p3 permit 2001:db8:3::1/128
+ipv6 prefix-list p4 permit 2001:db8:4::1/128
+ipv6 prefix-list p5 permit 2001:db8:5::1/128
+!
+route-map r1 permit 10
+ match ipv6 address prefix-list p1
+ set ipv6 next-hop global 2001:db8:1::1
+route-map r1 permit 20
+ match ipv6 address prefix-list p2
+ set ipv6 next-hop global 2001:db8:2::1
+route-map r1 permit 30
+ match ipv6 address prefix-list p3
+ set ipv6 next-hop global 2001:db8:3::1
+route-map r1 permit 40
+ match ipv6 address prefix-list p4
+ set ipv6 next-hop global 2001:db8:4::1
+route-map r1 permit 50
+ match ipv6 address prefix-list p5
+ set ipv6 next-hop global 2001:db8:5::1
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf
new file mode 100644
index 0000000000..e69345f4f6
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf
@@ -0,0 +1,11 @@
+!
+int lo
+ ipv6 address 2001:db8:1::1/128
+ ipv6 address 2001:db8:2::1/128
+ ipv6 address 2001:db8:3::1/128
+ ipv6 address 2001:db8:4::1/128
+ ipv6 address 2001:db8:5::1/128
+!
+int r2-eth0
+ ip address 2001:db8::2/64
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
new file mode 100644
index 0000000000..8c86526bf1
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@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 if we can match BGP prefixes by next-hop which is
+specified by an IPv6 Access-list, prefix-list or just an address.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+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
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route_map_match_ipv6_next_hop_access_list():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show ipv6 route json"))
+ expected = {
+ "2001:db8:1::1/128": [
+ {
+ "communities": "65002:1",
+ }
+ ],
+ "2001:db8:2::1/128": [
+ {
+ "communities": "65002:2",
+ }
+ ],
+ "2001:db8:3::1/128": [
+ {
+ "communities": "65002:3",
+ }
+ ],
+ "2001:db8:4::1/128": [
+ {
+ "communities": "65002:4",
+ }
+ ],
+ "2001:db8:5::1/128": [
+ {
+ "communities": "65002:5",
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, router)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't match routes using ipv6 next-hop access-list"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_route_server_client/__init__.py b/tests/topotests/bgp_route_server_client/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/__init__.py
diff --git a/tests/topotests/bgp_route_server_client/r1/bgpd.conf b/tests/topotests/bgp_route_server_client/r1/bgpd.conf
new file mode 100644
index 0000000000..d6c83079f7
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r1/bgpd.conf
@@ -0,0 +1,11 @@
+!
+router bgp 65001
+ bgp router-id 10.10.10.1
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8:1::1 remote-as external
+ neighbor 2001:db8:1::1 timers 3 10
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8:1::1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_route_server_client/r1/zebra.conf b/tests/topotests/bgp_route_server_client/r1/zebra.conf
new file mode 100644
index 0000000000..08d0be6220
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r1/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ipv6 address 2001:db8:f::1/128
+!
+int r1-eth0
+ ipv6 address 2001:db8:1::2/64
+!
diff --git a/tests/topotests/bgp_route_server_client/r2/bgpd.conf b/tests/topotests/bgp_route_server_client/r2/bgpd.conf
new file mode 100644
index 0000000000..bdcae4a996
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r2/bgpd.conf
@@ -0,0 +1,15 @@
+router bgp 65000 view RS
+ bgp router-id 10.10.10.2
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8:1::2 remote-as external
+ neighbor 2001:db8:1::2 timers 3 10
+ neighbor 2001:db8:3::2 remote-as external
+ neighbor 2001:db8:3::2 timers 3 10
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8:1::2 activate
+ neighbor 2001:db8:3::2 activate
+ neighbor 2001:db8:1::2 route-server-client
+ neighbor 2001:db8:3::2 route-server-client
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_route_server_client/r2/zebra.conf b/tests/topotests/bgp_route_server_client/r2/zebra.conf
new file mode 100644
index 0000000000..806bc4fe32
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+int r2-eth0
+ ipv6 address 2001:db8:1::1/64
+!
+int r2-eth1
+ ipv6 address 2001:db8:3::1/64
+!
diff --git a/tests/topotests/bgp_route_server_client/r3/bgpd.conf b/tests/topotests/bgp_route_server_client/r3/bgpd.conf
new file mode 100644
index 0000000000..4b565e7b77
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r3/bgpd.conf
@@ -0,0 +1,11 @@
+!
+router bgp 65003
+ bgp router-id 10.10.10.3
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8:3::1 remote-as external
+ neighbor 2001:db8:3::1 timers 3 10
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8:3::1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_route_server_client/r3/zebra.conf b/tests/topotests/bgp_route_server_client/r3/zebra.conf
new file mode 100644
index 0000000000..b5511a437c
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r3/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ipv6 address 2001:db8:f::3/128
+!
+int r3-eth0
+ ipv6 address 2001:db8:3::2/64
+!
diff --git a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
new file mode 100644
index 0000000000..c11bc119eb
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@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 if we send ONLY GUA address for route-server-client peers.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+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
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route_server_client():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show bgp 2001:db8:f::3/128 json"))
+ expected = {
+ "prefix": "2001:db8:f::3/128",
+ "paths": [{"nexthops": [{"ip": "2001:db8:3::2"}]}],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Cannot see BGP GUA next hop from r3 in r1"
+
+ def _bgp_single_next_hop(router):
+ output = json.loads(router.vtysh_cmd("show bgp 2001:db8:f::3/128 json"))
+ return len(output["paths"][0]["nexthops"])
+
+ assert (
+ _bgp_single_next_hop(r1) == 1
+ ), "Not ONLY one Next Hop received for 2001:db8:f::3/128"
+
+ def _bgp_gua_lla_next_hop(router):
+ output = json.loads(router.vtysh_cmd("show bgp view RS 2001:db8:f::3/128 json"))
+ expected = {
+ "prefix": "2001:db8:f::3/128",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "ip": "2001:db8:3::2",
+ "hostname": "r3",
+ "afi": "ipv6",
+ "scope": "global",
+ },
+ {"hostname": "r3", "afi": "ipv6", "scope": "link-local"},
+ ]
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_gua_lla_next_hop, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Cannot see BGP LLA next hop from r3 in r2"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json
new file mode 100644
index 0000000000..b1d7d09db8
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json
@@ -0,0 +1,563 @@
+{
+ "address_types": ["ipv4","ipv6"],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 30,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r4-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {
+ "name": "ISR",
+ "id": "1"
+ }
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["11.11.11.1/32", "11.11.11.11/32"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["11:11::1/128", "11:11::11/128"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["10.10.10.10/32", "10.10.10.100/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["10:10::10/128", "10:10::100/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r2": {
+ "links": {
+ "r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r4-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {
+ "name": "ISR",
+ "id": "1"
+ }
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["22.22.22.2/32", "22.22.22.22/32"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["22:22::2/128", "22:22::22/128"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["20.20.20.20/32", "20.20.20.200/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["20:20::20/128", "20:20::200/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r3": {
+ "links": {
+ "r1-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp":
+ [
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["30.30.30.3/32", "30.30.30.30/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["30:30::3/128", "30:30::30/128"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50.50.50.5/32", "50.50.50.50/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50:50::5/128", "50:50::50/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r4": {
+ "links": {
+ "r1-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp":
+ [
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["40.40.40.4/32", "40.40.40.40/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["40:40::4/128", "40:40::40/128"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50.50.50.5/32", "50.50.50.50/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50:50::5/128", "50:50::50/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json
new file mode 100644
index 0000000000..0b13882176
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json
@@ -0,0 +1,1088 @@
+{
+ "address_types": ["ipv4","ipv6"],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 24,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 24,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "r3-link1": {"ipv4": "192.168.1.1/24", "ipv6": "fd00:0:0:1::1/120", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "192.168.1.1/24", "ipv6": "fd00:0:0:1::1/120", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "1",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "1",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "1",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "1",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r2": {
+ "links": {
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "2",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "2",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "2",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "2",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r3": {
+ "links": {
+ "r1-link1": {"ipv4": "192.168.1.2/24", "ipv6": "fd00:0:0:1::2/120", "vrf": "RED"},
+ "r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r1-link3": {"ipv4": "192.168.1.2/24", "ipv6": "fd00:0:0:1::2/120", "vrf": "GREEN"},
+ "r1-link4": {"ipv4": "auto", "ipv6": "auto"},
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r2-link4": {"ipv4": "auto", "ipv6": "auto"},
+ "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r4-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r4-link4": {"ipv4": "auto", "ipv6": "auto"},
+ "r5-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r5-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r5-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r5-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "3",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link1": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link2": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link2": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link3": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r4": {
+ "links": {
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "4",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "4",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "4",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "4",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "r5": {
+ "links": {
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "3",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py
new file mode 100644
index 0000000000..d9d4f4f8b2
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py
@@ -0,0 +1,916 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2020 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP VRF Lite:
+
+1. Verify BGP best path selection algorithm works fine when
+routes are imported from ISR to default vrf and vice versa.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ step,
+ create_route_maps,
+ create_prefix_lists,
+ check_router_status,
+ get_frr_ipv6_linklocal,
+ shutdown_bringup_interface,
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_community,
+ verify_bgp_rib,
+ clear_bgp,
+ verify_best_path_as_per_bgp_attribute
+)
+from lib.topojson import build_config_from_json
+
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.10/32", "ipv6": "10:10::10/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+NETWORK3_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
+NETWORK3_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
+
+NETWORK4_1 = {"ipv4": "40.40.40.4/32", "ipv6": "40:40::4/128"}
+NETWORK4_2 = {"ipv4": "40.40.40.40/32", "ipv6": "40:40::40/128"}
+NETWORK4_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
+NETWORK4_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
+NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+LOOPBACK_1 = {
+ "ipv4": "10.0.0.7/24",
+ "ipv6": "fd00:0:0:1::7/64",
+ "ipv4_mask": "255.255.255.0",
+ "ipv6_mask": None,
+}
+LOOPBACK_2 = {
+ "ipv4": "10.0.0.16/24",
+ "ipv6": "fd00:0:0:3::5/64",
+ "ipv4_mask": "255.255.255.0",
+ "ipv6_mask": None,
+}
+PREFERRED_NEXT_HOP = "global"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_vrf_lite_best_path_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def disable_route_map_to_prefer_global_next_hop(tgen, topo):
+ """
+ This API is to remove prefer global route-map applied on neighbors
+
+ Parameter:
+ ----------
+ * `tgen` : Topogen object
+ * `topo` : Input JSON data
+
+ Returns:
+ --------
+ True/errormsg
+
+ """
+
+ logger.info("Remove prefer-global rmap applied on neighbors")
+ input_dict = {
+ "r1": {
+ "bgp": [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ "r2": {
+ "bgp": [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r2-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ "r3": {
+ "bgp": [
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ "r4": {
+ "bgp": [
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r4-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r4-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase :Failed \n Error: {}".format(result)
+
+ return True
+
+
+def test_bgp_best_path_with_dynamic_import_p0(request):
+ """
+ 1.5.6. Verify BGP best path selection algorithm works fine when
+ routes are imported from ISR to default vrf and vice versa.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ build_config_from_json(tgen, topo)
+
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ for addr_type in ADDR_TYPES:
+
+ step(
+ "Redistribute configured static routes into BGP process" " on R1/R2 and R3"
+ )
+
+ input_dict_1 = {}
+ DUT = ["r1", "r2", "r3", "r4"]
+ VRFS = ["ISR", "ISR", "default", "default"]
+ AS_NUM = [100, 100, 300, 400]
+
+ for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
+ temp = {dut: {"bgp": []}}
+ input_dict_1.update(temp)
+
+ temp[dut]["bgp"].append(
+ {
+ "local_as": as_num,
+ "vrf": vrf,
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ },
+ }
+ )
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Import from default vrf into vrf ISR on R1 and R2 as below")
+
+ input_dict_vrf = {}
+ DUT = ["r1", "r2"]
+ VRFS = ["ISR", "ISR"]
+ AS_NUM = [100, 100]
+
+ for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
+ temp = {dut: {"bgp": []}}
+ input_dict_vrf.update(temp)
+
+ temp[dut]["bgp"].append(
+ {
+ "local_as": as_num,
+ "vrf": vrf,
+ "address_family": {
+ addr_type: {"unicast": {"import": {"vrf": "default"}}}
+ },
+ }
+ )
+
+ result = create_router_bgp(tgen, topo, input_dict_vrf)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ input_dict_default = {}
+ DUT = ["r1", "r2"]
+ VRFS = ["default", "default"]
+ AS_NUM = [100, 100]
+
+ for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
+ temp = {dut: {"bgp": []}}
+ input_dict_default.update(temp)
+
+ temp[dut]["bgp"].append(
+ {
+ "local_as": as_num,
+ "vrf": vrf,
+ "address_family": {
+ addr_type: {"unicast": {"import": {"vrf": "ISR"}}}
+ },
+ }
+ )
+
+ result = create_router_bgp(tgen, topo, input_dict_default)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify ECMP/Next-hop/Imported routes Vs Locally originated "
+ "routes/eBGP routes vs iBGP routes --already covered in almost"
+ " all tests"
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify Pre-emption")
+
+ input_routes_r3 = {
+ "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
+ }
+
+ intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
+ intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
+
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
+ nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
+ else:
+ nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+ nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r4_r1]
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Shutdown interface connected to r1 from r4:")
+ shutdown_bringup_interface(tgen, "r4", intf_r4_r1, False)
+
+ for addr_type in ADDR_TYPES:
+
+ input_routes_r3 = {
+ "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
+ }
+
+ intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
+ intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
+
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
+ nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
+ else:
+ nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+ nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+
+ step("Verify next-hop is changed")
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1]
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bringup interface connected to r1 from r4:")
+ shutdown_bringup_interface(tgen, "r4", intf_r4_r1, True)
+
+ for addr_type in ADDR_TYPES:
+
+ input_routes_r3 = {
+ "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
+ }
+
+ intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
+ intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
+
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
+ nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
+ else:
+ nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+ nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+
+ step("Verify next-hop is not chnaged aftr shutdown:")
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1]
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Active-Standby scenario(as-path prepend and Local pref)")
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create prefix-list")
+
+ input_dict_pf = {
+ "r1": {
+ "prefix_lists": {
+ addr_type: {
+ "pf_ls_{}".format(addr_type): [
+ {
+ "seqid": 10,
+ "network": NETWORK3_4[addr_type],
+ "action": "permit",
+ }
+ ]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_pf)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create route-map to match prefix-list and set localpref 500")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 10,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {"locPrf": 500},
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Create route-map to match prefix-list and set localpref 600")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH2_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 20,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {"locPrf": 600},
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ input_dict_rma = {
+ "r1": {
+ "bgp": [
+ {
+ "local_as": "100",
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_PATH1_{}".format(
+ addr_type
+ ),
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_PATH2_{}".format(
+ addr_type
+ ),
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ },
+ }
+ }
+ }
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_rma)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ dut = "r1"
+ attribute = "locPrf"
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify bestpath is installed as per highest localpref")
+
+ input_routes_r3 = {
+ "r3": {
+ "static_routes": [
+ {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
+ ]
+ }
+ }
+
+ result = verify_best_path_as_per_bgp_attribute(
+ tgen, addr_type, dut, input_routes_r3, attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create route-map to match prefix-list and set localpref 700")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 10,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {"locPrf": 700},
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify bestpath is changed as per highest localpref")
+
+ input_routes_r3 = {
+ "r3": {
+ "static_routes": [
+ {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
+ ]
+ }
+ }
+
+ result = verify_best_path_as_per_bgp_attribute(
+ tgen, addr_type, dut, input_routes_r3, attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create route-map to match prefix-list and set as-path prepend")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH2_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 20,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 700,
+ "path": {"as_num": "111", "as_action": "prepend"},
+ },
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ attribute = "path"
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify bestpath is changed as per shortest as-path")
+
+ input_routes_r3 = {
+ "r3": {
+ "static_routes": [
+ {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
+ ]
+ }
+ }
+
+ result = verify_best_path_as_per_bgp_attribute(
+ tgen, addr_type, dut, input_routes_r3, attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
new file mode 100644
index 0000000000..e930b62706
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
@@ -0,0 +1,539 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test BGP VRF Lite:
+1. Verify that locally imported routes are selected as best path over eBGP imported routes
+ peers.
+2. Verify ECMP for imported routes from different VRFs.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ step,
+ create_static_routes,
+ check_router_status,
+ apply_raw_config
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_rib,
+ verify_bgp_bestpath
+)
+from lib.topojson import build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"}
+NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"}
+NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+
+PREFIX_LIST = {
+ "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"],
+ "ipv6": ["11:11::1", "22:22::2", "22:22::22"],
+}
+PREFERRED_NEXT_HOP = "global"
+VRF_LIST = ["RED", "BLUE", "GREEN"]
+COMM_VAL_1 = "100:100"
+COMM_VAL_2 = "500:500"
+COMM_VAL_3 = "600:600"
+BESTPATH = {
+ "ipv4": "0.0.0.0",
+ "ipv6": "::"
+}
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_vrf_lite_best_path_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
+ """
+ Verify ECMP for imported routes from different VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+
+ step("Configure same static routes in tenant vrfs RED and GREEN on router "
+ "R3 and redistribute in respective BGP process")
+
+ for vrf_name in ["RED", "GREEN"]:
+ for addr_type in ADDR_TYPES:
+ if vrf_name == "GREEN":
+ next_hop_vrf = topo["routers"]["r1"]["links"][
+ "r3-link3"][addr_type].split("/")[0]
+ else:
+ next_hop_vrf = topo["routers"]["r2"]["links"][
+ "r3-link1"][addr_type].split("/")[0]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "next_hop": next_hop_vrf,
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "redistribute": [{
+ "redist_type": "static"
+ }]
+ }
+ }
+ })
+
+ redist_dict = {"r3": {"bgp": [{
+ "vrf": vrf_name, "local_as": 3, "address_family": temp
+ }]}}
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that configured static routes are installed in respective "
+ "BGP table for vrf RED & GREEN")
+ for vrf_name in ["RED", "GREEN"]:
+ for addr_type in ADDR_TYPES:
+ if vrf_name == "GREEN":
+ next_hop_vrf = topo["routers"]["r1"]["links"][
+ "r3-link3"][addr_type].split("/")[0]
+ else:
+ next_hop_vrf = topo["routers"]["r2"]["links"][
+ "r3-link1"][addr_type].split("/")[0]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ step("Import vrf RED and GREEN into default vrf and Configure ECMP")
+ bgp_val = []
+ for vrf_name in ["RED", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "import": {
+ "vrf": vrf_name
+ },
+ "maximum_paths": {
+ "ebgp": 2
+ }
+ }
+ }
+ })
+
+ bgp_val.append({
+ "local_as": 3, "address_family": temp
+ })
+
+ import_dict = {"r3": {"bgp": bgp_val}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Configure bgp bestpath on router r3")
+ r3_raw_config = {
+ "r3": {
+ "raw_config": [
+ "router bgp 3",
+ "bgp bestpath as-path multipath-relax"
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, r3_raw_config)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that routes are imported with two different next-hop vrfs "
+ "and IPs. Additionally R3 must do ECMP for both the routes.")
+
+ for addr_type in ADDR_TYPES:
+ next_hop_vrf = [
+ topo["routers"]["r2"]["links"]["r3-link1"][addr_type]. \
+ split("/")[0],
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \
+ split("/")[0]
+ ]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ step("Now change the next-hop of static routes in vrf RED and GREEN to "
+ "same IP address")
+ for addr_type in ADDR_TYPES:
+ next_hop_vrf = topo["routers"]["r1"]["links"][
+ "r3-link3"][addr_type].split("/")[0]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "next_hop": next_hop_vrf,
+ "vrf": "RED"
+ },
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "next_hop": topo["routers"]["r2"]["links"][
+ "r3-link1"][addr_type].split("/")[0],
+ "vrf": "RED",
+ "delete": True
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that now routes are imported with two different next-hop "
+ "vrfs but same IPs. Additionally R3 must do ECMP for both the routes")
+
+ for addr_type in ADDR_TYPES:
+ next_hop_vrf = [
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type].\
+ split("/")[0],
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \
+ split("/")[0]
+ ]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(request):
+ """
+ Verify ECMP for imported routes from different VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+
+ step("Configure same static routes on R2 and R3 vrfs and redistribute in BGP "
+ "for GREEN and RED vrf instances")
+ for dut, network in zip(["r2", "r3"], [
+ [NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]):
+ for vrf_name, network_vrf in zip(["RED", "GREEN"], network):
+ step("Configure static route for VRF : {} on {}".format(vrf_name,
+ dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [network_vrf[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ for dut, as_num in zip(["r2", "r3"], ["2", "3"]):
+ for vrf_name in ["RED", "GREEN"]:
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "redistribute": [{
+ "redist_type": "static"
+ }]
+ }
+ }
+ })
+
+ redist_dict = {dut: {"bgp": [{
+ "vrf": vrf_name, "local_as": as_num, "address_family": temp
+ }]}}
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that R2 and R3 has installed redistributed routes in default "
+ "and RED vrfs and GREEN respectively:")
+ for dut, network in zip(["r2", "r3"],
+ [[NETWORK1_1, NETWORK1_2],
+ [NETWORK1_1, NETWORK1_2]]):
+ for vrf_name, network_vrf in zip(["RED", "GREEN"], network):
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [network_vrf[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ step("Import vrf RED's route in vrf GREEN on R3")
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "import": {
+ "vrf": "RED"
+ }
+ }
+ }
+ })
+
+ import_dict = {"r3": {"bgp": [{
+ "vrf": "GREEN", "local_as": 3, "address_family": temp
+ }]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that locally imported routes are installed over eBGP imported"
+ " routes from VRF RED into VRF GREEN")
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_2[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "GREEN"
+ }
+ ]
+ }
+ }
+
+ input_routes = {
+ "r3": {
+ addr_type: [
+ {
+ "network": NETWORK1_2[addr_type],
+ "bestpath": BESTPATH[addr_type],
+ "vrf": "GREEN"
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_bestpath(tgen, addr_type, input_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_netns/peer1/exa-send.py b/tests/topotests/bgp_vrf_netns/peer1/exa-send.py
index 9279cc45ff..ab0eb8ce8f 100755
--- a/tests/topotests/bgp_vrf_netns/peer1/exa-send.py
+++ b/tests/topotests/bgp_vrf_netns/peer1/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py
index a0cae0a40b..ff9ad6150a 100644
--- a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py
+++ b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py
@@ -175,11 +175,19 @@ def test_isis_route_installation():
for rname, router in tgen.routers().items():
filename = "{0}/{1}/{1}_route.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
- actual = router.vtysh_cmd(
- "show ip route vrf {0}-cust1 json".format(rname), isjson=True
- )
- assertmsg = "Router '{}' routes mismatch".format(rname)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+
+ def compare_routing_table(router, expected):
+ "Helper function to ensure zebra rib convergence"
+
+ actual = router.vtysh_cmd(
+ "show ip route vrf {0}-cust1 json".format(rname), isjson=True
+ )
+ return topotest.json_cmp(actual, expected)
+
+ test_func = functools.partial(compare_routing_table, router, expected)
+ (result, diff) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = "Router '{}' routes mismatch diff: {}".format(rname, diff)
+ assert result, assertmsg
def test_isis_linux_route_installation():
@@ -220,12 +228,18 @@ def test_isis_route6_installation():
for rname, router in tgen.routers().items():
filename = "{0}/{1}/{1}_route6.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
- actual = router.vtysh_cmd(
- "show ipv6 route vrf {}-cust1 json".format(rname), isjson=True
- )
- assertmsg = "Router '{}' routes mismatch".format(rname)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+ def compare_routing_table(router, expected):
+ "Helper function to ensure zebra rib convergence"
+ actual = router.vtysh_cmd(
+ "show ipv6 route vrf {}-cust1 json".format(rname), isjson=True
+ )
+ return topotest.json_cmp(actual, expected)
+
+ test_func = functools.partial(compare_routing_table, router, expected)
+ (result, diff) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = "Router '{}' routes mismatch diff: ".format(rname, diff)
+ assert result, assertmsg
def test_isis_linux_route6_installation():
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 458ae4b054..3253fe6900 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -989,6 +989,14 @@ def __create_bgp_unicast_address_family(
if "no_allowas_in" in peer:
allow_as_in = peer["no_allowas_in"]
config_data.append("no {} allowas-in {}".format(neigh_cxt, allow_as_in))
+
+ if "shutdown" in peer:
+ shut_val = peer["shutdown"]
+ if shut_val is True:
+ config_data.append("{} shutdown".format(neigh_cxt))
+ elif shut_val is False:
+ config_data.append("no {} shutdown".format(neigh_cxt))
+
if prefix_lists:
for prefix_list in prefix_lists:
name = prefix_list.setdefault("name", {})
@@ -2221,6 +2229,7 @@ def verify_bgp_attributes(
rmap_name=None,
input_dict=None,
seq_id=None,
+ vrf=None,
nexthop=None,
expected=True,
):
@@ -2275,7 +2284,10 @@ def verify_bgp_attributes(
logger.info("Verifying BGP set attributes for dut {}:".format(router))
for static_route in static_routes:
- cmd = "show bgp {} {} json".format(addr_type, static_route)
+ if vrf:
+ cmd = "show bgp vrf {} {} {} json".format(vrf, addr_type, static_route)
+ else:
+ cmd = "show bgp {} {} json".format(addr_type, static_route)
show_bgp_json = run_frr_cmd(rnode, cmd, isjson=True)
dict_to_test = []
@@ -2821,7 +2833,6 @@ def verify_bgp_rib(
st_rt,
dut,
)
- return errormsg
else:
nh_found = True
@@ -4428,6 +4439,83 @@ def verify_evpn_routes(
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return False
+
+
+@retry(retry_timeout=10)
+def verify_bgp_bestpath(tgen, addr_type, input_dict):
+ """
+ Verifies bgp next hop values in best-path output
+
+ * `dut` : device under test
+ * `addr_type` : Address type ipv4/ipv6
+ * `input_dict`: having details like multipath and bestpath
+
+ Usage
+ -----
+ input_dict_1 = {
+ "r1": {
+ "ipv4" : {
+ "bestpath": "50.0.0.1",
+ "multipath": ["50.0.0.1", "50.0.0.2"],
+ "network": "100.0.0.0/24"
+ }
+ "ipv6" : {
+ "bestpath": "1000::1",
+ "multipath": ["1000::1", "1000::2"]
+ "network": "2000::1/128"
+ }
+ }
+ }
+
+ result = verify_bgp_bestpath(tgen, input_dict)
+
+ """
+
+ result = False
+ logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+ for dut in input_dict.keys():
+ rnode = tgen.routers()[dut]
+
+ logger.info("[DUT: %s]: Verifying bgp bestpath and multipath " "routes:", dut)
+ result = False
+ for network_dict in input_dict[dut][addr_type]:
+ nw_addr = network_dict.setdefault("network", None)
+ vrf = network_dict.setdefault("vrf", None)
+ bestpath = network_dict.setdefault("bestpath", None)
+
+ if vrf:
+ cmd = "show bgp vrf {} {} {} bestpath json".format(
+ vrf, addr_type, nw_addr
+ )
+ else:
+ cmd = "show bgp {} {} bestpath json".format(addr_type, nw_addr)
+
+ data = run_frr_cmd(rnode, cmd, isjson=True)
+ route = data["paths"][0]
+
+ if "bestpath" in route:
+ if route["bestpath"]["overall"] is True:
+ _bestpath = route["nexthops"][0]["ip"]
+
+ if _bestpath != bestpath:
+ return (
+ "DUT:[{}] Bestpath do not match for"
+ " network: {}, Expected "
+ " {} as bgp bestpath found {}".format(
+ dut, nw_addr, bestpath, _bestpath
+ )
+ )
+
+ logger.info(
+ "DUT:[{}] Found expected bestpath: "
+ " {} for network: {}".format(dut, _bestpath, nw_addr)
+ )
+ result = True
+
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return result
+
+
def verify_tcp_mss(tgen, dut, neighbour, configured_tcp_mss, vrf=None):
"""
This api is used to verify the tcp-mss value assigned to a neigbour of DUT
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index cf8efdea16..c744e5bbbf 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -26,6 +26,7 @@ import socket
import subprocess
import sys
import traceback
+import functools
from collections import OrderedDict
from copy import deepcopy
from datetime import datetime, timedelta
@@ -2970,24 +2971,34 @@ def addKernelRoute(
logger.info("[DUT: {}]: Running command: [{}]".format(router, cmd))
output = rnode.run(cmd)
- # Verifying if ip route added to kernal
- result = rnode.run(verify_cmd)
- logger.debug("{}\n{}".format(verify_cmd, result))
- if "/" in grp_addr:
- ip, mask = grp_addr.split("/")
- if mask == "32" or mask == "128":
- grp_addr = ip
- else:
- mask = "32" if addr_type == "ipv4" else "128"
+ def check_in_kernel(rnode, verify_cmd, grp_addr, router):
+ # Verifying if ip route added to kernal
+ errormsg = None
+ result = rnode.run(verify_cmd)
+ logger.debug("{}\n{}".format(verify_cmd, result))
+ if "/" in grp_addr:
+ ip, mask = grp_addr.split("/")
+ if mask == "32" or mask == "128":
+ grp_addr = ip
+ else:
+ mask = "32" if addr_type == "ipv4" else "128"
- if not re_search(r"{}".format(grp_addr), result) and mask != "0":
- errormsg = (
- "[DUT: {}]: Kernal route is not added for group"
- " address {} Config output: {}".format(router, grp_addr, output)
- )
+ if not re_search(r"{}".format(grp_addr), result) and mask != "0":
+ errormsg = (
+ "[DUT: {}]: Kernal route is not added for group"
+ " address {} Config output: {}".format(
+ router, grp_addr, output
+ )
+ )
return errormsg
+ test_func = functools.partial(
+ check_in_kernel, rnode, verify_cmd, grp_addr, router
+ )
+ (result, out) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assert result, out
+
logger.debug("Exiting lib API: addKernelRoute()")
return True
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index c425e121af..92d29ad1ab 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -265,35 +265,6 @@ def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf):
cmd = "no {}".format(cmd)
config_data.append(cmd)
- # area interface information for ospf6d only
- if ospf == "ospf6":
- area_iface = ospf_data.setdefault("neighbors", {})
- if area_iface:
- for neighbor in area_iface:
- if "area" in area_iface[neighbor]:
- iface = input_dict[router]["links"][neighbor]["interface"]
- cmd = "interface {} area {}".format(
- iface, area_iface[neighbor]["area"]
- )
- if area_iface[neighbor].setdefault("delete", False):
- cmd = "no {}".format(cmd)
- config_data.append(cmd)
-
- try:
- if "area" in input_dict[router]["links"][neighbor]["ospf6"]:
- iface = input_dict[router]["links"][neighbor]["interface"]
- cmd = "interface {} area {}".format(
- iface,
- input_dict[router]["links"][neighbor]["ospf6"]["area"],
- )
- if input_dict[router]["links"][neighbor].setdefault(
- "delete", False
- ):
- cmd = "no {}".format(cmd)
- config_data.append(cmd)
- except KeyError:
- pass
-
# summary information
summary_data = ospf_data.setdefault("summary-address", {})
if summary_data:
@@ -363,69 +334,6 @@ def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf):
return config_data
-def create_router_ospf6(
- tgen, topo=None, input_dict=None, build=False, load_config=True
-):
- """
- API to configure ospf on router
-
- Parameters
- ----------
- * `tgen` : Topogen object
- * `topo` : json file data
- * `input_dict` : Input dict data, required when configuring from testcase
- * `build` : Only for initial setup phase this is set as True.
-
- Usage
- -----
- input_dict = {
- "r1": {
- "ospf6": {
- "router_id": "22.22.22.22",
- }
- }
-
- Returns
- -------
- True or False
- """
- logger.debug("Entering lib API: create_router_ospf6()")
- result = False
-
- if topo is None:
- topo = tgen.json_topo
-
- if not input_dict:
- input_dict = deepcopy(topo)
- else:
- topo = topo["routers"]
- input_dict = deepcopy(input_dict)
-
- config_data_dict = {}
-
- for router in input_dict.keys():
- if "ospf6" not in input_dict[router]:
- logger.debug("Router %s: 'ospf6' not present in input_dict", router)
- continue
-
- config_data = __create_ospf_global(
- tgen, input_dict, router, build, load_config, "ospf6"
- )
- if config_data:
- config_data_dict[router] = config_data
-
- try:
- result = create_common_configurations(
- tgen, config_data_dict, "ospf6", build, load_config
- )
- except InvalidCLIError:
- logger.error("create_router_ospf6", exc_info=True)
- result = False
-
- logger.debug("Exiting lib API: create_router_ospf6()")
- return result
-
-
def config_ospf_interface(
tgen, topo=None, input_dict=None, build=False, load_config=True
):
@@ -874,6 +782,16 @@ def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False)
}
result = verify_ospf6_neighbor(tgen, topo, dut, input_dict, lan=True)
+ 3. To check there are no neighbors.
+ input_dict = {
+ "r0": {
+ "ospf6": {
+ "neighbors": []
+ }
+ }
+ }
+ result = verify_ospf6_neighbor(tgen, topo, dut, input_dict)
+
Returns
-------
True or False (Error Message)
@@ -904,6 +822,19 @@ def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False)
ospf_data_list = input_dict[router]["ospf6"]
ospf_nbr_list = ospf_data_list["neighbors"]
+ # Check if looking for no neighbors
+ if ospf_nbr_list == []:
+ if show_ospf_json["neighbors"] == []:
+ logger.info("[DUT: {}] OSPF6 no neighbors found".format(router))
+ return True
+ else:
+ errormsg = (
+ "[DUT: {}] OSPF6 active neighbors found, expected None".format(
+ router
+ )
+ )
+ return errormsg
+
for ospf_nbr, nbr_data in ospf_nbr_list.items():
try:
diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py
index 944981add4..dd2f787014 100644
--- a/tests/topotests/lib/pim.py
+++ b/tests/topotests/lib/pim.py
@@ -21,8 +21,10 @@ import os
import re
import sys
import traceback
+import functools
from copy import deepcopy
from time import sleep
+from lib import topotest
# Import common_config to use commomnly used APIs
@@ -1481,24 +1483,34 @@ def verify_pim_interface_traffic(tgen, input_dict):
rnode = tgen.routers()[dut]
logger.info("[DUT: %s]: Verifying pim interface traffic", dut)
- show_pim_intf_traffic_json = run_frr_cmd(
- rnode, "show ip pim interface traffic json", isjson=True
- )
- output_dict[dut] = {}
- for intf, data in input_dict[dut].items():
- interface_json = show_pim_intf_traffic_json[intf]
- for state in data:
+ def show_pim_intf_traffic(rnode, dut, input_dict, output_dict):
+ show_pim_intf_traffic_json = run_frr_cmd(
+ rnode, "show ip pim interface traffic json", isjson=True
+ )
- # Verify Tx/Rx
- if state in interface_json:
- output_dict[dut][state] = interface_json[state]
- else:
- errormsg = (
- "[DUT %s]: %s is not present"
- "for interface %s [FAILED]!! " % (dut, state, intf)
- )
- return errormsg
+ output_dict[dut] = {}
+ for intf, data in input_dict[dut].items():
+ interface_json = show_pim_intf_traffic_json[intf]
+ for state in data:
+
+ # Verify Tx/Rx
+ if state in interface_json:
+ output_dict[dut][state] = interface_json[state]
+ else:
+ errormsg = (
+ "[DUT %s]: %s is not present"
+ "for interface %s [FAILED]!! " % (dut, state, intf)
+ )
+ return errormsg
+ return None
+
+ test_func = functools.partial(
+ show_pim_intf_traffic, rnode, dut, input_dict, output_dict
+ )
+ (result, out) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ if not result:
+ return out
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return output_dict
diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py
index 4f23e1ace0..3ca3353ed3 100644
--- a/tests/topotests/lib/topojson.py
+++ b/tests/topotests/lib/topojson.py
@@ -40,7 +40,7 @@ from lib.common_config import (
topo_daemons,
number_to_column,
)
-from lib.ospf import create_router_ospf, create_router_ospf6
+from lib.ospf import create_router_ospf
from lib.pim import create_igmp_config, create_pim_config
from lib.topolog import logger
@@ -334,7 +334,6 @@ def build_config_from_json(tgen, topo=None, save_bkup=True):
("igmp", create_igmp_config),
("bgp", create_router_bgp),
("ospf", create_router_ospf),
- ("ospf6", create_router_ospf6),
]
)
@@ -353,6 +352,18 @@ def build_config_from_json(tgen, topo=None, save_bkup=True):
logger.info("build_config_from_json: failed to configure topology")
pytest.exit(1)
+ logger.info("Built config now clearing ospf neighbors as that router-id might not be what is used")
+ for ospf in ["ospf", "ospf6"]:
+ for router in data:
+ if ospf not in data[router]:
+ continue
+
+ r = tgen.gears[router]
+ if ospf == "ospf":
+ r.vtysh_cmd("clear ip ospf process")
+ else:
+ r.vtysh_cmd("clear ipv6 ospf6 process")
+
def create_tgen_from_json(testfile, json_file=None):
"""Create a topogen object given a testfile.
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
index b80da41bec..fd17180051 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
@@ -408,7 +408,7 @@ def test_ospf_lan_tc1_p0(request):
topo_modify_change_ip = deepcopy(topo)
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
- IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 3
+ IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 4
) + "/{}".format(intf_ip.split("/")[1])
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
diff --git a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json
index c8a3ce783b..cdb8813b3d 100644
--- a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json
+++ b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json
@@ -23,7 +23,8 @@
},
"ospf6": {
"hello_interval": 1,
- "dead_interval": 4
+ "dead_interval": 4,
+ "area": "1.1.1.1"
}
}
},
@@ -36,9 +37,7 @@
"ospf6": {
"router_id": "1.1.1.1",
"neighbors": {
- "r3": {
- "area": "1.1.1.1"
- }
+ "r3": {}
}
}
},
@@ -56,7 +55,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "1.1.1.1"
}
},
"r4": {
@@ -71,7 +71,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
}
},
@@ -85,8 +86,8 @@
"ospf6": {
"router_id": "2.2.2.2",
"neighbors": {
- "r3": { "area": "1.1.1.1" },
- "r4": { "area": "0.0.0.0" }
+ "r3": {},
+ "r4": {}
}
}
},
@@ -104,7 +105,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "1.1.1.1"
}
},
"r2": {
@@ -119,7 +121,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "1.1.1.1"
}
},
"r4": {
@@ -134,7 +137,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
}
},
@@ -149,9 +153,9 @@
"ospf6": {
"router_id": "3.3.3.3",
"neighbors": {
- "r1": { "area": "1.1.1.1" },
- "r2": { "area": "1.1.1.1" },
- "r4": { "area": "0.0.0.0" }
+ "r1": {},
+ "r2": {},
+ "r4": {}
}
}
},
@@ -169,7 +173,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
},
"r3": {
@@ -184,7 +189,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
},
"r5": {
@@ -199,7 +205,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "2.2.2.2"
}
}
},
@@ -214,9 +221,9 @@
"ospf6": {
"router_id": "4.4.4.4",
"neighbors": {
- "r2": { "area": "0.0.0.0" },
- "r3": { "area": "0.0.0.0" },
- "r5": { "area": "2.2.2.2" }
+ "r2": {},
+ "r3": {},
+ "r5": {}
}
}
},
@@ -234,7 +241,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "2.2.2.2"
}
}
},
@@ -247,7 +255,7 @@
"ospf6": {
"router_id": "5.5.5.5",
"neighbors": {
- "r4": { "area": "2.2.2.2" }
+ "r4": {}
}
}
}
diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json
new file mode 100644
index 0000000000..2b91abc9e3
--- /dev/null
+++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json
@@ -0,0 +1,86 @@
+{
+ "address_types": [
+ "ipv6"
+ ],
+ "lo_prefix": {
+ "ipv6": "2001::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv6": "12::1/64",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "1.1.1.1",
+ "neighbors": {
+ "r2": {}
+ }
+ }
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv6": "12::2/64",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r3": {
+ "ipv6": "23::2/64",
+ "ospf6": {
+ "area": "1.1.1.1",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "2.2.2.2",
+ "neighbors": {
+ "r1": {},
+ "r3": {}
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv6": "23::3/64",
+ "ospf6": {
+ "area": "1.1.1.1",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "3.3.3.3",
+ "neighbors": {
+ "r2": {}
+ }
+ }
+ }
+ }
+}
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py
new file mode 100644
index 0000000000..64a067cd1a
--- /dev/null
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py
@@ -0,0 +1,162 @@
+#!/usr/bin/python
+
+from lib.topogen import Topogen, get_topogen
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ step,
+ topo_daemons,
+)
+from lib.topolog import logger
+from lib.topojson import build_config_from_json
+from lib.ospf import create_router_ospf, verify_ospf6_neighbor
+import os
+import sys
+import time
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+
+pytestmark = [pytest.mark.ospfd]
+
+
+# Global variables
+topo = None
+
+"""
+TOPOOLOGY
+
+ +---+ 0.0.0.0 +---+ 1.1.1.1 +---+
+ +R1 +------------+R2 |------------+R3 |
+ +-+-+ +--++ +--++
+
+TESTCASES =
+1. OSPF Verify E-bit mismatch between R2 and R3
+2. OSPF Verify N-bit mismatch between R2 and R3
+"""
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/ospfv3_nssa.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, topo)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen, daemons)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ result = verify_ospf6_neighbor(tgen, topo)
+ assert result is True, "setup_module: Failed \n Error:" " {}".format(result)
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment.
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+# ##################################
+# Test cases start here.
+# ##################################
+
+
+def test_ospfv3_bit_mismatch(request):
+ """OSPF verify E-bit and N-bit mismatch."""
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ global topo
+ step("Bring up the base config as per the topology")
+ reset_config_on_routers(tgen)
+
+ input_dict = {"r3": {"ospf6": {"neighbors": []}}}
+
+ step("Configure r3 as stub router")
+ stub = {"r3": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "stub"}]}}}
+ result = create_router_ospf(tgen, topo, stub)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+ # Verify r3 lost its adjacency with r2 due to E-bit mismatch
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3", input_dict=input_dict)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ step("Configure r2 as stub router")
+ stub = {"r2": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "stub"}]}}}
+ result = create_router_ospf(tgen, topo, stub)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+ # Verify r3 has an adjacency up with r2 again
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3")
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ step("Configure r3 as NSSA router")
+ nssa = {"r3": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "nssa"}]}}}
+ result = create_router_ospf(tgen, topo, nssa)
+ # Verify r3 lost its adjacency with r2 due to N-bit mismatch
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3", input_dict=input_dict)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ step("Configure r2 as NSSA router")
+ nssa = {"r2": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "nssa"}]}}}
+ result = create_router_ospf(tgen, topo, nssa)
+ # Verify r3 has an adjacency up with r2 again
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3")
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/pim_basic/mcast-rx.py b/tests/topotests/pim_basic/mcast-rx.py
index 862ad46af4..885337666a 100755
--- a/tests/topotests/pim_basic/mcast-rx.py
+++ b/tests/topotests/pim_basic/mcast-rx.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# mcast-rx.py
#
diff --git a/tests/topotests/pim_basic/mcast-tx.py b/tests/topotests/pim_basic/mcast-tx.py
index 87038ad5cf..88c234573f 100755
--- a/tests/topotests/pim_basic/mcast-tx.py
+++ b/tests/topotests/pim_basic/mcast-tx.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# mcast-tx.py
#
diff --git a/tools/coccinelle/json_object_string_addf_inet_ntop.cocci b/tools/coccinelle/json_object_string_addf_inet_ntop.cocci
new file mode 100644
index 0000000000..d9f92e564c
--- /dev/null
+++ b/tools/coccinelle/json_object_string_addf_inet_ntop.cocci
@@ -0,0 +1,19 @@
+@@
+identifier json;
+expression family, buf, value;
+constant key, buflen;
+@@
+
+(
+-json_object_string_add(json, key, inet_ntop(AF_INET, &value, buf, sizeof(buf)));
++json_object_string_addf(json, key, "%pI4", &value);
+|
+-json_object_string_add(json, key, inet_ntop(AF_INET, &value, buf, buflen));
++json_object_string_addf(json, key, "%pI4", &value);
+|
+-json_object_string_add(json, key, inet_ntop(AF_INET6, &value, buf, sizeof(buf)));
++json_object_string_addf(json, key, "%pI6", &value);
+|
+-json_object_string_add(json, key, inet_ntop(AF_INET6, &value, buf, buflen));
++json_object_string_addf(json, key, "%pI6", &value);
+)
diff --git a/tools/coccinelle/json_object_string_addf_prefix2str.cocci b/tools/coccinelle/json_object_string_addf_prefix2str.cocci
new file mode 100644
index 0000000000..ae012b91be
--- /dev/null
+++ b/tools/coccinelle/json_object_string_addf_prefix2str.cocci
@@ -0,0 +1,16 @@
+@@
+identifier json;
+expression family, value;
+expression prefix;
+constant key;
+@@
+
+(
+-prefix2str(prefix, value, ...);
+...
+-json_object_string_add(json, key, value);
++json_object_string_addf(json, key, "%pFX", prefix);
+|
+-json_object_string_add(json, key, prefix2str(prefix, value, ...));
++json_object_string_addf(json, key, "%pFX", prefix);
+)
diff --git a/tools/coccinelle/vty_json.cocci b/tools/coccinelle/vty_json.cocci
new file mode 100644
index 0000000000..481dac5406
--- /dev/null
+++ b/tools/coccinelle/vty_json.cocci
@@ -0,0 +1,9 @@
+@@
+identifier vty;
+identifier json;
+@@
+
+-vty_out(vty, "%s\n", json_object_to_json_string_ext(json, ...));
+...
+-json_object_free(json);
++vty_json(vty, json);
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index 775611b3e3..4e2c12c4e0 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -216,7 +216,7 @@ static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp)
return NULL;
}
- p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf_id);
+ p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf->vrf_id);
if (!p) {
DEBUGD(&vrrp_dbg_zebra,
@@ -544,7 +544,7 @@ static bool vrrp_attach_interface(struct vrrp_router *r)
size_t ifps_cnt =
if_lookup_by_hwaddr(r->vmac.octet, sizeof(r->vmac.octet), &ifps,
- r->vr->ifp->vrf_id);
+ r->vr->ifp->vrf->vrf_id);
/*
* Filter to only those macvlan interfaces whose parent is the base
@@ -1083,9 +1083,9 @@ static int vrrp_socket(struct vrrp_router *r)
frr_with_privs(&vrrp_privs) {
r->sock_rx = vrf_socket(r->family, SOCK_RAW, IPPROTO_VRRP,
- r->vr->ifp->vrf_id, NULL);
+ r->vr->ifp->vrf->vrf_id, NULL);
r->sock_tx = vrf_socket(r->family, SOCK_RAW, IPPROTO_VRRP,
- r->vr->ifp->vrf_id, NULL);
+ r->vr->ifp->vrf->vrf_id, NULL);
}
if (r->sock_rx < 0 || r->sock_tx < 0) {
@@ -1102,7 +1102,7 @@ static int vrrp_socket(struct vrrp_router *r)
* Bind Tx socket to macvlan device - necessary for VRF support,
* otherwise the kernel will select the vrf device
*/
- if (r->vr->ifp->vrf_id != VRF_DEFAULT) {
+ if (r->vr->ifp->vrf->vrf_id != VRF_DEFAULT) {
frr_with_privs (&vrrp_privs) {
ret = setsockopt(r->sock_tx, SOL_SOCKET,
SO_BINDTODEVICE, r->mvl_ifp->name,
@@ -1751,7 +1751,7 @@ vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
struct interface *p;
struct vrrp_vrouter *vr;
- p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf_id);
+ p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf->vrf_id);
if (!p)
return NULL;
diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
index d7d37f1f33..4cea8ebe4a 100644
--- a/vrrpd/vrrp_zebra.c
+++ b/vrrpd/vrrp_zebra.c
@@ -34,15 +34,15 @@
static struct zclient *zclient;
-static void vrrp_zebra_debug_if_state(struct interface *ifp, vrf_id_t vrf_id,
- const char *func)
+static void vrrp_zebra_debug_if_state(struct interface *ifp, const char *func)
{
DEBUGD(&vrrp_dbg_zebra,
- "%s: %s index %d(%u) parent %d mac %02x:%02x:%02x:%02x:%02x:%02x flags %ld metric %d mtu %d operative %d",
- func, ifp->name, vrf_id, ifp->link_ifindex, ifp->ifindex,
- ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2],
- ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5],
- (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp));
+ "%s: %s index %d vrf %s(%u) parent %d mac %02x:%02x:%02x:%02x:%02x:%02x flags %ld metric %d mtu %d operative %d",
+ func, ifp->name, ifp->ifindex, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->link_ifindex, ifp->hw_addr[0], ifp->hw_addr[1],
+ ifp->hw_addr[2], ifp->hw_addr[3], ifp->hw_addr[4],
+ ifp->hw_addr[5], (long)ifp->flags, ifp->metric, ifp->mtu,
+ if_is_operative(ifp));
}
static void vrrp_zebra_debug_if_dump_address(struct interface *ifp,
@@ -82,7 +82,7 @@ static int vrrp_router_id_update_zebra(int command, struct zclient *zclient,
int vrrp_ifp_create(struct interface *ifp)
{
- vrrp_zebra_debug_if_state(ifp, ifp->vrf_id, __func__);
+ vrrp_zebra_debug_if_state(ifp, __func__);
vrrp_if_add(ifp);
@@ -91,7 +91,7 @@ int vrrp_ifp_create(struct interface *ifp)
int vrrp_ifp_destroy(struct interface *ifp)
{
- vrrp_zebra_debug_if_state(ifp, ifp->vrf_id, __func__);
+ vrrp_zebra_debug_if_state(ifp, __func__);
vrrp_if_del(ifp);
@@ -100,7 +100,7 @@ int vrrp_ifp_destroy(struct interface *ifp)
int vrrp_ifp_up(struct interface *ifp)
{
- vrrp_zebra_debug_if_state(ifp, ifp->vrf_id, __func__);
+ vrrp_zebra_debug_if_state(ifp, __func__);
vrrp_if_up(ifp);
@@ -109,7 +109,7 @@ int vrrp_ifp_up(struct interface *ifp)
int vrrp_ifp_down(struct interface *ifp)
{
- vrrp_zebra_debug_if_state(ifp, ifp->vrf_id, __func__);
+ vrrp_zebra_debug_if_state(ifp, __func__);
vrrp_if_down(ifp);
@@ -134,7 +134,7 @@ static int vrrp_zebra_if_address_add(int command, struct zclient *zclient,
if (!c)
return 0;
- vrrp_zebra_debug_if_state(c->ifp, vrf_id, __func__);
+ vrrp_zebra_debug_if_state(c->ifp, __func__);
vrrp_zebra_debug_if_dump_address(c->ifp, __func__);
vrrp_if_address_add(c->ifp);
@@ -160,7 +160,7 @@ static int vrrp_zebra_if_address_del(int command, struct zclient *client,
if (!c)
return 0;
- vrrp_zebra_debug_if_state(c->ifp, vrf_id, __func__);
+ vrrp_zebra_debug_if_state(c->ifp, __func__);
vrrp_zebra_debug_if_dump_address(c->ifp, __func__);
vrrp_if_address_del(c->ifp);
@@ -175,8 +175,8 @@ void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable)
"Requesting Zebra to turn router advertisements %s for %s",
r->vr->vrid, enable ? "on" : "off", r->mvl_ifp->name);
- zclient_send_interface_radv_req(zclient, r->mvl_ifp->vrf_id, r->mvl_ifp,
- enable, VRRP_RADV_INT);
+ zclient_send_interface_radv_req(zclient, r->mvl_ifp->vrf->vrf_id,
+ r->mvl_ifp, enable, VRRP_RADV_INT);
}
void vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
@@ -185,7 +185,7 @@ void vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
VRRP_LOGPFX "Requesting Zebra to set %s protodown %s", ifp->name,
down ? "on" : "off");
- zclient_send_interface_protodown(zclient, ifp->vrf_id, ifp, down);
+ zclient_send_interface_protodown(zclient, ifp->vrf->vrf_id, ifp, down);
}
static zclient_handler *const vrrp_handlers[] = {
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index b719987666..b9577ccd8c 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1279,6 +1279,7 @@ static struct cmd_node bgp_vpnv4_node = {
.node = BGP_VPNV4_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_vpnv6_node = {
@@ -1286,6 +1287,7 @@ static struct cmd_node bgp_vpnv6_node = {
.node = BGP_VPNV6_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_flowspecv4_node = {
@@ -1293,6 +1295,7 @@ static struct cmd_node bgp_flowspecv4_node = {
.node = BGP_FLOWSPECV4_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_flowspecv6_node = {
@@ -1300,6 +1303,7 @@ static struct cmd_node bgp_flowspecv6_node = {
.node = BGP_FLOWSPECV6_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv4_node = {
@@ -1307,6 +1311,7 @@ static struct cmd_node bgp_ipv4_node = {
.node = BGP_IPV4_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv4m_node = {
@@ -1314,6 +1319,7 @@ static struct cmd_node bgp_ipv4m_node = {
.node = BGP_IPV4M_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv4l_node = {
@@ -1321,6 +1327,7 @@ static struct cmd_node bgp_ipv4l_node = {
.node = BGP_IPV4L_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv6_node = {
@@ -1328,6 +1335,7 @@ static struct cmd_node bgp_ipv6_node = {
.node = BGP_IPV6_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_ipv6m_node = {
@@ -1335,6 +1343,7 @@ static struct cmd_node bgp_ipv6m_node = {
.node = BGP_IPV6M_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_evpn_node = {
@@ -1342,6 +1351,7 @@ static struct cmd_node bgp_evpn_node = {
.node = BGP_EVPN_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
static struct cmd_node bgp_evpn_vni_node = {
@@ -1356,6 +1366,7 @@ static struct cmd_node bgp_ipv6l_node = {
.node = BGP_IPV6L_NODE,
.parent_node = BGP_NODE,
.prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
};
#ifdef ENABLE_BGP_VNC
@@ -1516,6 +1527,7 @@ struct cmd_node link_params_node = {
.node = LINK_PARAMS_NODE,
.parent_node = INTERFACE_NODE,
.prompt = "%s(config-link-params)# ",
+ .no_xpath = true,
};
#ifdef HAVE_BGPD
@@ -2134,7 +2146,7 @@ DEFUNSH(VTYSH_PATHD, pcep_cli_pcep_pce_config, pcep_cli_pcep_pce_config_cmd,
#endif /* HAVE_PATHD */
DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
- "route-map WORD <deny|permit> (1-65535)",
+ "route-map RMAP_NAME <deny|permit> (1-65535)",
"Create route-map or enter route-map command mode\n"
"Route map tag\n"
"Route map denies set operations\n"
@@ -3007,6 +3019,60 @@ DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
return CMD_SUCCESS;
}
+DEFUN(vtysh_debug_uid_backtrace,
+ vtysh_debug_uid_backtrace_cmd,
+ "[no] debug unique-id UID backtrace",
+ NO_STR
+ DEBUG_STR
+ "Options per individual log message, by unique ID\n"
+ "Log message unique ID (XXXXX-XXXXX)\n"
+ "Add backtrace to log when message is printed\n")
+{
+ unsigned int i, ok = 0;
+ int err = CMD_SUCCESS, ret;
+ const char *uid;
+ char line[64];
+
+ if (!strcmp(argv[0]->text, "no")) {
+ uid = argv[3]->arg;
+ snprintfrr(line, sizeof(line),
+ "no debug unique-id %s backtrace", uid);
+ } else {
+ uid = argv[2]->arg;
+ snprintfrr(line, sizeof(line), "debug unique-id %s backtrace",
+ uid);
+ }
+
+ for (i = 0; i < array_size(vtysh_client); i++)
+ if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
+ ret = vtysh_client_execute(&vtysh_client[i], line);
+ switch (ret) {
+ case CMD_SUCCESS:
+ ok++;
+ break;
+ case CMD_ERR_NOTHING_TODO:
+ /* ignore this daemon
+ *
+ * note this doesn't need to handle instances
+ * of the same daemon individually because
+ * the same daemon will have the same UIDs
+ */
+ break;
+ default:
+ if (err == CMD_SUCCESS)
+ err = ret;
+ break;
+ }
+ }
+
+ if (err == CMD_SUCCESS && !ok) {
+ vty_out(vty, "%% no running daemon recognizes unique-ID %s\n",
+ uid);
+ err = CMD_WARNING;
+ }
+ return err;
+}
+
DEFUNSH(VTYSH_ALL, vtysh_service_password_encrypt,
vtysh_service_password_encrypt_cmd, "service password-encryption",
"Set up miscellaneous service\n"
@@ -4430,6 +4496,8 @@ void vtysh_init_vty(void)
install_element(CONFIG_NODE, &vtysh_debug_all_cmd);
install_element(ENABLE_NODE, &vtysh_debug_memstats_cmd);
install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd);
+ install_element(ENABLE_NODE, &vtysh_debug_uid_backtrace_cmd);
+ install_element(CONFIG_NODE, &vtysh_debug_uid_backtrace_cmd);
/* northbound */
install_element(ENABLE_NODE, &show_config_running_cmd);
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 7d66319669..936cb70622 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -433,6 +433,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
config = config_get(SEGMENT_ROUTING_NODE, line);
else if (strncmp(line, "bfd", strlen("bfd")) == 0)
config = config_get(BFD_NODE, line);
+ else if (strncmp(line, "rpki", strlen("rpki")) == 0)
+ config = config_get(RPKI_NODE, line);
else {
if (strncmp(line, "log", strlen("log")) == 0
|| strncmp(line, "hostname", strlen("hostname")) == 0
diff --git a/yang/confd/confd.frr-ripd.yang b/yang/confd/confd.frr-ripd.yang
index 9b21c0756f..7bbe54cca9 100644
--- a/yang/confd/confd.frr-ripd.yang
+++ b/yang/confd/confd.frr-ripd.yang
@@ -11,8 +11,10 @@ module confd.frr-ripd {
tailf:annotate-module "frr-ripd" {
tailf:annotate-statement "container[name='ripd']" {
- tailf:annotate-statement "container[name='state']" {
- tailf:callpoint "state";
+ tailf:annotate-statement "list[name='instance']" {
+ tailf:annotate-statement "container[name='state']" {
+ tailf:callpoint "state";
+ }
}
}
tailf:annotate-statement "rpc[name='clear-rip-route']" {
diff --git a/yang/confd/confd.frr-ripngd.yang b/yang/confd/confd.frr-ripngd.yang
index 5d876ff4d3..83383fb454 100644
--- a/yang/confd/confd.frr-ripngd.yang
+++ b/yang/confd/confd.frr-ripngd.yang
@@ -11,8 +11,10 @@ module confd.frr-ripngd {
tailf:annotate-module "frr-ripngd" {
tailf:annotate-statement "container[name='ripngd']" {
- tailf:annotate-statement "container[name='state']" {
- tailf:callpoint "state";
+ tailf:annotate-statement "list[name='instance']" {
+ tailf:annotate-statement "container[name='state']" {
+ tailf:callpoint "state";
+ }
}
}
tailf:annotate-statement "rpc[name='clear-ripng-route']" {
diff --git a/yang/frr-bgp-bmp.yang b/yang/frr-bgp-bmp.yang
index 2417874ea0..cf945cabef 100644
--- a/yang/frr-bgp-bmp.yang
+++ b/yang/frr-bgp-bmp.yang
@@ -13,6 +13,8 @@ submodule frr-bgp-bmp {
prefix frr-bt;
}
+ include "frr-bgp-common-multiprotocol";
+
organization
"FRRouting";
contact
diff --git a/yang/frr-bgp-common-structure.yang b/yang/frr-bgp-common-structure.yang
index 2ad22a1435..3378c10c03 100644
--- a/yang/frr-bgp-common-structure.yang
+++ b/yang/frr-bgp-common-structure.yang
@@ -25,6 +25,8 @@ submodule frr-bgp-common-structure {
prefix frr-bt;
}
+ include "frr-bgp-common";
+
organization
"FRRouting";
contact
diff --git a/yang/frr-bgp-neighbor.yang b/yang/frr-bgp-neighbor.yang
index 03af643ba2..6d73580661 100644
--- a/yang/frr-bgp-neighbor.yang
+++ b/yang/frr-bgp-neighbor.yang
@@ -5,6 +5,10 @@ submodule frr-bgp-neighbor {
prefix "bgp";
}
+ include "frr-bgp-common-multiprotocol";
+
+ include "frr-bgp-common-structure";
+
organization
"FRRouting";
contact
diff --git a/yang/frr-bgp-peer-group.yang b/yang/frr-bgp-peer-group.yang
index 80c9ecff2a..15c31bf010 100644
--- a/yang/frr-bgp-peer-group.yang
+++ b/yang/frr-bgp-peer-group.yang
@@ -13,6 +13,10 @@ submodule frr-bgp-peer-group {
prefix frr-bt;
}
+ include "frr-bgp-common-structure";
+
+ include "frr-bgp-neighbor";
+
organization
"FRRouting";
contact
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
index c4eb78608b..1e8c04bc6f 100644
--- a/yang/frr-route-map.yang
+++ b/yang/frr-route-map.yang
@@ -106,6 +106,18 @@ module frr-route-map {
"Match an IPv6 prefix-list";
}
+ identity ipv6-next-hop-list {
+ base rmap-match-type;
+ description
+ "Match an IPv6 next-hop";
+ }
+
+ identity ipv6-next-hop-prefix-list {
+ base rmap-match-type;
+ description
+ "Match an IPv6 next-hop prefix list";
+ }
+
identity ipv6-next-hop-type {
base rmap-match-type;
description
@@ -200,6 +212,8 @@ module frr-route-map {
+ "derived-from-or-self(../condition, 'ipv4-next-hop-list') or "
+ "derived-from-or-self(../condition, 'ipv4-next-hop-prefix-list') or "
+ "derived-from-or-self(../condition, 'ipv6-address-list') or "
+ + "derived-from-or-self(../condition, 'ipv6-next-hop-list') or "
+ + "derived-from-or-self(../condition, 'ipv6-next-hop-prefix-list') or "
+ "derived-from-or-self(../condition, 'ipv6-prefix-list')";
leaf list-name {
type filter:access-list-name;
diff --git a/yang/frr-routing.yang b/yang/frr-routing.yang
index f8441669af..6a721b2924 100644
--- a/yang/frr-routing.yang
+++ b/yang/frr-routing.yang
@@ -1,7 +1,7 @@
module frr-routing {
yang-version "1.1";
namespace "http://frrouting.org/yang/routing";
- prefix "rt";
+ prefix "frr-routing";
import ietf-yang-types {
prefix "yang";
diff --git a/yang/subdir.am b/yang/subdir.am
index a2243fb8e4..828ebd9086 100644
--- a/yang/subdir.am
+++ b/yang/subdir.am
@@ -88,6 +88,10 @@ dist_yangmodels_DATA += yang/frr-bgp-types.yang
dist_yangmodels_DATA += yang/frr-bgp.yang
endif
+if OSPFD
+dist_yangmodels_DATA += yang/frr-ospfd.yang
+endif
+
if PATHD
dist_yangmodels_DATA += yang/frr-pathd.yang
endif
@@ -97,3 +101,29 @@ CLEANFILES += \
yang/ietf/*.c \
yang/confd/*.c \
#
+
+if CONFD
+
+SUBMODULES = $(shell cd $(top_srcdir); grep -l belongs-to $(dist_yangmodels_DATA))
+EXCLUDED_MODULES = $(SUBMODULES) yang/frr-module-translator.yang
+YANG_MODULES = $(filter-out $(EXCLUDED_MODULES),$(dist_yangmodels_DATA))
+
+fxsdir = $(sysconfdir)/confd
+fxs_DATA = $(YANG_MODULES:.yang=.fxs)
+
+SUFFIXES += .fxs
+CLEANFILES += $(fxs_DATA)
+
+AM_V_CONFDC = $(AM_V_CONFDC_@AM_V@)
+AM_V_CONFDC_ = $(AM_V_CONFDC_@AM_DEFAULT_V@)
+AM_V_CONFDC_0 = @echo " CONFDC " $@;
+
+CONFDC_FLAGS = --yangpath $(srcdir)/yang --yangpath $(srcdir)/yang/ietf
+
+yang/%.fxs: yang/%.yang yang/confd/confd.%.yang
+ $(AM_V_CONFDC)$(CONFDC) $(CONFDC_FLAGS) -c -o $@ -a $(srcdir)/yang/confd/confd.$*.yang -- $<
+
+yang/%.fxs: yang/%.yang
+ $(AM_V_CONFDC)$(CONFDC) $(CONFDC_FLAGS) -c -o $@ -- $<
+
+endif
diff --git a/zebra/connected.c b/zebra/connected.c
index 80d434bafc..b261ddb791 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -73,7 +73,7 @@ static void connected_announce(struct interface *ifp, struct connected *ifc)
if (!ifc)
return;
- if (!if_is_loopback_or_vrf(ifp) && ifc->address->family == AF_INET) {
+ if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) {
if (ifc->address->prefixlen == IPV4_MAX_BITLEN)
SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
else
@@ -201,7 +201,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
- .vrf_id = ifp->vrf_id,
+ .vrf_id = ifp->vrf->vrf_id,
};
struct zebra_vrf *zvrf;
uint32_t metric;
@@ -210,12 +210,12 @@ void connected_up(struct interface *ifp, struct connected *ifc)
struct listnode *cnode;
struct connected *c;
- zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
if (!zvrf) {
flog_err(
EC_ZEBRA_VRF_NOT_FOUND,
- "%s: Received Up for interface but no associated zvrf: %d",
- __func__, ifp->vrf_id);
+ "%s: Received Up for interface but no associated zvrf: %s(%d)",
+ __func__, ifp->vrf->name, ifp->vrf->vrf_id);
return;
}
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
@@ -381,19 +381,19 @@ void connected_down(struct interface *ifp, struct connected *ifc)
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
- .vrf_id = ifp->vrf_id,
+ .vrf_id = ifp->vrf->vrf_id,
};
struct zebra_vrf *zvrf;
uint32_t count = 0;
struct listnode *cnode;
struct connected *c;
- zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
if (!zvrf) {
flog_err(
EC_ZEBRA_VRF_NOT_FOUND,
- "%s: Received Down for interface but no associated zvrf: %d",
- __func__, ifp->vrf_id);
+ "%s: Received Down for interface but no associated zvrf: %s(%d)",
+ __func__, ifp->vrf->name, ifp->vrf->vrf_id);
return;
}
@@ -491,12 +491,12 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p)
connected_withdraw(ifc);
/* Schedule LSP forwarding entries for processing, if appropriate. */
- if (ifp->vrf_id == VRF_DEFAULT) {
+ if (ifp->vrf->vrf_id == VRF_DEFAULT) {
if (IS_ZEBRA_DEBUG_MPLS)
zlog_debug(
"%u: IF %s IP %pFX address delete, scheduling MPLS processing",
- ifp->vrf_id, ifp->name, p);
- mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), p);
+ ifp->vrf->vrf_id, ifp->name, p);
+ mpls_mark_lsps_for_processing(ifp->vrf->info, p);
}
}
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 2f39284fb0..3b02128c90 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -363,8 +363,7 @@ DEFUN(fpm_show_counters_json, fpm_show_counters_json_cmd,
json_object_int_add(jo, "user-configures",
gfnc->counters.user_configures);
json_object_int_add(jo, "user-disables", gfnc->counters.user_disables);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
- json_object_free(jo);
+ vty_json(vty, jo);
return CMD_SUCCESS;
}
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index c3faf22d17..4e4ebc9cda 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -152,7 +152,7 @@ static int if_get_hwaddr(struct interface *ifp)
ifreq.ifr_addr.sa_family = AF_INET;
/* Fetch Hardware address if available. */
- ret = vrf_if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq, ifp->vrf_id);
+ ret = vrf_if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq, ifp->vrf->vrf_id);
if (ret < 0)
ifp->hw_addr_len = 0;
else {
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 187cd10e9c..1c6c70ae84 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -423,8 +423,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
/* use ioctl to get IP address of an interface */
frr_with_privs(&zserv_privs) {
sd = vrf_socket(PF_INET, SOCK_DGRAM, IPPROTO_IP,
- interface->vrf_id,
- NULL);
+ interface->vrf->vrf_id, NULL);
if (sd < 0) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Failure to read interface %s speed: %d %s",
@@ -435,7 +434,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
return 0;
}
/* Get the current link state for the interface */
- rc = vrf_ioctl(interface->vrf_id, sd, SIOCETHTOOL,
+ rc = vrf_ioctl(interface->vrf->vrf_id, sd, SIOCETHTOOL,
(char *)&ifdata);
}
if (rc < 0) {
@@ -1809,7 +1808,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifp = if_get_by_name(name, vrf_id, NULL);
} else {
/* pre-configured interface, learnt now */
- if (ifp->vrf_id != vrf_id)
+ if (ifp->vrf->vrf_id != vrf_id)
if_update_to_new_vrf(ifp, vrf_id);
}
@@ -1863,13 +1862,13 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
netlink_proc_dplane_if_protodown(ifp->info,
!!protodown);
}
- } else if (ifp->vrf_id != vrf_id) {
+ } else if (ifp->vrf->vrf_id != vrf_id) {
/* VRF change for an interface. */
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u flags 0x%x",
- name, ifp->ifindex, ifp->vrf_id, vrf_id,
- ifi->ifi_flags);
+ name, ifp->ifindex, ifp->vrf->vrf_id,
+ vrf_id, ifi->ifi_flags);
if_handle_vrf_change(ifp, vrf_id);
} else {
diff --git a/zebra/interface.c b/zebra/interface.c
index 49a1e49175..8b5dbabb92 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -584,7 +584,7 @@ void if_add_update(struct interface *ifp)
{
struct zebra_if *if_data;
struct zebra_ns *zns;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
/* case interface populate before vrf enabled */
if (zvrf->zns)
@@ -611,8 +611,8 @@ void if_add_update(struct interface *ifp)
if (IS_ZEBRA_DEBUG_KERNEL) {
zlog_debug(
"interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.",
- ifp->name, VRF_LOGNAME(zvrf->vrf),
- ifp->vrf_id, ifp->ifindex);
+ ifp->name, ifp->vrf->name,
+ ifp->vrf->vrf_id, ifp->ifindex);
}
return;
@@ -623,14 +623,14 @@ void if_add_update(struct interface *ifp)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"interface %s vrf %s(%u) index %d becomes active.",
- ifp->name, VRF_LOGNAME(zvrf->vrf), ifp->vrf_id,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ifp->ifindex);
} else {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s vrf %s(%u) index %d is added.",
- ifp->name, VRF_LOGNAME(zvrf->vrf),
- ifp->vrf_id, ifp->ifindex);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex);
}
}
@@ -769,12 +769,11 @@ void if_delete_update(struct interface *ifp)
struct zebra_if *zif;
if (if_is_up(ifp)) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
flog_err(
EC_LIB_INTERFACE,
"interface %s vrf %s(%u) index %d is still up while being deleted.",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex);
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex);
return;
}
@@ -784,13 +783,10 @@ void if_delete_update(struct interface *ifp)
/* Mark interface as inactive */
UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
- if (IS_ZEBRA_DEBUG_KERNEL) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s vrf %s(%u) index %d is now inactive.",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ifp->ifindex);
- }
/* Delete connected routes from the kernel. */
if_delete_connected(ifp);
@@ -814,7 +810,7 @@ void if_delete_update(struct interface *ifp)
* occur with this implementation whereas it is not possible with
* vrf-lite).
*/
- if (ifp->vrf_id && !vrf_is_backend_netns())
+ if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
if_handle_vrf_change(ifp, VRF_DEFAULT);
/* Reset some zebra interface params to default values. */
@@ -842,7 +838,7 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
{
vrf_id_t old_vrf_id;
- old_vrf_id = ifp->vrf_id;
+ old_vrf_id = ifp->vrf->vrf_id;
/* Uninstall connected routes. */
if_uninstall_connected(ifp);
@@ -884,7 +880,7 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
struct in6_addr *address,
int add)
{
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
struct zebra_if *zif = ifp->info;
char buf[16] = "169.254.0.1";
struct in_addr ipv4_ll;
@@ -1022,7 +1018,7 @@ void if_up(struct interface *ifp)
{
struct zebra_if *zif;
struct interface *link_if;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
zif = ifp->info;
zif->up_count++;
@@ -1086,7 +1082,7 @@ void if_down(struct interface *ifp)
{
struct zebra_if *zif;
struct interface *link_if;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifp->vrf->info;
zif = ifp->info;
zif->down_count++;
@@ -1175,7 +1171,7 @@ void zebra_if_update_all_links(struct zebra_ns *zns)
zlog_debug("bond mbr %s map to bond %d",
zif->ifp->name,
zif->bondslave_info.bond_ifindex);
- zebra_l2_map_slave_to_bond(zif, ifp->vrf_id);
+ zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
}
/* update SVI linkages */
@@ -1314,7 +1310,6 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
{
struct prefix *p;
json_object *json_addr = NULL;
- char buf[PREFIX2STR_BUFFER];
/* Print interface address. */
p = connected->address;
@@ -1322,8 +1317,7 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
if (json) {
json_addr = json_object_new_object();
json_object_array_add(json, json_addr);
- json_object_string_add(json_addr, "address",
- prefix2str(p, buf, sizeof(buf)));
+ json_object_string_addf(json_addr, "address", "%pFX", p);
} else {
vty_out(vty, " %s %pFX", prefix_family_str(p), p);
}
@@ -1331,10 +1325,8 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
/* If there is destination address, print it. */
if (CONNECTED_PEER(connected) && connected->destination) {
if (json) {
- json_object_string_add(
- json_addr, "peer",
- prefix2str(connected->destination, buf,
- sizeof(buf)));
+ json_object_string_addf(json_addr, "peer", "%pFX",
+ connected->destination);
} else {
vty_out(vty, " peer %pFX", connected->destination);
}
@@ -2062,18 +2054,14 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
vxlan_info = &zebra_if->l2info.vxl;
json_object_int_add(json_if, "vxlanId", vxlan_info->vni);
if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
- json_object_string_add(json_if, "vtepIp",
- inet_ntop(AF_INET,
- &vxlan_info->vtep_ip,
- buf, sizeof(buf)));
+ json_object_string_addf(json_if, "vtepIp", "%pI4",
+ &vxlan_info->vtep_ip);
if (vxlan_info->access_vlan)
json_object_int_add(json_if, "accessVlanId",
vxlan_info->access_vlan);
if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
- json_object_string_add(json_if, "mcastGroup",
- inet_ntop(AF_INET,
- &vxlan_info->mcast_grp,
- buf, sizeof(buf)));
+ json_object_string_addf(json_if, "mcastGroup", "%pI4",
+ &vxlan_info->mcast_grp);
if (vxlan_info->ifindex_link
&& (vxlan_info->link_nsid != NS_UNKNOWN)) {
struct interface *ifp;
@@ -2090,16 +2078,12 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
gre_info = &zebra_if->l2info.gre;
if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
- json_object_string_add(json_if, "vtepIp",
- inet_ntop(AF_INET,
- &gre_info->vtep_ip,
- buf, sizeof(buf)));
+ json_object_string_addf(json_if, "vtepIp", "%pI4",
+ &gre_info->vtep_ip);
if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
- json_object_string_add(
- json_if, "vtepRemoteIp",
- inet_ntop(AF_INET,
- &gre_info->vtep_ip_remote,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_if, "vtepRemoteIp", "%pI4",
+ &gre_info->vtep_ip_remote);
}
if (gre_info->ifindex_link
&& (gre_info->link_nsid != NS_UNKNOWN)) {
@@ -2233,9 +2217,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
json_object_double_add(json_te, "utilizedBandwidth",
iflp->use_bw);
if (IS_PARAM_SET(iflp, LP_RMT_AS))
- json_object_string_add(json_te, "neighborAsbrIp",
- inet_ntop(AF_INET, &iflp->rmt_ip,
- buf, sizeof(buf)));
+ json_object_string_addf(json_te, "neighborAsbrIp",
+ "%pI4", &iflp->rmt_ip);
json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as);
}
@@ -2361,12 +2344,8 @@ DEFPY(show_interface, show_interface_cmd,
}
}
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2408,12 +2387,8 @@ DEFPY (show_interface_vrf_all,
}
}
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2461,12 +2436,8 @@ DEFPY (show_interface_name_vrf,
else
if_dump_vty(vty, ifp);
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2526,12 +2497,8 @@ DEFPY (show_interface_name_vrf_all,
else
if_dump_vty(vty, ifp);
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (json)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2905,6 +2872,7 @@ struct cmd_node link_params_node = {
.node = LINK_PARAMS_NODE,
.parent_node = INTERFACE_NODE,
.prompt = "%s(config-link-params)# ",
+ .no_xpath = true,
};
static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
@@ -4239,7 +4207,7 @@ static int if_config_write(struct vty *vty)
if_data = ifp->info;
- if (ifp->vrf_id == VRF_DEFAULT)
+ if (ifp->vrf->vrf_id == VRF_DEFAULT)
vty_frame(vty, "interface %s\n", ifp->name);
else
vty_frame(vty, "interface %s vrf %s\n",
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 42a5bfd9db..8b30eea9f1 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -140,7 +140,7 @@ void if_get_metric(struct interface *ifp)
ifreq_set_name(&ifreq, ifp);
- if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf_id) < 0)
+ if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf->vrf_id) < 0)
return;
ifp->metric = ifreq.ifr_metric;
if (ifp->metric == 0)
@@ -158,7 +158,7 @@ void if_get_mtu(struct interface *ifp)
ifreq_set_name(&ifreq, ifp);
#if defined(SIOCGIFMTU)
- if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf_id) < 0) {
+ if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf->vrf_id) < 0) {
zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU)");
ifp->mtu6 = ifp->mtu = -1;
return;
@@ -414,7 +414,7 @@ void if_get_flags(struct interface *ifp)
ifreq_set_name(&ifreq, ifp);
- ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
+ ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
if (ret < 0) {
flog_err_sys(EC_LIB_SYSTEM_CALL,
"vrf_if_ioctl(SIOCGIFFLAGS %s) failed: %s",
@@ -443,13 +443,13 @@ void if_get_flags(struct interface *ifp)
struct if_data *ifdata = &ifdr.ifdr_data;
strlcpy(ifdr.ifdr_name, ifp->name, sizeof(ifdr.ifdr_name));
- ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifdr, ifp->vrf_id);
+ ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifdr, ifp->vrf->vrf_id);
#else
struct if_data ifd = {.ifi_link_state = 0};
struct if_data *ifdata = &ifd;
ifreq.ifr_data = (caddr_t)ifdata;
- ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreq, ifp->vrf_id);
+ ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreq, ifp->vrf->vrf_id);
#endif
if (ret == -1)
@@ -511,7 +511,7 @@ int if_set_flags(struct interface *ifp, uint64_t flags)
ifreq.ifr_flags = ifp->flags;
ifreq.ifr_flags |= flags;
- ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
+ ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
if (ret < 0) {
zlog_info("can't set interface flags");
@@ -532,7 +532,7 @@ int if_unset_flags(struct interface *ifp, uint64_t flags)
ifreq.ifr_flags = ifp->flags;
ifreq.ifr_flags &= ~flags;
- ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
+ ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
if (ret < 0) {
zlog_info("can't unset interface flags");
diff --git a/zebra/main.c b/zebra/main.c
index 038022ceb2..2a8dc39771 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -183,6 +183,9 @@ static void sigint(void)
}
}
+ if (zrouter.lsp_process_q)
+ work_queue_free_and_null(&zrouter.lsp_process_q);
+
vrf_terminate();
ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
@@ -440,8 +443,8 @@ int main(int argc, char **argv)
* we have to have route_read() called before.
*/
zrouter.startup_time = monotime(NULL);
- thread_add_timer(zrouter.master, rib_sweep_route,
- NULL, graceful_restart, NULL);
+ thread_add_timer(zrouter.master, rib_sweep_route, NULL,
+ graceful_restart, &zrouter.sweeper);
/* Needed for BSD routing socket. */
pid = getpid();
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 26f6d404e9..c59ff1bbec 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -449,8 +449,8 @@ void zebra_interface_up_update(struct interface *ifp)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s(%u)",
- ifp->name, ifp->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s vrf %s(%u)",
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
if (ifp->ptm_status || !ifp->ptm_enable) {
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode,
@@ -475,8 +475,8 @@ void zebra_interface_down_update(struct interface *ifp)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s(%u)",
- ifp->name, ifp->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s vrf %s(%u)",
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -494,8 +494,8 @@ void zebra_interface_add_update(struct interface *ifp)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s(%u)", ifp->name,
- ifp->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s vrf %s(%u)",
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -514,8 +514,8 @@ void zebra_interface_delete_update(struct interface *ifp)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s(%u)",
- ifp->name, ifp->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s vrf %s(%u)",
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -538,8 +538,8 @@ void zebra_interface_address_add_update(struct interface *ifp,
if (IS_ZEBRA_DEBUG_EVENT) {
p = ifc->address;
zlog_debug(
- "MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %pFX on %s(%u)",
- p, ifp->name, ifp->vrf_id);
+ "MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %pFX on %s vrf %s(%u)",
+ p, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
}
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
@@ -575,8 +575,8 @@ void zebra_interface_address_delete_update(struct interface *ifp,
if (IS_ZEBRA_DEBUG_EVENT) {
p = ifc->address;
zlog_debug(
- "MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %pFX on %s(%u)",
- p, ifp->name, ifp->vrf_id);
+ "MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %pFX on %s vrf %s(%u)",
+ p, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
}
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0);
@@ -607,7 +607,7 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
- ifp->name, ifp->vrf_id, new_vrf_id);
+ ifp->name, ifp->vrf->vrf_id, new_vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -634,7 +634,7 @@ void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id)
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
- ifp->name, old_vrf_id, ifp->vrf_id);
+ ifp->name, old_vrf_id, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -925,8 +925,8 @@ void zebra_interface_parameters_update(struct interface *ifp)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s(%u)",
- ifp->name, ifp->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s vrf %s(%u)",
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
diff --git a/zebra/router-id.c b/zebra/router-id.c
index ac81d537d0..ea438b4367 100644
--- a/zebra/router-id.c
+++ b/zebra/router-id.c
@@ -159,7 +159,7 @@ void router_id_add_address(struct connected *ifc)
struct prefix before;
struct prefix after;
struct zserv *client;
- struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifc->ifp->vrf->info;
afi_t afi;
struct list *rid_lo;
struct list *rid_all;
@@ -206,7 +206,7 @@ void router_id_del_address(struct connected *ifc)
struct prefix before;
struct listnode *node;
struct zserv *client;
- struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id);
+ struct zebra_vrf *zvrf = ifc->ifp->vrf->info;
afi_t afi;
struct list *rid_lo;
struct list *rid_all;
@@ -521,7 +521,7 @@ DEFUN (show_ip_router_id,
vrf_name = argv[idx]->arg;
}
- zvrf = vrf_info_get(vrf_id);
+ zvrf = vrf_info_lookup(vrf_id);
if (zvrf != NULL) {
if (is_ipv6) {
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index b3f04e421e..24c01b7f51 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -507,7 +507,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
if (index) {
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), index);
if (ifp)
- nh_vrf_id = ifp->vrf_id;
+ nh_vrf_id = ifp->vrf->vrf_id;
}
nh.vrf_id = nh_vrf_id;
@@ -581,7 +581,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
index);
if (ifp)
- nh_vrf_id = ifp->vrf_id;
+ nh_vrf_id = ifp->vrf->vrf_id;
else {
flog_warn(
EC_ZEBRA_UNKNOWN_INTERFACE,
@@ -2799,7 +2799,7 @@ static struct nexthop netlink_nexthop_process_nh(struct rtattr **tb,
if (ifp)
*ifp = ifp_lookup;
if (ifp_lookup)
- nh.vrf_id = ifp_lookup->vrf_id;
+ nh.vrf_id = ifp_lookup->vrf->vrf_id;
else {
flog_warn(
EC_ZEBRA_UNKNOWN_INTERFACE,
@@ -3503,8 +3503,8 @@ static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
zlog_debug(
"%s: Tx family %s IF %s(%u) vrf %s(%u) MAC %pEA vid %u",
__func__, nl_family_to_str(req.ndm.ndm_family),
- br_if->name, br_if->ifindex,
- vrf_id_to_name(br_if->vrf_id), br_if->vrf_id, mac, vid);
+ br_if->name, br_if->ifindex, br_if->vrf->name,
+ br_if->vrf->vrf_id, mac, vid);
return netlink_request(&zns->netlink_cmd, &req);
}
@@ -3676,7 +3676,6 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
struct interface *link_if;
struct ethaddr mac;
struct ipaddr ip;
- struct vrf *vrf;
char buf[ETHER_ADDR_STRLEN];
int mac_present = 0;
bool is_ext;
@@ -3695,7 +3694,6 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (!ifp || !ifp->info)
return 0;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
zif = (struct zebra_if *)ifp->info;
/* Parse attributes and extract fields of interest. */
@@ -3705,7 +3703,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
zlog_debug("%s family %s IF %s(%u) vrf %s(%u) - no DST",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id);
+ ndm->ndm_ifindex, ifp->vrf->name, ifp->vrf->vrf_id);
return 0;
}
@@ -3801,7 +3799,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
nl_family_to_str(
ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
- VRF_LOGNAME(vrf), ifp->vrf_id,
+ ifp->vrf->name,
+ ifp->vrf->vrf_id,
(unsigned long)RTA_PAYLOAD(
tb[NDA_LLADDR]));
return 0;
@@ -3825,8 +3824,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
"Rx %s family %s IF %s(%u) vrf %s(%u) IP %pIA MAC %s state 0x%x flags 0x%x ext_flags 0x%x",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
- &ip,
+ ndm->ndm_ifindex, ifp->vrf->name,
+ ifp->vrf->vrf_id, &ip,
mac_present
? prefix_mac2str(&mac, buf, sizeof(buf))
: "",
@@ -3861,7 +3860,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
zlog_debug("Rx %s family %s IF %s(%u) vrf %s(%u) IP %pIA",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
+ ndm->ndm_ifindex, ifp->vrf->name, ifp->vrf->vrf_id,
&ip);
/* Process the delete - it may result in re-adding the neighbor if it is
@@ -4004,7 +4003,7 @@ int netlink_neigh_read_specific_ip(const struct ipaddr *ip,
{
int ret = 0;
struct zebra_ns *zns;
- struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vlan_if->vrf_id);
+ struct zebra_vrf *zvrf = vlan_if->vrf->info;
struct zebra_dplane_info dp_info;
zns = zvrf->zns;
@@ -4014,7 +4013,7 @@ int netlink_neigh_read_specific_ip(const struct ipaddr *ip,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: neigh request IF %s(%u) IP %pIA vrf %s(%u)",
__func__, vlan_if->name, vlan_if->ifindex, ip,
- vrf_id_to_name(vlan_if->vrf_id), vlan_if->vrf_id);
+ vlan_if->vrf->name, vlan_if->vrf->vrf_id);
ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip,
vlan_if->ifindex);
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index ab3e55d100..350b97cc5d 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -99,7 +99,7 @@ static struct zebra_vrf *rtadv_interface_get_zvrf(const struct interface *ifp)
if (!vrf_is_backend_netns())
return vrf_info_lookup(VRF_DEFAULT);
- return vrf_info_lookup(ifp->vrf_id);
+ return ifp->vrf->info;
}
static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
@@ -210,12 +210,9 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
}
/* Logging of packet. */
- if (IS_ZEBRA_DEBUG_PACKET) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp->name,
- VRF_LOGNAME(vrf), ifp->ifindex, sock);
- }
+ ifp->vrf->name, ifp->ifindex, sock);
/* Fill in sockaddr_in6. */
memset(&addr, 0, sizeof(struct sockaddr_in6));
@@ -387,11 +384,9 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
sizeof(struct nd_opt_rdnss) + sizeof(struct in6_addr);
if (len + opt_len > max_len) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
zlog_warn(
"%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex);
+ ifp->name, ifp->vrf->name, ifp->ifindex);
goto no_more_opts;
}
struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
@@ -493,8 +488,9 @@ static int rtadv_timer(struct thread *thread)
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
FOR_ALL_INTERFACES (vrf, ifp) {
- if (if_is_loopback_or_vrf(ifp) || !if_is_operative(ifp)
- || (vrf_is_backend_netns() && ifp->vrf_id != zvrf->vrf->vrf_id))
+ if (if_is_loopback(ifp) || !if_is_operative(ifp)
+ || (vrf_is_backend_netns()
+ && ifp->vrf->vrf_id != zvrf->vrf->vrf_id))
continue;
zif = ifp->info;
@@ -509,17 +505,12 @@ static int rtadv_timer(struct thread *thread)
<= 0)
zif->rtadv.inFastRexmit = 0;
- if (IS_ZEBRA_DEBUG_SEND) {
- struct vrf *vrf =
- vrf_lookup_by_id(
- ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_SEND)
zlog_debug(
"Fast RA Rexmit on interface %s(%s:%u)",
ifp->name,
- VRF_LOGNAME(vrf),
+ ifp->vrf->name,
ifp->ifindex);
- }
rtadv_send_packet(zvrf->rtadv.sock, ifp,
RA_ENABLE);
@@ -619,14 +610,11 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
if (len < sizeof(struct nd_router_advert)) {
- if (IS_ZEBRA_DEBUG_PACKET) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug(
"%s(%s:%u): Rx RA with invalid length %d from %s",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, len,
+ ifp->name, ifp->vrf->name, ifp->ifindex, len,
addr_str);
- }
return;
}
@@ -634,14 +622,11 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
rtadv_process_optional(msg + sizeof(struct nd_router_advert),
len - sizeof(struct nd_router_advert),
ifp, addr);
- if (IS_ZEBRA_DEBUG_PACKET) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug(
"%s(%s:%u): Rx RA with non-linklocal source address from %s",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex,
+ ifp->name, ifp->vrf->name, ifp->ifindex,
addr_str);
- }
return;
}
@@ -719,14 +704,11 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
return;
}
- if (IS_ZEBRA_DEBUG_PACKET) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp->name,
- VRF_LOGNAME(vrf), ifp->ifindex, len, addr_str);
- }
+ ifp->vrf->name, ifp->ifindex, len, addr_str);
- if (if_is_loopback_or_vrf(ifp))
+ if (if_is_loopback(ifp))
return;
/* Check interface configuration. */
@@ -736,11 +718,9 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
/* ICMP message length check. */
if (len < sizeof(struct icmp6_hdr)) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
zlog_debug(
"%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, len);
+ ifp->name, ifp->vrf->name, ifp->ifindex, len);
return;
}
@@ -749,20 +729,16 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
/* ICMP message type check. */
if (icmph->icmp6_type != ND_ROUTER_SOLICIT
&& icmph->icmp6_type != ND_ROUTER_ADVERT) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex,
+ ifp->name, ifp->vrf->name, ifp->ifindex,
icmph->icmp6_type);
return;
}
/* Hoplimit check. */
if (hoplimit >= 0 && hoplimit != 255) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp->name,
- VRF_LOGNAME(vrf), ifp->ifindex, hoplimit);
+ ifp->vrf->name, ifp->ifindex, hoplimit);
return;
}
@@ -1295,14 +1271,12 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
zebra_route_string(client->proto));
return;
}
- if (vrf_is_backend_netns() && ifp->vrf_id != zvrf_id(zvrf)) {
- struct vrf *vrf = zvrf->vrf;
-
+ if (vrf_is_backend_netns() && ifp->vrf->vrf_id != zvrf_id(zvrf)) {
zlog_debug(
"%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
- VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
+ ifp->vrf->name, zvrf_id(zvrf), ifindex,
enable ? "enable" : "disable",
- zebra_route_string(client->proto), ifp->vrf_id);
+ zebra_route_string(client->proto), ifp->vrf->vrf_id);
return;
}
@@ -1462,7 +1436,7 @@ DEFUN (ipv6_nd_ra_fast_retrans,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on this interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1484,7 +1458,7 @@ DEFUN (no_ipv6_nd_ra_fast_retrans,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on this interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1506,7 +1480,7 @@ DEFPY (ipv6_nd_ra_hop_limit,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on this interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1529,7 +1503,7 @@ DEFPY (no_ipv6_nd_ra_hop_limit,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on this interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1551,7 +1525,7 @@ DEFPY (ipv6_nd_ra_retrans_interval,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on loopback interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1574,7 +1548,7 @@ DEFPY (no_ipv6_nd_ra_retrans_interval,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot remove IPv6 Router Advertisements on loopback interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1595,7 +1569,7 @@ DEFUN (ipv6_nd_suppress_ra,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on this interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1619,7 +1593,7 @@ DEFUN (no_ipv6_nd_suppress_ra,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- if (if_is_loopback_or_vrf(ifp)) {
+ if (if_is_loopback(ifp)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on this interface\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -2608,7 +2582,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
zif = ifp->info;
- if (!if_is_loopback_or_vrf(ifp)) {
+ if (!if_is_loopback(ifp)) {
if (zif->rtadv.AdvSendAdvertisements
&& CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
vty_out(vty, " no ipv6 nd suppress-ra\n");
@@ -2856,13 +2830,10 @@ static int if_join_all_router(int sock, struct interface *ifp)
ifp->name, ifp->ifindex, sock,
safe_strerror(errno));
- if (IS_ZEBRA_DEBUG_EVENT) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"%s(%s:%u): Join All-Routers multicast group, socket %u",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock);
- }
+ ifp->name, ifp->vrf->name, ifp->ifindex, sock);
return 0;
}
@@ -2879,22 +2850,18 @@ static int if_leave_all_router(int sock, struct interface *ifp)
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
sizeof(mreq));
- if (ret < 0) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ if (ret < 0)
flog_err_sys(
EC_LIB_SOCKET,
"%s(%s:%u): Failed to leave group, socket %u error %s",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock,
+ ifp->name, ifp->vrf->name, ifp->ifindex, sock,
safe_strerror(errno));
- }
- if (IS_ZEBRA_DEBUG_EVENT) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+ if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"%s(%s:%u): Leave All-Routers multicast group, socket %u",
- ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock);
- }
+ ifp->name, ifp->vrf->name, ifp->ifindex, sock);
+
return 0;
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 54ab0afd5c..421438a051 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -185,7 +185,7 @@ int zsend_interface_add(struct zserv *client, struct interface *ifp)
{
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf->vrf_id);
zserv_encode_interface(s, ifp);
client->ifadd_cnt++;
@@ -197,7 +197,7 @@ int zsend_interface_delete(struct zserv *client, struct interface *ifp)
{
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf->vrf_id);
zserv_encode_interface(s, ifp);
client->ifdel_cnt++;
@@ -237,7 +237,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
return 0;
}
- zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf->vrf_id);
/* Add Interface Index */
stream_putl(s, ifp->ifindex);
@@ -299,7 +299,7 @@ int zsend_interface_address(int cmd, struct zserv *client,
struct prefix *p;
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, cmd, ifp->vrf_id);
+ zclient_create_header(s, cmd, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
/* Interface address flag. */
@@ -341,7 +341,7 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client,
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
struct prefix *p;
- zclient_create_header(s, cmd, ifp->vrf_id);
+ zclient_create_header(s, cmd, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
/* Prefix information. */
@@ -459,7 +459,7 @@ int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
{
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf->vrf_id);
/* Fill in the name of the interface and its new VRF (id) */
stream_put(s, ifp->name, INTERFACE_NAMSIZ);
@@ -534,7 +534,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
{
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, cmd, ifp->vrf_id);
+ zclient_create_header(s, cmd, ifp->vrf->vrf_id);
zserv_encode_interface(s, ifp);
if (cmd == ZEBRA_INTERFACE_UP)
@@ -985,7 +985,8 @@ void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
family2addrsize(sockunion_family(&ip)));
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
- if (!vrf_bitmap_check(client->nhrp_neighinfo[afi], ifp->vrf_id))
+ if (!vrf_bitmap_check(client->nhrp_neighinfo[afi],
+ ifp->vrf->vrf_id))
continue;
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
@@ -3421,7 +3422,7 @@ static inline void zebra_gre_get(ZAPI_HANDLER_ARGS)
zebra_ns_lookup(gre_info->link_nsid),
gre_info->ifindex_link);
if (ifp_link)
- vrf_id_link = ifp_link->vrf_id;
+ vrf_id_link = ifp_link->vrf->vrf_id;
stream_putl(s, vrf_id_link);
stream_putl(s, gre_info->vtep_ip.s_addr);
stream_putl(s, gre_info->vtep_ip_remote.s_addr);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 20aa9b8432..4000272544 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -3569,9 +3569,9 @@ dplane_br_port_update(const struct interface *ifp, bool non_df,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
- ctx->zd_vrf_id = ifp->vrf_id;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
- zns = zebra_ns_lookup(ifp->vrf_id);
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
dplane_ctx_ns_init(ctx, zns, false);
ctx->zd_ifindex = ifp->ifindex;
@@ -3646,16 +3646,16 @@ static enum zebra_dplane_result intf_addr_update_internal(
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug("init intf ctx %s: idx %d, addr %u:%pFX",
- dplane_op2str(op), ifp->ifindex, ifp->vrf_id,
+ dplane_op2str(op), ifp->ifindex, ifp->vrf->vrf_id,
ifc->address);
ctx = dplane_ctx_alloc();
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
- ctx->zd_vrf_id = ifp->vrf_id;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
- zns = zebra_ns_lookup(ifp->vrf_id);
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
dplane_ctx_ns_init(ctx, zns, false);
/* Init the interface-addr-specific area */
@@ -3853,9 +3853,9 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx,
struct zebra_ns *zns;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
- ctx->zd_vrf_id = ifp->vrf_id;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
- zns = zebra_ns_lookup(ifp->vrf_id);
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
dplane_ctx_ns_init(ctx, zns, false);
strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
@@ -4078,9 +4078,9 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
- ctx->zd_vrf_id = ifp->vrf_id;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
- zns = zebra_ns_lookup(ifp->vrf_id);
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
dplane_ctx_ns_init(ctx, zns, false);
strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
@@ -4152,10 +4152,10 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
- ctx->zd_vrf_id = ifp->vrf_id;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
dplane_ctx_set_type(ctx, protocol);
- zns = zebra_ns_lookup(ifp->vrf_id);
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
dplane_ctx_ns_init(ctx, zns, false);
strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
@@ -4403,13 +4403,13 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
- zns = zebra_ns_lookup(ifp->vrf_id);
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
if (!zns)
return result;
dplane_ctx_ns_init(ctx, zns, false);
dplane_ctx_set_ifname(ctx, ifp->name);
- ctx->zd_vrf_id = ifp->vrf_id;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
ctx->zd_ifindex = ifp->ifindex;
if (ifp_link)
ctx->u.gre.link_ifindex = ifp_link->ifindex;
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index 4006e1fed5..13b9cc2002 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -152,12 +152,10 @@ void zebra_evpn_print(struct zebra_evpn *zevpn, void **ctxt)
json_object_int_add(json, "sviIfindex",
zevpn->svi_if->ifindex);
}
- json_object_string_add(json, "vtepIp",
- inet_ntop(AF_INET, &zevpn->local_vtep_ip,
- buf, sizeof(buf)));
- json_object_string_add(json, "mcastGroup",
- inet_ntop(AF_INET, &zevpn->mcast_grp,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "vtepIp", "%pI4",
+ &zevpn->local_vtep_ip);
+ json_object_string_addf(json, "mcastGroup", "%pI4",
+ &zevpn->mcast_grp);
json_object_string_add(json, "advertiseGatewayMacip",
zevpn->advertise_gw_macip ? "Yes" : "No");
json_object_string_add(json, "advertiseSviMacip",
@@ -419,10 +417,10 @@ int zebra_evpn_advertise_subnet(struct zebra_evpn *zevpn, struct interface *ifp,
apply_mask(&p);
if (advertise)
- ip_prefix_send_to_client(ifp->vrf_id, &p,
+ ip_prefix_send_to_client(ifp->vrf->vrf_id, &p,
ZEBRA_IP_PREFIX_ROUTE_ADD);
else
- ip_prefix_send_to_client(ifp->vrf_id, &p,
+ ip_prefix_send_to_client(ifp->vrf->vrf_id, &p,
ZEBRA_IP_PREFIX_ROUTE_DEL);
}
return 0;
@@ -483,7 +481,7 @@ int zebra_evpn_gw_macip_del(struct interface *ifp, struct zebra_evpn *zevpn,
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"%u:SVI %s(%u) VNI %u, sending GW MAC %pEA IP %pIA del to BGP",
- ifp->vrf_id, ifp->name, ifp->ifindex, zevpn->vni,
+ ifp->vrf->vrf_id, ifp->name, ifp->ifindex, zevpn->vni,
&n->emac, ip);
/* Remove neighbor from BGP. */
@@ -1533,7 +1531,7 @@ void zebra_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
if (!mac && !n)
return;
- zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
+ zvrf = zevpn->vxlan_if->vrf->info;
/* Ignore the delete if this mac is a gateway mac-ip */
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 6fc01925eb..e285c206b8 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -619,7 +619,6 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
struct listnode *node = NULL;
char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
- char addr_buf[PREFIX_STRLEN];
struct zebra_vrf *zvrf;
struct timeval detect_start_time = {0, 0};
char timebuf[MONOTIME_STRLEN];
@@ -658,10 +657,8 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
json_object_int_add(json_mac, "vlan", vid);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
json_object_string_add(json_mac, "type", "remote");
- json_object_string_add(
- json_mac, "remoteVtep",
- inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip,
- addr_buf, sizeof(addr_buf)));
+ json_object_string_addf(json_mac, "remoteVtep", "%pI4",
+ &mac->fwd_info.r_vtep_ip);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
json_object_string_add(json_mac, "type", "auto");
@@ -944,10 +941,8 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
"", mac->loc_seq, mac->rem_seq);
} else {
json_object_string_add(json_mac, "type", "remote");
- json_object_string_add(
- json_mac, "remoteVtep",
- inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip,
- addr_buf, sizeof(addr_buf)));
+ json_object_string_addf(json_mac, "remoteVtep", "%pI4",
+ &mac->fwd_info.r_vtep_ip);
json_object_object_add(json_mac_hdr, buf1, json_mac);
json_object_int_add(json_mac, "localSequence",
mac->loc_seq);
@@ -1882,7 +1877,7 @@ static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac,
struct zebra_vrf *zvrf;
struct zebra_evpn_es *es;
- zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
@@ -2241,7 +2236,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
zlog_debug(
" Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
"entry exists and has not changed ",
- sticky ? "sticky " : "",
+ sticky ? "sticky " : "",
macaddr, ifp->name,
ifp->ifindex, vid, zevpn->vni,
local_inactive
@@ -2486,7 +2481,7 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, struct zebra_evpn *zevpn,
ns_id_t local_ns_id = NS_DEFAULT;
struct zebra_vrf *zvrf;
- zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 3f7e6256fc..af4629e41c 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -418,12 +418,8 @@ void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail)
hash_iterate(zvrf->evpn_table, zebra_evpn_es_evi_show_one_evpn_hash_cb,
&wctx);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj, vni_t vni, int detail)
@@ -446,12 +442,8 @@ void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj, vni_t vni, int detail)
vty_out(vty, "VNI %d doesn't exist\n", vni);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
/* Initialize the ES tables maintained per-L2_VNI */
@@ -998,12 +990,8 @@ void zebra_evpn_acc_vl_show(struct vty *vty, bool uj)
hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
&wctx);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj)
@@ -1021,12 +1009,8 @@ void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj)
hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
&wctx);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid)
@@ -1045,12 +1029,8 @@ void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid)
vty_out(vty, "VLAN %u not present\n", vid);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
}
/* Initialize VLAN member bitmap on an interface. Although VLAN membership
@@ -1325,12 +1305,9 @@ static void zebra_evpn_es_l2_nh_show_entry(struct zebra_evpn_l2_nh *nh,
{
if (json_array) {
json_object *json = NULL;
- char ip_buf[INET6_ADDRSTRLEN];
json = json_object_new_object();
- json_object_string_add(json, "vtep",
- inet_ntop(AF_INET, &nh->vtep_ip, ip_buf,
- sizeof(ip_buf)));
+ json_object_string_addf(json, "vtep", "%pI4", &nh->vtep_ip);
json_object_int_add(json, "nhId", nh->nh_id);
json_object_int_add(json, "refCnt", nh->ref_cnt);
@@ -1366,12 +1343,8 @@ void zebra_evpn_l2_nh_show(struct vty *vty, bool uj)
hash_iterate(zmh_info->nh_ip_table, zebra_evpn_l2_nh_show_cb, &wctx);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
static struct zebra_evpn_l2_nh *zebra_evpn_l2_nh_find(struct in_addr vtep_ip)
@@ -3008,13 +2981,11 @@ static void zebra_evpn_es_json_vtep_fill(struct zebra_evpn_es *es,
struct listnode *node;
json_object *json_vtep_entry;
char alg_buf[EVPN_DF_ALG_STR_LEN];
- char ip_buf[INET6_ADDRSTRLEN];
for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
json_vtep_entry = json_object_new_object();
- json_object_string_add(json_vtep_entry, "vtep",
- inet_ntop(AF_INET, &es_vtep->vtep_ip,
- ip_buf, sizeof(ip_buf)));
+ json_object_string_addf(json_vtep_entry, "vtep", "%pI4",
+ &es_vtep->vtep_ip);
if (es_vtep->flags & ZEBRA_EVPNES_VTEP_RXED_ESR) {
json_object_string_add(
json_vtep_entry, "dfAlgorithm",
@@ -3222,12 +3193,8 @@ void zebra_evpn_es_show(struct vty *vty, bool uj)
RB_FOREACH(es, zebra_es_rb_head, &zmh_info->es_rb_tree)
zebra_evpn_es_show_entry(vty, es, json_array);
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
void zebra_evpn_es_show_detail(struct vty *vty, bool uj)
@@ -3248,12 +3215,8 @@ void zebra_evpn_es_show_detail(struct vty *vty, bool uj)
json_object_array_add(json_array, json);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (uj)
+ vty_json(vty, json_array);
}
void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi)
@@ -3276,12 +3239,8 @@ void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi)
}
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
}
int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp)
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index af46ea6d7a..5fb4e07665 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -923,7 +923,7 @@ void zebra_evpn_process_neigh_on_local_mac_change(struct zebra_evpn *zevpn,
struct listnode *node = NULL;
struct zebra_vrf *zvrf = NULL;
- zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
+ zvrf = zevpn->vxlan_if->vrf->info;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("Processing neighbors on local MAC %pEA %s, VNI %u",
@@ -1308,11 +1308,11 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
}
}
- zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
+ zvrf = zevpn->vxlan_if->vrf->info;
if (!zvrf) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(" Unable to find vrf for: %d",
- zevpn->vxlan_if->vrf_id);
+ zevpn->vxlan_if->vrf->vrf_id);
return -1;
}
@@ -1725,7 +1725,6 @@ void zebra_evpn_print_neigh(struct zebra_neigh *n, void *ctxt,
struct vty *vty;
char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
- char addr_buf[PREFIX_STRLEN];
const char *type_str;
const char *state_str;
bool flags_present = false;
@@ -1812,10 +1811,8 @@ void zebra_evpn_print_neigh(struct zebra_neigh *n, void *ctxt,
n->mac->es->esi_str);
} else {
if (json)
- json_object_string_add(
- json, "remoteVtep",
- inet_ntop(AF_INET, &n->r_vtep_ip,
- addr_buf, sizeof(addr_buf)));
+ json_object_string_addf(json, "remoteVtep",
+ "%pI4", &n->r_vtep_ip);
else
vty_out(vty, " Remote VTEP: %pI4\n",
&n->r_vtep_ip);
@@ -1974,10 +1971,8 @@ void zebra_evpn_print_neigh_hash(struct hash_bucket *bucket, void *ctxt)
json_object_string_add(json_row, "remoteEs",
n->mac->es->esi_str);
else
- json_object_string_add(
- json_row, "remoteVtep",
- inet_ntop(AF_INET, &n->r_vtep_ip,
- addr_buf, sizeof(addr_buf)));
+ json_object_string_addf(json_row, "remoteVtep",
+ "%pI4", &n->r_vtep_ip);
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
json_object_boolean_true_add(json_row,
"defaultGateway");
@@ -2342,7 +2337,7 @@ int zebra_evpn_neigh_del_ip(struct zebra_evpn *zevpn, const struct ipaddr *ip)
return 0;
}
- zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
+ zvrf = zevpn->vxlan_if->vrf->info;
if (!zvrf) {
zlog_debug("%s: VNI %u vrf lookup failed.", __func__,
zevpn->vni);
diff --git a/zebra/zebra_evpn_vxlan.h b/zebra/zebra_evpn_vxlan.h
index c7acd23436..3884a1e7ea 100644
--- a/zebra/zebra_evpn_vxlan.h
+++ b/zebra/zebra_evpn_vxlan.h
@@ -28,7 +28,7 @@ zebra_get_vrr_intf_for_svi(struct interface *ifp)
struct interface *tmp_if = NULL;
struct zebra_if *zif = NULL;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
assert(zvrf);
FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) {
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 420bed7064..8a9f3dffe3 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -58,7 +58,7 @@ static void map_slaves_to_bridge(struct interface *br_if, int link,
struct zebra_vrf *zvrf;
struct zebra_ns *zns;
- zvrf = zebra_vrf_lookup_by_id(br_if->vrf_id);
+ zvrf = br_if->vrf->info;
assert(zvrf);
zns = zvrf->zns;
assert(zns);
@@ -425,7 +425,7 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
zif = ifp->info;
assert(zif);
- zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
if (!zvrf)
return;
@@ -505,7 +505,7 @@ void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex,
/* Set up or remove link with master */
if (bond_ifindex != IFINDEX_INTERNAL)
- zebra_l2_map_slave_to_bond(zif, ifp->vrf_id);
+ zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
else if (old_bond_ifindex != IFINDEX_INTERNAL)
zebra_l2_unmap_slave_from_bond(zif);
}
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 00ac98cbc0..924a43049b 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -1037,6 +1037,16 @@ static void lsp_processq_del(struct work_queue *wq, void *data)
struct zebra_lsp *lsp;
struct hash *lsp_table;
struct zebra_nhlfe *nhlfe;
+ bool in_shutdown = false;
+
+ /* If zebra is shutting down, don't delete any structs,
+ * just ignore this callback. The LSPs will be cleaned up
+ * during the shutdown processing.
+ */
+ in_shutdown = atomic_load_explicit(&zrouter.in_shutdown,
+ memory_order_relaxed);
+ if (in_shutdown)
+ return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
assert(zvrf);
@@ -1504,7 +1514,6 @@ static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf,
static json_object *nhlfe_json(struct zebra_nhlfe *nhlfe)
{
- char buf[BUFSIZ];
json_object *json_nhlfe = NULL;
json_object *json_backups = NULL;
json_object *json_label_stack;
@@ -1531,15 +1540,13 @@ static json_object *nhlfe_json(struct zebra_nhlfe *nhlfe)
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- json_object_string_add(json_nhlfe, "nexthop",
- inet_ntop(AF_INET, &nexthop->gate.ipv4,
- buf, sizeof(buf)));
+ json_object_string_addf(json_nhlfe, "nexthop", "%pI4",
+ &nexthop->gate.ipv4);
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- json_object_string_add(
- json_nhlfe, "nexthop",
- inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
+ json_object_string_addf(json_nhlfe, "nexthop", "%pI6",
+ &nexthop->gate.ipv6);
if (nexthop->ifindex)
json_object_string_add(json_nhlfe, "interface",
@@ -3718,9 +3725,7 @@ void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf,
if (use_json) {
json = lsp_json(lsp);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else
lsp_print(vty, lsp);
}
@@ -3747,9 +3752,7 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
sizeof(buf)),
lsp_json(lsp));
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
struct ttable *tt;
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index b1d2f1f0b3..c237133130 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -518,7 +518,7 @@ static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt,
}
if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) {
- vrf_id = ifp->vrf_id;
+ vrf_id = ifp->vrf->vrf_id;
} else {
struct vrf *pVrf;
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
index d5083d4cbe..57276974c3 100644
--- a/zebra/zebra_pw.c
+++ b/zebra/zebra_pw.c
@@ -783,9 +783,7 @@ static void vty_show_mpls_pseudowire_detail_json(struct vty *vty)
vty_show_mpls_pseudowire(pw, json_pws);
}
json_object_object_add(json, "pw", json_pws);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
DEFUN(show_pseudowires_detail, show_pseudowires_detail_cmd,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 42fa927d9e..3df70a3b56 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1026,7 +1026,7 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
struct interface *ifp = if_lookup_by_index(
nexthop->ifindex, alternate->vrf_id);
- if (ifp && if_is_loopback_or_vrf(ifp))
+ if (ifp && if_is_loopback(ifp))
return alternate;
}
@@ -1034,7 +1034,7 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
struct interface *ifp = if_lookup_by_index(
nexthop->ifindex, current->vrf_id);
- if (ifp && if_is_loopback_or_vrf(ifp))
+ if (ifp && if_is_loopback(ifp))
return current;
}
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 4ce756c953..92a3b9424b 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -232,12 +232,11 @@ void zebra_router_terminate(void)
{
struct zebra_router_table *zrt, *tmp;
+ THREAD_OFF(zrouter.sweeper);
+
RB_FOREACH_SAFE (zrt, zebra_router_table_head, &zrouter.tables, tmp)
zebra_router_free_table(zrt);
- if (zrouter.lsp_process_q)
- work_queue_free_and_null(&zrouter.lsp_process_q);
-
work_queue_free_and_null(&zrouter.ribq);
meta_queue_free(zrouter.mq);
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 408f9cbee5..dd788216c7 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -196,6 +196,7 @@ struct zebra_router {
* Time for when we sweep the rib from old routes
*/
time_t startup_time;
+ struct thread *sweeper;
/*
* The hash of nexthop groups associated with this router
diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c
index cb1e6c4228..fe4641cd94 100644
--- a/zebra/zebra_srv6_vty.c
+++ b/zebra/zebra_srv6_vty.c
@@ -108,9 +108,7 @@ DEFUN (show_srv6_locator,
}
- vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
- JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
vty_out(vty, "Locator:\n");
vty_out(vty, "Name ID Prefix Status\n");
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 85e1a4b2bf..9c57381165 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -709,10 +709,8 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- json_object_string_add(
- json_nexthop, "ip",
- inet_ntop(AF_INET, &nexthop->gate.ipv4,
- buf, sizeof(buf)));
+ json_object_string_addf(json_nexthop, "ip", "%pI4",
+ &nexthop->gate.ipv4);
json_object_string_add(json_nexthop, "afi",
"ipv4");
@@ -729,10 +727,8 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- json_object_string_add(
- json_nexthop, "ip",
- inet_ntop(AF_INET6, &nexthop->gate.ipv6,
- buf, sizeof(buf)));
+ json_object_string_addf(json_nexthop, "ip", "%pI6",
+ &nexthop->gate.ipv6);
json_object_string_add(json_nexthop, "afi",
"ipv6");
@@ -1131,11 +1127,7 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
prefix2str(&rn->p, buf, sizeof(buf));
json_object_object_add(json, buf, json_prefix);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY
- | JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
+ vty_json(vty, json);
}
static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
@@ -1245,14 +1237,8 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
}
}
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json,
- JSON_C_TO_STRING_PRETTY
- | JSON_C_TO_STRING_NOSLASHESCAPE));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
@@ -2484,10 +2470,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(json_route_summary, "routesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_route_summary, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_route_summary);
+ vty_json(vty, json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -2635,10 +2618,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_route_summary, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_route_summary);
+ vty_json(vty, json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -3010,9 +2990,7 @@ DEFUN (show_vrf_vni,
if (uj) {
json_object_object_add(json, "vrfs", json_vrfs);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
return CMD_SUCCESS;
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 105a50e143..5ef7c9acea 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -385,10 +385,8 @@ static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
json_object_string_add(
json, "routerMac",
prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
- json_object_string_add(json, "vtepIp",
- inet_ntop(AF_INET,
- &zrmac->fwd_info.r_vtep_ip,
- buf1, sizeof(buf1)));
+ json_object_string_addf(json, "vtepIp", "%pI4",
+ &zrmac->fwd_info.r_vtep_ip);
json_object_int_add(json, "refCount",
rb_host_count(&zrmac->host_rb));
RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
@@ -680,10 +678,8 @@ static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx)
json_object_string_add(
json_rmac, "routerMac",
prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
- json_object_string_add(json_rmac, "vtepIp",
- inet_ntop(AF_INET,
- &zrmac->fwd_info.r_vtep_ip,
- buf, sizeof(buf)));
+ json_object_string_addf(json_rmac, "vtepIp", "%pI4",
+ &zrmac->fwd_info.r_vtep_ip);
json_object_object_add(
json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
json_rmac);
@@ -729,10 +725,8 @@ static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx)
json_evpn_list = json_object_new_array();
json_object_int_add(json, "vni", zl3vni->vni);
json_object_string_add(json, "type", "L3");
- json_object_string_add(
- json, "localVtepIp",
- inet_ntop(AF_INET, &zl3vni->local_vtep_ip, buf,
- sizeof(buf)));
+ json_object_string_addf(json, "localVtepIp", "%pI4",
+ &zl3vni->local_vtep_ip);
json_object_string_add(json, "vxlanIntf",
zl3vni_vxlan_if_name(zl3vni));
json_object_string_add(json, "sviIntf",
@@ -1036,9 +1030,9 @@ static int zevpn_build_hash_table_zns(struct ns *ns,
zif->brslave_info.br_if);
if (vlan_if) {
zevpn->svi_if = vlan_if;
- zevpn->vrf_id = vlan_if->vrf_id;
+ zevpn->vrf_id = vlan_if->vrf->vrf_id;
zl3vni = zl3vni_from_vrf(
- vlan_if->vrf_id);
+ vlan_if->vrf->vrf_id);
if (zl3vni)
listnode_add_sort(
zl3vni->l2vnis, zevpn);
@@ -2142,7 +2136,7 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
vlan_if = zvni_map_to_svi(vxl->access_vlan,
zif->brslave_info.br_if);
if (vlan_if)
- zevpn->vrf_id = vlan_if->vrf_id;
+ zevpn->vrf_id = vlan_if->vrf->vrf_id;
zevpn->vxlan_if = ifp;
zevpn->local_vtep_ip = vxl->vtep_ip;
@@ -2321,11 +2315,8 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
zl3vni_print_rmac(zrmac, vty, json);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
@@ -2365,11 +2356,8 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
@@ -2393,11 +2381,8 @@ void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
void *))zl3vni_print_rmac_hash_all_vni,
args);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
@@ -2438,11 +2423,8 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
zl3vni_print_nh(n, vty, json);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
@@ -2482,11 +2464,8 @@ void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
@@ -2510,11 +2489,8 @@ void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
void *))zl3vni_print_nh_hash_all_vni,
args);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2548,11 +2524,8 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
args[1] = json;
zl3vni_print(zl3vni, (void *)args);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
@@ -2639,11 +2612,8 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
json_object_int_add(json, "numArpNd", num_neigh);
hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2669,11 +2639,8 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
(void (*)(struct hash_bucket *,
void *))zevpn_print_neigh_hash_all_evpn,
args);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2700,11 +2667,8 @@ void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
(void (*)(struct hash_bucket *,
void *))zevpn_print_neigh_hash_all_evpn_detail,
args);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2741,11 +2705,8 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
zebra_evpn_print_neigh(n, vty, json);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2789,11 +2750,8 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
&wctx);
hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2855,11 +2813,8 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
hash_iterate(zevpn->neigh_table, zebra_evpn_print_dad_neigh_hash,
&wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2913,9 +2868,7 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
if (use_json) {
json_object_object_add(json, "macs", json_mac);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
}
@@ -2942,11 +2895,8 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
wctx.print_dup = print_dup;
hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -2974,11 +2924,8 @@ void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn_detail,
&wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -3004,11 +2951,8 @@ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
wctx.json = json;
hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/*
@@ -3048,11 +2992,8 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
zebra_evpn_print_mac(mac, vty, json);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
/* Print Duplicate MACs per VNI */
@@ -3106,9 +3047,7 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
if (use_json) {
json_object_object_add(json, "macs", json_mac);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
}
@@ -3448,9 +3387,7 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
json_object_int_add(json, "numMacs", wctx.count);
if (wctx.count)
json_object_object_add(json, "macs", json_mac);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
}
}
@@ -3499,11 +3436,8 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
*/
if (json_array)
json_object_array_add(json_array, json);
- else {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ else
+ vty_json(vty, json);
}
}
@@ -3570,11 +3504,8 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
zebra_evpn_mh_print(vty);
}
- if (uj) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (uj)
+ vty_json(vty, json);
}
/*
@@ -3610,11 +3541,8 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
(void (*)(struct hash_bucket *, void *))zl3vni_print_hash,
args);
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
+ if (use_json)
+ vty_json(vty, json);
}
void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
@@ -3699,12 +3627,8 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
void *))zl3vni_print_hash_detail,
&zes);
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json_array, JSON_C_TO_STRING_PRETTY));
- json_object_free(json_array);
- }
+ if (use_json)
+ vty_json(vty, json_array);
}
/*
@@ -3981,7 +3905,7 @@ int zebra_vxlan_check_readd_vtep(struct interface *ifp,
return 0;
/* Locate VRF corresponding to interface. */
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = ifp->vrf->info;
if (!zvrf)
return -1;
@@ -4703,11 +4627,11 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
zlog_debug(
"SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
ifp->name, ifp->ifindex, zevpn->vni,
- vrf_id_to_name(ifp->vrf_id));
+ ifp->vrf->name);
/* update the vrf information for l2-vni and inform bgp */
zevpn->svi_if = ifp;
- zevpn->vrf_id = ifp->vrf_id;
+ zevpn->vrf_id = ifp->vrf->vrf_id;
zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
if (zl3vni)
@@ -4749,7 +4673,8 @@ void zebra_vxlan_macvlan_down(struct interface *ifp)
zlog_debug(
"macvlan parent link is not found. Parent index %d ifp %s",
zif->link_ifindex,
- ifindex2ifname(zif->link_ifindex, ifp->vrf_id));
+ ifindex2ifname(zif->link_ifindex,
+ ifp->vrf->vrf_id));
return;
}
link_zif = link_ifp->info;
@@ -4920,8 +4845,8 @@ int zebra_vxlan_if_up(struct interface *ifp)
zif->brslave_info.br_if);
if (vlan_if) {
zevpn->svi_if = vlan_if;
- zevpn->vrf_id = vlan_if->vrf_id;
- zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
+ zevpn->vrf_id = vlan_if->vrf->vrf_id;
+ zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
if (zl3vni)
listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
}
@@ -5274,8 +5199,8 @@ int zebra_vxlan_if_add(struct interface *ifp)
zif->brslave_info.br_if);
if (vlan_if) {
zevpn->svi_if = vlan_if;
- zevpn->vrf_id = vlan_if->vrf_id;
- zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
+ zevpn->vrf_id = vlan_if->vrf->vrf_id;
+ zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
if (zl3vni)
listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
}
@@ -5284,8 +5209,7 @@ int zebra_vxlan_if_add(struct interface *ifp)
zlog_debug(
"Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
vni,
- vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
- : VRF_DEFAULT_NAME,
+ vlan_if ? vlan_if->vrf->name : VRF_DEFAULT_NAME,
ifp->name, ifp->ifindex, vxl->access_vlan,
&vxl->vtep_ip, &vxl->mcast_grp,
zif->brslave_info.bridge_ifindex);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index abb9c5ca5d..f3f69661c4 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1197,7 +1197,8 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
snprintfrr(client_string, sizeof(client_string), "%s",
zebra_route_string(client->proto));
- vty_out(vty, "%-10s%12s %12s%12s%8d/%-8d%8d/%-8d\n", client_string,
+ vty_out(vty, "%-10s%12s %12s%12s %10d/%-10d %10d/%-10d\n",
+ client_string,
zserv_time_buf(&connect_time, cbuf, ZEBRA_TIME_BUF),
zserv_time_buf(&last_read_time, rbuf, ZEBRA_TIME_BUF),
zserv_time_buf(&last_write_time, wbuf, ZEBRA_TIME_BUF),
@@ -1291,9 +1292,9 @@ DEFUN (show_zebra_client_summary,
struct zserv *client;
vty_out(vty,
- "Name Connect Time Last Read Last Write IPv4 Routes IPv6 Routes \n");
+ "Name Connect Time Last Read Last Write IPv4 Routes IPv6 Routes\n");
vty_out(vty,
- "--------------------------------------------------------------------------------\n");
+ "------------------------------------------------------------------------------------------\n");
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
zebra_show_client_brief(vty, client);